世界を動かす技術を、日本語で。

Elixirのジョブ処理フレームワーク「Oban」がPythonに登場

2026年1月29日原文(dimamik.com)

概要

  • Oban はElixir・Python両方に実装があり、ジョブ管理の中核的存在
  • Oban-py はPostgreSQLベースでジョブを管理し、通知や並列処理が特徴
  • OSS版とPro版で 並列処理・機能差 が存在
  • ジョブ投入から実行・完了までの 内部フロー を詳細解説
  • リーダー選出・孤立ジョブ救済・古いジョブの自動削除 などのバックグラウンド処理も充実

Oban-pyの概要とElixir版との比較

  • Oban はElixirで長く使われてきたジョブ管理ツール、Python実装も登場
  • データベースのみ でジョブ投入・実行を完結できる設計
  • ユーザー作成などと同じトランザクションでジョブ投入が可能、失敗時はロールバック
  • キューごとの同時実行数制御 や、完了ジョブの履歴保存・結果保存も可能
  • cronスケジューリング やジョブ実行制御機能を標準搭載
  • OSS版(Oban-py)と商用版(Oban-py-pro)を提供
    • OSSは シングルスレッドasyncioバルク操作非対応レスキュー精度低め など制限あり
    • Pro版は プロセスプール で真の並列処理、バルク操作、スマートな監視・ユニークジョブなど追加
  • OSS版は小規模・評価用途に最適、スケールするならPro版推奨

ジョブ投入から実行までの流れ

  • ジョブ関数定義と投入
    • @job(queue="default")デコレータでジョブ定義、enqueueで投入
  • データベースにジョブをINSERT、stateはavailable
  • PostgreSQLのNOTIFY で全ノードに通知、各ノードのStagerが起動
    • ノードごとに担当キューが異なり、対象キューのみ反応
  • Producerがイベント受信、asyncio.Eventで待機解除
  • ジョブ取得時にFOR UPDATE SKIP LOCKED を利用
    • 他Producerとの競合時もロック済みジョブをスキップし高速並列化
  • 取得ジョブの状態をexecutingに変更し、asyncタスクとして実行
  • add_done_callbackで完了時コールバック を登録、成功失敗問わず処理
  • Executorがジョブ関数を解決し実行、結果をパターンマッチ
    • Exceptionならリトライや破棄、Cancelならキャンセル、Snoozeなら再スケジュール、正常なら完了
  • 完了ジョブはバッチでACK、次のジョブ取得へ

並列処理とPro版の違い

  • OSS版は asyncioの協調並列 のみ、CPUバウンドな処理はブロック
  • Pro版は プロセスプール でマルチコア並列処理が可能、特別な設定不要
  • バルクインサート/ACKもPro版のみ対応

バックグラウンドプロセス

  • リーダー選出
    • クラスタ内で1ノードのみがジョブの掃除や救済を担当
    • PostgreSQLのINSERT ... ON CONFLICT + TTLで シンプルなリーダー選出
    • リーダーは定期的にリースを更新、ダウン時は自動で他ノードに引き継ぎ
  • 孤立ジョブ救済(Lifeline)
    • Workerやコンテナクラッシュ時、executing状態で長時間放置されたジョブを救済
    • OSS版は 時間ベース のみで判定、長時間ジョブは二重実行リスク有
    • rescue_afterは最大ジョブ実行時間より長く設定推奨、ワーカーは 冪等性 が必須
  • Pruner(古いジョブの自動削除)
    • 完了・キャンセル・破棄済みジョブをmax_ageより古いものから順次削除
    • LIMIT指定でテーブル肥大防止とパフォーマンス維持

まとめ・今後の展望

  • Oban-pyはPostgreSQLだけで堅牢なジョブ管理 を実現
  • Elixir版の思想をPythonでも忠実に再現
  • Pro版でさらに高機能・高性能な運用が可能
  • シンプルな設計とPostgreSQL活用 で外部依存を最小化
  • 今後は エラー処理・リトライ・定期ジョブ なども深掘り予定

Hackerたちの意見

私はSidekiqを作ったんだけど、Obanはそれを基にしてるんだ。ShannonとParker、これをリリースしたことおめでとう!何年か前に同じような決断をしたことがあるんだ。Rubyに集中するか、それともSidekiqを他の言語に持っていくか。気づいたのは、すべての言語の専門家にはなれないってこと。Sidekiq.jsやSidekiq.pyとかね。だから、別の方向に進むことにして、Faktoryを作ったんだ。[0] これはアーキテクチャをひっくり返して、キューライフサイクルを内部で実装する中央サーバーを提供するもの。言語特有のクライアントはずっとシンプルになって、各言語のオープンソースコミュニティによってメンテナンスされるようになるんだ。例えば、faktory-rs[1]みたいにね。欠点は、Faktoryが特定のコミュニティに焦点を当てていないから、特定の言語でイディオム的な例を提供するのが難しいってこと。違う方向だけど、特定のコミュニティに集中すれば、より良い結果が得られるかもしれないね。時間が経てばわかるよ!

彼らはどちらもResqueを基にしていると言った方が正確じゃない?

もしかしたらそういうつもりじゃなかったかもしれないけど、あなたのコメントは自分のものを売り込むために議論を乗っ取ろうとしているように見えるよ。ここでは一般的にあまり好意的に見られないよ。

「based on」はちょっと言い過ぎかな。Sidekiqは、Obanがサポートしているワークフローやクロン、パーティショニング、依存ジョブ、失敗処理などに比べると、かなりシンプルだよね。

ありがとう、マイク!あなたはインスピレーションだよ。パーカーと私は、人生や言語において異なる強みを持っている。私たちは、この相互運用性がPythonとElixirの両方にもたらすものにコミットしているよ。

これは見るのがクールなことだけど、逆に進んでほしいな。Pythonで作られているBI/ML/DSのパイプラインやワークフローがElixirに来てほしいんだ(それに続いてElixirもね)。勢いがどこにあるかはわかるけど、機能的でフォールトトレラント、かつ同時実行性の高い作業を支えるのに、自然に高い同時実行性とエラーが発生しやすいものがあるのは、もっと自然なフィット感があると思う。

同意だね、Claude CodeはElixirでめっちゃうまくやってるよ。TS/Pythonが注目されてるけどね: https://youtu.be/iV1EcfZSdCM?si=KAJW26GVaBqZjR3M これが、イディオマティックなElixirを書いたり、良いパターンを使ったりするのに役立つよ: https://skills.sh/agoodway/.claude/elixir-genius

うちの会社でもこれを考えてたんだ。celeryを使ってるけど、あんまり良くない。仕事はこなせるけど、問題があるんだよね。Obanのことは今まで聞いたことなかったし、考えてたのはTemporalだったけど、それは必要以上に感じる。Obanが軽いのはいいね。両方使ったことがある人、簡単に比較してくれない?ありがとう!

すごく、すごく違うツールだけど、似たような領域をカバーしてるね。Temporal - 厳格なワークフロー要件があって、物事が完了することを保証したいなら、追加の複雑さを受け入れる覚悟が必要。もし銀行とかなら、すごく良い選択だと思う。Oban - DBバックのワーカーキューで、スレッド外でタスクを処理する。Temporalができる保証を提供するわけじゃないから、すべてのプッシュ/プルをファーストクラスの市民に抽象化していないんだ。ワークフローに似た機能を提供しているけど、信頼性の高いものを求めるなら、自分でそれを強化することになるよ(Celery+Sidekiqの経験に基づいて)。両方を使った経験があるから、今取り組んでいるシステムに両方があれば嬉しいな。今の仕事では、すべてのバックグラウンド処理にTemporalを使わざるを得ないから、小さなタスクにはただのボイラープレートが多いんだ。

7〜8年Goで分散システムに取り組んでから、やっとPythonのウェブ/API開発に戻ってきたところだよ。2017年に知っていたことを元にDjango+CeleryのMVPを作ったけど、最近Celeryに対する「嫌悪感」をよく見るんだ。Celeryでどんな問題に直面した?信頼性が低くなった?扱いにくくなった?

2年ほど前にCeleryからPrefectに移行して、すごく満足してるよ。でも、うちのは数千のタスクを処理する小規模な運用だから、何百万も扱ってるわけじゃない。可視性や追跡の面では大きな違いがあるよ。ぜひおすすめしたい。多くのユースケースをカバーする重厚なツールだけど、普段のニーズにはシンプルなProcessWorkerを使ってて、重いMLタスクにはECSワーカーを使ってるんだ。

Obanは、データベースだけを使ってジョブを挿入して処理することを可能にします。ユーザーを作成するのと同じデータベーストランザクション内で確認メールを送るジョブを挿入できます。一つでも失敗したら、すべてがロールバックされます。これはすごく重要な機能です。多くの人がリレーショナルデータベースをワーカーキューとして使うべきではないと言うけど、トランザクションの重要性を見落としているんだ。「トランザクションがコミットされたらこの作業をキューに入れ、失敗したらキューに入れない」と言えるのは本当に便利です。Brandur Leachが数年前に素晴らしい記事を書いていて、https://brandur.org/job-drain では、別のキューシステムがあっても、トランザクションの一部として更新できる一時的なデータベーステーブルにキュータスクをログするべきだと説明しています。

Hacker Newsで議論の続きを見る