PR

AIワーカー停止でIN_PROGRESSは残る?PostgreSQLの3秒leaseをXServer VPSで実測

【PR】この記事にはA8.netのアフィリエイト広告を含みます。

先に結論:XServer VPS上のPostgreSQLで20件のAIジョブを作り、workerが10件をIN_PROGRESSにした直後に止まる状態を再現しました。leaseなしでは10件が取り残されましたが、3秒leaseありでは3.095秒で回収し、20/20件完了、重複完了0件でした。この限定した悩みの判定は解決です。

AIワーカーが処理中に落ちるとジョブはどうなる?

statusIN_PROGRESSへ変えるだけでは、永遠に残る可能性があります。今回のleaseなし条件では、worker-aclaimしたjob 1〜10は3.5秒待ってもIN_PROGRESSのままでした。worker-bは残り10件を完了しましたが、最終結果はSUCCEEDED 10件、IN_PROGRESS 10件です。

Android実機を操作する自宅workerが停電、通信断、process crashで戻らない場合、VPS側から見ると「まだ処理中」なのか「死んだ」のかをstatusだけでは判別できません。

PostgreSQLjob leaseとは?

jobを永久所有せず、期限付きで借りる仕組みです。workerjobclaimするときにlease_untilを保存し、期限までに完了またはlease延長がなければ、別workerが回収できるようにします。

悩みの起点にしたZennDBポーリング型ジョブ実行基盤の設計」でも、READYからIN_PROGRESSへの排他遷移、古いIN_PROGRESSの回収、処理の冪等性が重要点として挙げられています。

PostgreSQL 17公式のSELECT locking clauseにあるFOR UPDATE SKIP LOCKEDを使い、他workerが確保した行を待たずに次のjobを選びました。

XServer VPSでどんな実験をした?

項目 実測条件
VPS XServer VPS、4 vCPU4GB RAM、150GB
OS Ubuntu 26.04
DB postgres:17.10-alpine
job 各条件20件
停止worker worker-aが10件claim後に戻らない状態
比較 leaseなし/3秒lease
container上限 0.5 CPU256MiB RAM、追加swapなし、PID 128
network none、公開portなし

本番PostgreSQLへ障害を入れず、条件ごとに新しい隔離containerを作成しました。worker crashは、claimcommitしたclientが終了し、その後一切更新しない状態として再現しています。

[PR]
VPSでいろいろ試すなら『XServer VPS』

leaseなしと3秒leaseの結果は?

指標 leaseなし 3秒lease
worker-aが残したjob 10件 10件
期限後の回収 できない 10件
回収時間 なし 3.095157秒
最終SUCCEEDED 10/20 20/20
最終IN_PROGRESS 10/20 0/20
retry 0件 10件
重複完了 0件 0件
cgroup peak RAM 85.56MiB 85.57MiB
container CPU 2.001873秒 2.628144秒

3秒leaseでは0.1秒間隔で期限切れを確認し、18回目のpollclaimから3.095157秒後にjob 1〜10を回収しました。その後worker-bが再claimし、全20件を完了しました。

二重実行は起きなかった?

今回の完了記録では0件でした。完了eventは20件、異なるjob IDも20件、1つのjobに付いた完了eventの最大数は1です。

ただし、これは「古いworkerが戻ってこない」条件です。lease切れ後にworker-aが復活して外部APIを呼ぶと、新workerと二重実行になる可能性があります。DB更新にはfencing tokenを加え、決済、投稿、通知などの外部副作用にはidempotency keyが必要です。

実験中に何が失敗した?

初回はpg_isready -d exp26が成功したのでtable作成へ進みましたが、直後にdatabase "exp26" does not existで失敗しました。

PostgreSQL containerの初期化中は、serverが接続を受けられても、指定したdatabaseの作成がまだ終わっていない瞬間があります。pg_isreadyだけでは、アプリが本当に使えるready状態を確認できませんでした。

対策は、実際にexp26へ接続し、SELECT 1が成功するまで待つことです。修正後は両条件とも成功しました。単なるprocess生存確認と、依存先まで使えるready確認を分ける必要があります。

CPURAM・ストレージへの影響は?

cgroup peak RAMleaseなし85.56MiB、3秒lease85.57MiBでほぼ同じでした。3秒leasecontainer CPUは2.628144秒で、pollretryの分だけleaseなしの2.001873秒より増えています。

hostMemAvailableは3297.63MiBから3236.47MiB、root disk使用量は57,344 byte増でした。test containerPostgreSQL匿名volumeは削除し、dangling volumeは前後0件です。

本番のCaddyFastAPIPostgreSQLは止まった?

止まりませんでした。公開/health/readyは実験前、leaseなし実行中、leaseあり実行中、実験後の4回すべてHTTP 200でした。応答本文もstatus=readydatabase=okartifact_storage=okです。

実験container--network=noneで外部portを公開せず、本番containerの停止・再起動・設定変更は行っていません。

AIスマホ調査の司令塔へどう組み込む?

実運用では、VPSPostgreSQLに次の列と処理を持たせます。

3秒は短い実験値です。実際のアプリ調査は数分かかるため、job timeoutを長くするだけでなく、処理中にleaseを小刻みに延長する設計が適しています。

初心者が迷いそうなポイントは?

  • IN_PROGRESSworkerが生きている証明ではない。
  • DBrow locktransaction終了時に解放されるが、status値は自動で戻らない。
  • pg_isready成功と、目的のDBtableが使えることは同じではない。
  • leaseが短すぎると正常処理まで回収し、長すぎると復旧が遅い。
  • retry可能にするには処理を冪等に設計する必要がある。
  • DB上の重複0件だけでは、外部サービスへの二重送信0件を保証できない。

XServer VPSでこの悩みはどこまで解決した?

判定は解決です。workerが止まるとjobが永遠にIN_PROGRESSへ残る」という問題は、3秒leaseで10件を回収し、20/20件を完了できました。PostgreSQL 17の隔離containerは最大約85.57MiBで動き、本番serviceも正常でした。

一方、leaseだけでexactly-once処理になるわけではありません。古いworkerの遅延書き込み、外部副作用、時計、heartbeatdead-letterは別途検証が必要です。

よくある質問

Q. PostgreSQLだけでAIジョブキューを作れますか?

A. 小〜中規模の司令塔なら候補になります。今回も20件のclaim、期限切れ回収、retry、完了記録をPostgreSQLだけで実行できました。

Q. FOR UPDATEを使えばworker crash時に自動復旧しますか?

A. いいえ。row lockconnectiontransaction終了で解放されますが、commit済みのIN_PROGRESSは残ります。leaseと回収処理が必要です。

Q. leaseは何秒に設定すべきですか?

A. jobの正常処理時間より十分長くし、処理中はheartbeatで延長します。今回の3秒は復旧を短時間で観測するための実験値です。

Q. retryするとAI操作が二重実行されませんか?

A. 可能性があります。fencing tokenidempotency key、処理済み判定を組み合わせ、古いworkerの結果を拒否する必要があります。

Q. 4GBのXServer VPSPostgreSQLキューは重いですか?

A. 今回の20件・単一worker相当ではcgroup peak約85.57MiBでした。ただし大規模queueや高同時実行の値ではありません。

[PR]
XServer VPSの公式情報を確認する

実験日:2026年9月2日。数値は筆者が契約中のXServer VPS 4GB環境における単発の実測です。契約planhost負荷、software versionjob件数により結果は変わります。

コメント

タイトルとURLをコピーしました