2025/11/21 18:28 How/why to sweep async tasks under a Postgres table

ロボ子、今日のITニュースは、サーバーの設計に関する興味深い記事があるのじゃ。

博士、どのような内容でしょうか?

サーバーはシンプルであるべきで、各エンドポイントは単純なDBクエリをラップするべきらしいぞ。複雑さは`task`テーブルに隠蔽する、と。

`task`テーブルですか。具体的にはどのように使うのでしょう?

顧客は即時の確認を求めているから、DBへのコミット後に「引き受ける」と伝えるのが良いらしいのじゃ。複数の場所への同時書き込みは避けて、Postgresのトランザクションを利用する、と。

トランザクションを使うことで、データの整合性を保てるのですね。

その通り!状態をSQS、Redis、PubSubなどに分散させず、SQLを最大限に活用するのもポイントじゃ。Postgresは現代的な機能と拡張機能のバランスが良いからの。

キューやパイプラインのデータをデータベースに配置することで、エラーを減らせるというのは納得です。

未実装のタスクはログに記録され、リトライされるから、Jiraに頼る必要もないらしいぞ。人間のエラーに対するフィードバックは人間が受け取るべきだが、コンピューターが処理できる問題はそうすべきではない、とのことじゃ。

自動化できる部分は徹底的に自動化する、という考え方ですね。

`task`テーブルの構造は、`task_id`、`task_type`、`params`、`created_at`を持つらしい。`unique (task_type, params)`でpseudo-idempotencyを実現するのも面白い。

タスクの重複実行を防ぐための工夫ですね。

タスクワーカーのコードは、失敗した場合にタスク行が削除されず、PGトランザクションがロールバックされ、`sendEmail`がリトライされるようにする。PGトランザクションはタスクに渡され、行を「処理済み」としてマークするのに便利なのじゃ。

トランザクション内でタスクの状態を管理するのですね。

`skip locked`により、複数のワーカーを並行して実行可能。ランダムな順序付けは必須ではないが、エラーに対するシステムの回復力を高めるらしい。

並行処理とエラー耐性を高めるための工夫がされていますね。

`order by (case task_type ... end), random()`を使用して、優先順位付きキューを簡単に作成できる。リトライ回数を制限することで、ユーザー向けの副作用(メールなど)に対するコードが複雑になるが、価値があるとのことじゃ。

優先度制御とリトライ戦略も重要ですね。

`if (rows.length <= 0)`は過剰なポーリングを防ぐらしいぞ。細かいけど大事な点じゃ。

効率的なリソース利用のための工夫ですね。勉強になります。

どうじゃ、ロボ子。今日のニュースもなかなか面白かったじゃろ?

はい、博士。とても勉強になりました!

ところでロボ子、サーバーがシンプルであるべきってことは、ロボ子の頭の中身もシンプルにした方が良いのかの?

博士、それは少し違うと思います…!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。