Skip to Content
操作指南原子資料集發布

原子資料集發布

Publish session 是給「整份資料必須一次對讀者可見」的批次通道。Moderator 先開啟 session,把一個或多個經驗證的 chunk 暫存到所有 record read 都看不到的區域,再派送 commit。Commit 會在同一個資料庫 transaction 裡軟刪除選填的 replace 集合,並新增所有 staged rows:不是完整新資料集一次落地,就是讀者繼續看到完整舊資料集。

這不是 bulk-insertbulk-updatebulk-delete 的部分成功語意。三種保證的並排比較見批次操作

Scope 與權限

Publish session 只存在於 department 與 company table:

ScopeBase path
Department/private/module/custom_tables/department/{department_id}/tables/{table_id}/publish-sessions
Company/private/module/custom_tables/company/tables/{table_id}/publish-sessions

沒有 chatroom 路由。每個操作都要求目前仍具 table moderator 權限。開啟 session 的 moderator 擁有變更權:只有他能 stage chunk、commit 或 abort;任何目前的 moderator 都能讀取 status,讓共同管理者看出是誰占用 active publish slot,以及 commit 為何失敗。

資料表帶有 require_approvalchannel 規則時不能開啟 session。Publish commit 無法先 hold 等待日後覆核,而 background worker 也沒有 acting chatroom 可通過 channel floor。

1. 開啟唯一 session

對 department 或 company base path 送出相同 payload:

{ "idempotency_key": "catalog-2026-08-20", "replace_filter": [ { "column": "col_55555555_5555_4555_8555_555555555555", "op": "eq", "value": "current" } ] }

兩個欄位都可省略。replace_filter 省略或為空時是 append-only publish;提供時最多包含 20 個已儲存欄位條件,並使用內部欄位鍵。Server 會在開啟時立即編譯,因此未知或 computed column 會在任何資料暫存前就失敗。

idempotency_key 最長 128 字。對同一張表與同一位 actor,只要原 session 尚未過期,且狀態為 opencommittingcommitted,以同一 key 重送就會回傳原 session 並標記 replayed: true,不會再開一個。已 aborted 的 session 即使原 expiry 尚未到,也不會被重播。

{ "session_id": "33333333-3333-4333-8333-333333333333", "expires_at": "2026-08-21T00:00:00Z", "replayed": false }

硬性到期時間是建立後 24 小時。每張表同一時間只能有一個 opencommitting session;在 owner abort、session 過期,或 commit 完成釋放 slot 之前,第二次開啟會收到 409 session_conflict

2. 暫存可安全重試的 chunks

每個 chunk 送到:

POST {base}/publish-sessions/{session_id}/chunks
{ "seq": 0, "records": [ { "訂單編號": "A-1001", "狀態": "current" }, { "訂單編號": "A-1002", "狀態": "current" } ] }

Chunk contract 有明確上限:

  • seq063 的整數。
  • 每個 chunk 可放 1–5,000 列;整個 session 的所有 sequence slots 合計最多 5,000 staged rows。
  • 每列使用一般 create body shape:顯示名稱或內部鍵,以及單筆建立路徑接受的 link 與 attachment shape。不要送 id。Validator 內部可能暫用一個 ID,但真實 record ID 只由 commit 的 create path 產生。
  • 重送既有 seq 會原子取代該整個 chunk。遇到回應不明時請重用同一 sequence number,不要以新號碼附加一份重複資料。
  • Schema validation 與 advisory rule precheck 會檢查完整 chunk;任一列失敗,整個 chunk 都拒絕,回傳 zero-based row_index errors,原本該 slot 的內容保持不變。

接受的列只存在 staging table。一般 record list、search、saved view、public read、callback 與 agent tool 都看不到。成功回應的 accepted count 與 staged_total 只代表已暫存,不代表已發布。

3. 派送原子 commit

確認 staged_count 後呼叫:

POST {base}/publish-sessions/{session_id}/commit

Session 必須是 open,且至少已有一列。成功回應是非同步派送:

{ "ticket_id": "44444444-4444-4444-8444-444444444444", "replayed": false }

這不代表 commit 已完成。Session 已是 committingcommitted 時重試,只會回既有 ticket 並標記 replayed: true,絕不重複派送同一次 commit。

Worker 會在一個 transaction 內完成整次 flip:

  1. 重新載入並鎖住 session 與 table,重新檢查 opener 現在的權限。
  2. 若有 replace_filter,將它與 opener 目前的 row ACL 及 scope floor 以 AND 合併;不在授權集合內的列永遠不會成為刪除目標。
  3. Live replacement set 最多 5,000 列。更廣的結果會以 replace_target_cap_exceeded 失敗;請縮小 filter 或拆分發布。
  4. 經由真正的 delete core 軟刪除所有獲授權 replacement rows。
  5. 經由真正的 create core 新增全部 staged rows,包括 schema、rules、links、attachments 與 scope enforcement。
  6. 只 commit 一次,接著清掉 staging 並把 session 標為 committed

最後 commit 前的任何失敗都會回滾完整 flip。讀者永遠看不到刪到一半或新增到一半的資料集。

同時輪詢兩個來源

以 generic task ticket 追蹤 worker 進度:

GET /public/task/{ticket_id}

並同時讀取 session:

GET {base}/publish-sessions/{session_id}

Generic ticket 告訴你 background work 是 submitting、processing、completed 或 failed。Session 則提供 publish lifecycle(opencommittingcommittedabortedexpired)、staged count、到期時間、ticket、replace filter 與最近一次 structured commit error。共同 moderator 可以讀這份 status,但不能變更 session。

在不暴露部分資料的前提下重試或放棄

可重試的 validation、row、link、permission 或 rule 失敗會回滾 transaction、記錄 structured error、讓 session 回到 open,並保留所有 chunks。請以相同 seq 重送來修正 staged chunk,或修好 live dependency,再次 commit;新的 attempt 會得到新 ticket。不要只看 generic ticket failed 就認定 session 已中止,必須讀 session status。

Table 消失、table/company identity 不一致或 session 過期時,session 會進入 terminal 狀態並清掉 staging,不會重新開啟。失去 moderator authority 不同:該次 commit 會以 actor_not_authorized 重新開啟 session 並保留 staging,直到 owner 恢復權限或 abort。Session 一旦 committed,就沒有 publish-session rollback;被軟刪除的舊列改走一般 record history 與 restore 語意。

若要放棄尚未 commit 的發布,由 owner 呼叫:

POST {base}/publish-sessions/{session_id}/abort

只有 open session 可以 abort。它會刪除所有 staged rows 並釋放 active slot;已進入 committing 的 commit 不能在這裡取消,已完成的 commit 也不能靠 abort 還原。

Client checklist

  1. 只在 department/company table 且確實需要一次可見時使用這條 lane。
  2. 將 open 回應的 session_idexpires_at 與穩定 idempotency key 一起保存。
  3. 以 deterministic 方式編號 chunks;回應不明時用相同 seq 重試。
  4. 絕不提供 record IDs,讓 commit 產生它們。
  5. Commit 前先確認 status 的 staged_count
  6. 把 commit 200 視為派送,接著同時輪詢 task 與 session。
  7. 可重試失敗時修復或取代問題 chunk 再 commit;確定放棄時趁 session 仍 open 執行 abort。

Endpoint 卡片與精確 request/response models 見批次操作參考

Last updated on