コンピュートユニット
Wippyはコードを実行する3つの方法を提供します:関数、プロセス、ワークフロー。これらは同じ基盤メカニズムを共有しますが、存続期間、状態の保存場所、障害発生時の動作が異なります。
関数
関数は最もシンプルなモデルです。呼び出すと実行され、結果を返します。呼び出し間で状態は永続化されません。
local result = funcs.call("app.math:add", 2, 3)
関数は呼び出し元のコンテキストで実行されます。呼び出し元がキャンセルまたは終了すると、実行中の関数もキャンセルされます。これにより、クリーンアップについて考える必要がなくなり、シンプルになります。
プロセス
プロセスはアクターです。複数のメッセージにわたって状態を維持し、開始した人とは独立して実行され、メッセージパッシングを通じて通信します。
local pid = process.spawn("app.workers:handler", "app:processes")
process.send(pid, "job", {task = "process_data"})
プロセスを生成すると、コードが終了した後も実行を継続します。プロセスは互いにモニタリングしたり、リンクしたり、失敗した子を自動的に再起動するスーパービジョンツリーを形成できます。
スケジューラはワーカープール上で数千のプロセスを多重化します。各プロセスはI/O待機時にyieldし、他のプロセスの実行を許可します。
ワークフロー
ワークフローは絶対に失敗してはならない操作のためのものです。状態をワークフロープロバイダ(Temporalなど)に永続化し、クラッシュ、再起動、インフラストラクチャの変更後でも中断した場所から正確に再開できます。
-- これは数日間実行でき、再起動を乗り越え、進捗を失うことはありません
workflow.execute("app.orders:process", order_id)
トレードオフはレイテンシーです。すべてのステップが記録されるため、ワークフローは関数やプロセスより遅くなります。しかし、マルチステップのビジネスプロセスや長時間実行されるオーケストレーションには、その耐久性が価値があります。
比較
| 関数 | プロセス | ワークフロー | |
|---|---|---|---|
| 状態 | なし | メモリ内 | 永続化 |
| 存続期間 | 単一呼び出し | 終了またはクラッシュまで | すべてを乗り越える |
| 通信 | 戻り値 + メッセージ | メッセージパッシング | アクティビティ呼び出し + メッセージ |
| 障害処理 | 呼び出し元が処理 | スーパービジョンツリー | 自動リトライ |
| レイテンシー | 最低 | 低 | 高め |
同じコード、異なる動作
多くのモジュールはコンテキストに応じて自動的に適応します。たとえば、time.sleep()は関数内ではワーカーをブロックし、プロセス内では他のプロセスの実行を許可するためにyieldし、ワークフロー内ではリカバリ時に正しくリプレイされるタイマーを記録します。