ワークフロー
ワークフローは長時間実行 operation の state を永続化し、crash や restart の後も execution を復旧できるようにします。payment、order fulfillment、multi-step approval などの process に適しています。
ワークフローを使う理由 :id=why-use-workflows
関数は実行中の state を memory に保持しますが、ワークフローは execution state を永続化します。
| 側面 | 関数 | ワークフロー |
|---|---|---|
| State | 呼び出し内のみ | 永続化された履歴から再構築 |
| Worker crash | 実行中の呼び出しが失敗 | 記録済み履歴から replay |
| Duration | 秒から分 | 時間から月 |
| Application failure | 呼び出し元に返す | provider policy に従って終了または retry |
ワークフローの動作
ワークフローのコードは通常のLuaコードのように見えます:
local funcs = require("funcs")
local time = require("time")
local result, err = funcs.call("app.api:charge_card", payment)
if err then return nil, err end
time.sleep("24h")
local status, err = funcs.call("app.api:check_status", result.id)
if err then return nil, err end
if status == "failed" then
local _, refund_err = funcs.call("app.api:refund", result.id)
if refund_err then return nil, refund_err end
end
return status
workflow engine は call を intercept し、結果を記録します。crash 後は記録済み履歴から execution を replay します。
workflow 内では、各 funcs.call() target が Temporal activity として実行されます。target の function.* entry は meta.temporal.activity.worker を介して worker に登録する必要があります。未登録 entry は workflow から利用できません。process.* activity target にはさらに、Temporal worker が使う function registry に登録するための meta.options.default_host(または legacy の meta.default_host)が必要です。function activity の例と activity option は Activityを参照してください。
funcs.call() は記録される activity を実行し、time.sleep() は workflow timer を使い、uuid.v4() は side effect を記録し、time.now() は workflow の deterministic time reference を読み取ります。
ワークフローパターン
Sagaパターン
失敗時に補償します。
local funcs = require("funcs")
local inventory, err = funcs.call("app.inventory:reserve", items)
if err then return nil, err end
local payment, err = funcs.call("app.payments:charge", amount)
if err then
local _, compensation_err = funcs.call("app.inventory:release", inventory.id)
return nil, compensation_err or err
end
local shipping, err = funcs.call("app.shipping:create", order)
if err then
local _, refund_err = funcs.call("app.payments:refund", payment.id)
local _, release_err = funcs.call("app.inventory:release", inventory.id)
return nil, refund_err or release_err or err
end
return {inventory = inventory, payment = payment, shipping = shipping}
Signal の待機 :id=waiting-for-signals
外部 event(approval decision、webhook、user action)を待ちます。
local funcs = require("funcs")
local _, err = funcs.call("app.approvals:submit", request)
if err then return nil, err end
local inbox = process.inbox()
local msg, open = inbox:receive() -- blocks until signal arrives
if not open then return nil, errors.new("workflow inbox closed") end
local decision, payload_err = msg:payload():data()
if payload_err then return nil, payload_err end
if decision.approved then
return funcs.call("app.orders:fulfill", request.order_id)
else
return funcs.call("app.notifications:send_rejection", request)
end
Compute model の選択 :id=choosing-a-compute-model
| ユースケース | 選択 |
|---|---|
| HTTP request 処理 | 関数 |
| Data transformation | 関数 |
| Background job | プロセス |
| User session state | プロセス |
| Real-time messaging | プロセス |
| Payment 処理 | ワークフロー |
| Order fulfillment | ワークフロー |
| 複数日にわたる approval | ワークフロー |
ワークフローの開始
ワークフローでは、workflow host を指定して process.spawn() を使います。
-- Spawn workflow on temporal worker
local pid, err = process.spawn("app.workflows:order_processor", "app:temporal_worker", order_data)
if err then return nil, err end
-- Send signals to workflow
local ok, err = process.send(pid, "update", {status = "approved"})
if err then return nil, err end
return ok
呼び出し元は同じ生成 API を使います。エントリが temporal.worker と process.host のどちらで実行されるかはホストが決定します。永続化された履歴と再生が適用されるのは、Temporal でホストされる経路だけです。通常のプロセスホストで実行したワークフローエントリはメモリ内プロセスのセマンティクスとなり、Temporal の永続性は得られません。
process.spawn() で child を生成すると、同じ provider 上の child workflow となり、durability guarantee が維持されます。
障害とスーパービジョン
プロセスはprocess.serviceを使用して監督されたサービスとして実行できます:
# Process definition
- name: session_handler
kind: process.lua
source: file://session_handler.lua
method: main
# Supervised service wrapping the process
- name: session_manager
kind: process.service
process: app:session_handler
host: app:processes
lifecycle:
auto_start: true
restart:
max_attempts: 10
ワークフローは process supervision tree を使いません。workflow provider が persistence と recovery を管理し、application-level retry は設定済みの workflow policy と activity policy に従います。
設定
プロセス定義(動的に生成):
- name: order_processor
kind: workflow.lua
source: file://order_processor.lua
method: main
meta:
temporal:
workflow:
worker: app:temporal_worker
modules:
- funcs
- time
funcs.call() から呼び出すすべての function または process も activity worker を宣言します。例:
- name: charge_card
kind: function.lua
source: file://charge_card.lua
method: main
meta:
temporal:
activity:
worker: app:temporal_worker
ワークフロープロバイダ:
- name: temporal_worker
kind: temporal.worker
client: app:temporal_client
task_queue: "orders"
lifecycle:
auto_start: true
production workflow infrastructure については Temporalを参照してください。