2012-05-07 10 views
0

時間予算を保持するモデル(PurchaseOrder - 略語PO)があります。ユーザーはこの予算に時間レコードを追加することができ、各時間レコードによって残りの予算が削減されます。Django 1.1シグナル - スレッドでの奇妙なタイミングの問題

残りの予算を更新するための信号を実装しました。 1時間のレコードを追加すると、それに応じて予算が削減されます。計算には時間がかかる可能性があるため、このタスクにスレッドを使用しました。

def update_po_remaining_value(sender, instance, **kwargs): 
    CalculatePOThread(sender, instance).start() 
post_save.connect(update_po_remaining_value, sender=HourRecord)  
post_delete.connect(update_po_remaining_value, sender=HourRecord) 

スレッドCalculatePOThreadが、これは完全に正常に動作時間のレコードセットを取得し、私のdev.workspaceでの予算から

hr_set = HourRecord.objects.filter(purchase_order = po) 

を設定し、総時間の記録を控除経由して、残りのPO予算値を計算しています。プロダクションでは、post_save接続もうまくいきますが、post_delete信号で奇妙な問題が発生しています。 HourRecord.objects.filter(purchase_order = po)というクエリによって返された時間レコードの合計には、CalculatePOThreadスレッドをトリガした削除された時間レコードがまだ含まれていることがよくあります。

何とか私は、クエリを実行する前にスレッドに6秒の遅延を追加することで、この動作を回避しました。 time.sleep(6)。

誰でもこのような状況が発生する理由を知っていますか?レコードが実際にデータベースから削除される前に、post_deleteシグナルがトリガされたようです。しかし、これはDjangoのバグであり、これは私の最後の推測だろう。

答えて

1

難しいとは言えませんが、私の推測ではスレッドセーフの問題が発生していると思います。長時間実行されるタスクを処理するためにスレッドを生成するときは、完了しようとしている間に、同様のスレッドが同じタスクで簡単に実行される可能性があることに注意する必要があります。一般に、スレッドで作業する場合、フットプリントを最小限に抑えたい、言い換えれば、データベースの状態などに大きく依存しないようにする必要があります。

データベースアクセスがこの場合にはである場合、データベースが同時に混乱しないようにロックを設定する必要があります。あなたがDjango 1.1を実行している場合、これははるかに難しくなります。 Django 1.1でテーブルレベルのロックを達成するには、実行しているデータベースサーバに依存することになり、独自の質問が必要です。

+0

あなたの答えをありがとう。 1つの追加情報:私はprod.envで迷っているのを確認しました。 1つずつpost.delete信号をトリガします。したがって私は他のスレッドが私のテストと競合していないことを保証しました。したがって、ロックはobject deleteコマンドによって設定されるべきであり、post_deleteシグナルは、ロックが解放された後、またはオブジェクトが削除された後にのみトリガされるべきである。しかし、それは私が影響を与えることができないDjango内部のものだと思います。 PS:DB = postgres、webserver = apache。 –

+0

もこの問題のようです:http://groups.google.com/group/django-haystack/browse_thread/thread/c452da9acfc04c64?pli=1 –