自訂資料表觸發器
Trigger 在資料變更提交成功之後建立非同步 run,再依序執行 actions。它適合通知、呼叫外部服務及衍生寫入,不是 validation:action 失敗不會回滾已提交的來源資料,也不能用來否決寫入;需要否決時請使用規則。
定義一個 trigger
{
"name": "新訂單通知與同步",
"on": "created",
"when": [
{ "column": "狀態", "op": "eq", "value": "已送出" }
],
"actions": [
{
"type": "notify",
"chatroom_id": "11111111-1111-4111-8111-111111111111",
"message": "新訂單:$row.訂單編號"
},
{
"type": "api_call",
"method": "POST",
"url": "https://integrator.example/orders/$row.訂單編號",
"body": { "record_id": "$row.訂單編號", "amount": "$row.金額" }
}
]
}on 可為 created、updated、deleted、restored 或 schedule。when 最多 5 個 AND predicates;updated 還可用 transition: { "column", "from"?, "to"? } 篩選前後狀態。每張表最多 50 個 triggers,每個 trigger 必須有 1 至 5 個 actions。
和 rules 相同,triggers.set 是 full-replace PUT。先 triggers.get、保留既有 trg_<hex> IDs、修改完整清單再送出。但只保留 trigger id 已經不夠:每個 action 現在都會回傳自己的穩定 id(act_<12 hex>),這個也必須原樣送回。 用戶端把它丟掉,伺服器就會重新產生 action 身分,任何目前處於 failed 或 pending 的 run 都會失去續跑能力。
這個 PUT 也會維護相依 commands 的凍結 dependency contract。伺服器不分 DSL version,會重新編譯所有在編輯前 stored dependency contract 仍 valid 的相依 commands,並在同一個 transaction 中提交 trigger 集合、schema history 與刷新後的 command definitions。若 command 的 stored contract 已因其他原因 stale,則維持 stale。候選 action 若加入新的 target table,仍必須符合每個選中 command 的 tag closure;只要有 command 無法刷新,REST 就回傳 409,且 detail.error: "command_dependency_refresh_failed",並回滾 trigger 集合、history 與所有刷新後的 definitions。成功 body 仍只回傳 table 與 triggers,不會列出刷新後的 command IDs 或 digests。
IaC trigger 行使用相同的刷新規則,並把 trigger 的 IaC state 一併納入原子 bundle。失敗會回滾該行的 bundle,而整次 apply 仍維持 per-line best effort。
十種 action
type | 最小 shape | 用途 |
|---|---|---|
webhook | { "type": "webhook", "url": "https://...", "headers": {}? } | POST trigger-time row snapshot |
api_call | { "type": "api_call", "method": "POST", "url": "https://...", "headers": {}?, "body": {}? } | 可設定 GET/POST/PUT/PATCH/DELETE 的外部 JSON 呼叫 |
create_record | { "type": "create_record", "table_id": id?, "data": {} } | 在相同 scope 或合法的同公司 ancestor scope 建立列 |
update_record | { "type": "update_record", "table_id": id?, "target": "$row", "data": {} } | 更新本列或一跳目標;明確 target table 使用相同的向上 scope matrix |
notify | { "type": "notify", "chatroom_id": id, "message": "..." } | 對同公司的 chatroom 發送訊息 |
send_channel_message | { "type": "send_channel_message", "recipient": "created_by_client", "message": "..." } | 依資料列解析出一位社群客戶,推送一則訊息 |
invoke_command | { "type": "invoke_command", "command_id": id, "inputs": {} } | 以 trigger 作者的身分執行一個複合指令 |
delete_record | { "type": "delete_record", "target": "$row" } | 只軟刪除觸發它的那一列 |
materialize_slots | { "type": "materialize_slots", "target": {...}, "horizon_days": 30 } | 在每日排程上把班表列展開成可預約時段 |
submit_sandbox_job | { "type": "submit_sandbox_job", "task_version_id": id, "input": {} } | 對 created/updated 資料列快照排入已授權的 Sandbox task version |
Actions 按陣列順序執行,遇到第一個失敗就停止。$row.<欄位> 可用於模板;API call 的 host 必須是靜態 HTTP(S) host,只有 path/query 可插值。字串模板在儲存時轉為 rename-stable key,執行時再從 trigger-time snapshot 取值;唯一例外是 notify.message,它以原文儲存,所以欄位改名會讓 notify 模板失效。
各種 action 的欄位、上限與失敗模式見動作型別。
一次執行是「誰」在做
由 trigger 寫出的資料列仍然標記為 trigger 的 created_by,但實際權限現在取決於是什麼造成這次執行:
| 觸發來源 | 資料列寫入以誰的權限執行 |
|---|---|
created / updated / deleted / restored | 造成該次寫入的 principal,且用他自己對目標表的權限 |
schedule | 系統權限,與以前相同 |
invoke_command(不論來源) | trigger 作者當下的有效權限 |
所以一個「只有管理者會寫資料時」運作良好的自動化,可能在低權限使用者觸發它的那一刻開始失敗,而失敗會以 ok: false 的 action receipt 呈現,整個 run 標記為 failed。webhook、api_call、notify、send_channel_message 不受這條 ACL 閘門限制。詳見 Grant 與 row policy。
提交、排隊、觀測
來源 transaction 會同時留下 run row;提交後才送入 worker。Run 使用同一個 chain_id 傳遞衍生寫入,最大 chain depth 為 3,避免 trigger 互相循環,且每條 chain 的 generated-run 預算為 1,000 個子 run。At-least-once 傳輸會以原子 pending → running 更新認領 run;同時送達的重複 worker 看到 rowcount=0 就會在任何 action 前退出。從 triggerRuns.list 讀取 status、attempts、payload、chain_generated_runs 與逐 action 結果,再依執行紀錄與重試處理失敗。
Warning Trigger 不能與
channelSCP 規則共存,因為背景 action 沒有 acting room。require_approval的互斥有四條,每一條都回409 approval_trigger_conflict:create_record/update_record的目標表、delete_record的自身表、invoke_command所引用 command 會寫入的每一張表,以及materialize_slots的目標表。invariant可以與 trigger 共存,且會驗證 trigger 寫入。
時間型工作見排程觸發器。端到端組合 rules、trigger、callback 與 run observation,請依自動化指南或使用流程精靈。