17

作成したモデル インスタンスが、直後に開始されたセロリ タスクからクエリされたときに見つからないのはなぜですか? 例えば:

# app.views

model = Model.objects.create()    # I create my lovely model in a view
from app.tasks import ModelTask   # I import my Async celery task
ModelTask.delay(model.pk)         # I start the task

それはすべて問題ないように見えます。呼び出し後の任意の時点でクエリを実行するcreate()と、モデルがデータベースに存在するはずです。

更新 1transaction.autocommit :ビューに、Django が提供するデフォルトの動作を使用しています。

ObjectDoesNotExistただし、以下のタスクは例外をスローします。

# app.tasks

class ModelTask(Task):
    def run(self, model_pk):
        from app.models import Model
        Model.objects.get(pk=model_pk)

私のテストでは、予想どおり、model_pk正しい正の整数 ID です。

結論

ここで非同期/「別のプロセス」の問題が発生していると思いますが、それが何であるかはわかりません。私が犯している明らかな間違いがあるかのように感じたら.

create()Django のデフォルトの「自動コミット」アプローチにより、メソッドが呼び出されるとすぐに DB アクションが実行されることが保証されるため、データベース トランザクションが答えになるとは思いません。

4

2 に答える 2

7

私のコードでも同じ問題が発生しました。長い調査の結果、 @transaction.commit_on_successデコレーターを使用していたため、競合状態が発生していることがわかりました。そのため、ビューが返された後にのみトランザクションがコミットされました。セロリタスクを呼び出した後に起こっていました。

「commit_on_success」デコレーターを削除すると、すべてが期待どおりに機能し始めました。Django のデフォルトのトランザクション動作は、データベース変更操作の後にトランザクションをコミットするためです。

@transaction.commit_on_successデコレーターと同様のことを行うため、TransactionMiddleware を使用していないことを確認することもできます。引き続き使用したい場合は、ビューでセロリ タスクまたは@transaction.commit_manuallyを使用して@transaction.autocommitデコレータを使用することを検討する必要があります。

于 2013-04-12T04:34:20.573 に答える