モデルEvent
があるとします。イベントが経過したら、招待されたすべてのユーザーに通知(電子メール、プッシュなど)を送信したい。以下に沿ったもの:
_class Event(models.Model):
start = models.DateTimeField(...)
end = models.DateTimeField(...)
invited = models.ManyToManyField(model=User)
def onEventElapsed(self):
for user in self.invited:
my_notification_backend.sendMessage(target=user, message="Event has elapsed")
_
もちろん、重要な部分は、timezone.now() >= event.end
を呼び出すたびにonEventElapsed
を呼び出すことです。 end
は現在の日付から数か月先になる可能性があることに注意してください。
私はこれを行う2つの基本的な方法について考えました。
定期的なcron
ジョブ(たとえば、5分ごとなど)を使用して、過去5分以内にイベントが経過したかどうかを確認し、メソッドを実行します。
celery
を使用し、onEventElapsed
パラメーターを使用してeta
をスケジュールして、将来的に実行します(モデルsave
メソッド内で)。
オプション1を考慮すると、潜在的な解決策は_Django-celery-beat
_になります。ただし、通知を送信するために一定の間隔でタスクを実行するのは少し奇妙に思えます。さらに、私は(おそらく)それほどエレガントではない解決策になる(潜在的な)問題を思いつきました。
True
に設定されるモデルにブールフィールドを追加します。次に、オプション2にも問題があります。
celery
を使用する場合、taskID
(簡単、ofc)を保存し、日付が変更されたらタスクを取り消して、新しいタスクを発行する必要があります。しかし、私は読んだことがあります。セロリには、将来実行されるタスクを扱うときに(デザイン固有の)問題があります githubの未解決の問題 。これがどのように起こり、なぜそれが解決するのが簡単ではないのかがわかります。今、私は潜在的に私の問題を解決できるいくつかのライブラリに出会いました:
Django-celery-beat
_...の可能な使用法にもつながります... 2つのフレームワークでも、ジョブをキューに入れることはまだ可能ですか(実行時間が少し長くなりますが、数か月先にはありませんか?)apscheduler
を使用します。しかし、遠い将来に実行されるタスクを処理する方法についての情報は見つかりませんでした。私がこれに取り組む方法に根本的な欠陥はありますか?あなたが持っているかもしれないどんな入力についても嬉しいです。
通知:これは何らかの意見に基づく可能性が高いことを知っていますが、醜いまたはエレガントなものと見なされるものに関係なく、私が見逃した非常に基本的なものがあるかもしれません。
私は働いている会社でこのようなことをやっていて、解決策は非常に簡単です。
通知を送信する必要があるかどうかを確認するために1時間ごとに実行されるcron /セロリビートを用意します。次に、それらの通知を送信し、完了としてマークします。これにより、通知時間が数年先になっていても送信されます。 ETAを使用することは、非常に長い待機時間を費やす方法ではありません。キャッシュ/ amqpがデータを失う可能性があります。
必要に応じて間隔を短くできますが、重複しないようにしてください。
1時間の時間差が大きすぎる場合は、1時間ごとにスケジューラを実行してください。ロジックは次のようなものになります
その方法論を使用すると、最高の世界(etaとbeat)の両方が得られます