前回の実行が終わる前に次の実行時刻が来たら、どうなりますか。
何もしなければ重複して起動します。同じデータを2つのプロセスが同時に触り、二重送信や二重集計が起きます。withoutOverlapping() を付けてロックを取れば防げます。
面接官が見ているのは重複実行という定番の事故を知っているか。
これは「Laravel で定期実行を組む方法として妥当なのはどれですか。」への追撃質問です。
よくある答えと、面談でどう見られるか
- 重複して起動する。withoutOverlapping() でロックを取り、有効期限も指定する
その通りです。プロセスが異常終了するとロックが残ることがあるので、期限指定まで言えると強いです。 - 自動的にスキップされる
何もしなければ重複起動します。それが二重処理の原因になります。 - 前の実行が強制終了される
強制終了はされません。並行して走ります。 - キューに積まれて順番待ちになる
スケジューラはキューとは別の仕組みです。
面接官は何を見ているか
- デフォルトでは重複して起動すると理解している
- 二重処理による不整合の危険を指摘できた
- withoutOverlapping() による対処を挙げた
模範解答
何もしなければ重複して起動します。処理が想定より長引いたときに、同じデータを2つのプロセスが同時に触ることになり、二重送信や二重集計といった不整合が起きます。対処は withoutOverlapping() を付けること。ロックを取って、前の実行中はスキップされます。
詰めて聞かれるのはロックの寿命です。既定の有効期限は24時間なので、サーバーが落ちるなどしてロックが残ると、翌日まで実行されないままになります。withoutOverlapping(10) のように分単位で短く指定しておくのが安全です。ロックはキャッシュに置かれるので、詰まったときは schedule:clear-cache で消せます。
なお、これはあくまで同一サーバー内の重複を防ぐ仕組みです。スケジューラを複数台で動かしていると各サーバーでそれぞれ実行されるので、そちらは onOneServer で1台に絞ります。