総括
- 私は中規模のdjangoプロジェクトを持っています
- (DB とは対照的に) メモリ内に多数のプレフィックス ツリーがあります。
- これらのツリーのノードは、タイムアウトの対象となるエンティティ/オブジェクトを表します。つまり、さまざまな時点でこれらのノードをタイムアウトにする必要があります
デザイン:
- 基本的に、リセット可能なワンショット タイマーを起動し、関連付けて、タイマーを作成するエンティティ (この場合はツリーのノード) に対して何らかの操作を実行できるコールバックを提供できるようにするタイマー コンストラクトが必要でした。
さまざまなオプションを調べた後、ネイティブに使用できるものは見つかりませんでした (django アプリなど)。Python の Timer オブジェクトは、スケーリング/実行されないため、これには適していません。したがって、以下に基づいて独自のタイマーを作成することにしました。
- タイム ホライズンを保持するタイム デルタ オブジェクトのソートされたリスト
- 「ダニ」をトリガーするメカニズム
実装の選択肢:
- ソートされたデルタ リストの Bisect のラッパーを使用しました: http://code.activestate.com/recipes/577197-sortedcollection/
- 目盛りを提供するためにセロリを使用しました-1分の粒度で、ワーカーはタイマークラスによって提供される timer_tick 関数をトリガーします。timer_tick は基本的に、ソートされたリストを通過し、ティックごとにヘッド ノードをデクリメントする必要があります。次に、いずれかのノードが 0 になった場合、コールバックを開始し、ソート済みタイマー リストからそれらのノードを削除します。
- タイマーを作成するには、オブジェクトの ID を返す Timer オブジェクトをインスタンス化する必要があります。この ID は db に格納され、タイマーを作成するエンティティを表す DB のエントリに関連付けられます
追加のデータ構造: Timer インスタンス (タイマーの作成ごとにインスタンス化される) を追跡するために、id を obj にマップする WeakRef ディクショナリがあります。
したがって、基本的に、メインの Django プロジェクトのメモリには 2 つのデータ構造があります。
問題文:
セロリ ワーカーはタイマー リストを調べ、id2obj マップを潜在的に変更する必要があるため、セロリ ワーカーとメインの間で状態を共有する方法を見つける必要があるようです。
SO/Google を調べたところ、次の提案が見つかりました
- マネジャー
- 共有メモリ
残念ながら、bisect ラッパーは、ピクルス化や状態共有にはあまり適していません。辞書を作成し、並べ替えられたリストを辞書内に埋め込もうとすることで、マネージャーのアプローチを試みました..エラーが発生しました(並べ替えられたリストによって保持されているメモリは共有されておらず、" shared" メモリ オブジェクトは機能しません)
最後に...質問:
- SortedCollection と Weakref Dict をワーカー スレッドと共有する方法はありますか
代替ソリューション:
ワーカースレッドをシンプルに保つのはどうですか...ティックごとにDBに書き込み、ポストDbシグナルを使用してメインで通知を受け取り、メインで期限切れのタイマーの処理を実行します。もちろん、短所は、並列化が失われることです。