I would like my cached methods to never return expired values and block wait instead.

オープン
#264 コメント 4 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
35/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
python
領域
backend

調査の方向性

dogpile/cache/region.py のリンク先の 954-958 行から始め、別のプロセスが置き換えを作成している間に期限切れの値がどのように処理されるかを追跡します。提供された multiprocessing の再現コードを使って、現在の挙動を確認します。完了条件は、並行して呼び出した側が期限切れの値を受け取るのではなく更新された値を待機し、再現コードで両方の呼び出しが新しい値を返すことです。

索引モデルが issue の本文から書いたものです。

説明

Hello,

I have a multiproces/thread scenario where my cached function can be called at the same time.

I end up falling into the scenario of
https://github.com/sqlalchemy/dogpile.cache/blob/de85b101f864bd0f5f3ba97dc96950b94f143d82/dogpile/cache/region.py#L954-L958

So what I have is an expired value in the cache.
Thread 1 retrieves it, notices it's expired, starts creating a new value, and will return the new value.
Meanwhile; Thread 2 retrieves it, notices it's expired, notices thread 1 is busy creating and returns the old value.

But the old value is entirely useless for my case. It's expired for a reason. Is there a way to configure the cache region to never return expired values and just block/wait for creation instead. Just like a cache miss?

(simplified) Code to reproduce my issue:

import os
import time
from multiprocessing import Process

from dogpile.cache import make_region

cache_region = make_region()
cache_region.configure(
    "dogpile.cache.dbm",
    expiration_time=1,
    arguments={
        "filename": "/tmp/cache.dbm",
    },
)


@cache_region.cache_on_arguments()
def get_value():
    print(os.getpid(), "Making new value...")
    time.sleep(2)
    return f"Got value {time.time():.0f}"


def run():
    print(os.getpid(), get_value())


print("3 sync calls in a row (value should be made once):")
run()
run()
run()

processes = []
for i in range(2):
    process = Process(target=run)
    processes.append(process)

time.sleep(2)
print()
print("2 async calls after cache expired (value should be made once) and be different from the previous:")
for process in processes:
    process.start()
for process in processes:
    process.join()

Example output:

3 sync calls in a row (value should be made once):
103954 Making new value...
103954 Got value 1740579012
103954 Got value 1740579012
103954 Got value 1740579012

2 async calls after cache expired (value should be made once) and be different from the previous:
103978 Got value 1740579012
103977 Making new value...
103977 Got value 1740579016

In the above output, the line 103978 Got value 1740579012 is bad for me. That should never return an expired value.

主要言語
Python
スター
301
フォーク
51
PR マージ指標
30日以内にマージされた PR はありません

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

sqlalchemy/dogpile.cache のほかの issue

sqlalchemy/dogpile.cache の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。