批次操作
同步執行原子混合寫入、派送允許部分成功的大量工作,或先暫存部門/公司資料集,再一次原子發布。下方卡片包含五個 publish-session 操作;完整生命週期與重試協定見原子資料集發布指南。
/private/module/custom_tables/{scope}/tables/{table_id}/records/bulk在一個交易中混合新增、更新與刪除資料列,並回傳各類操作筆數。
最多 100 個相依動作必須全成或全敗時使用。
- 聊天室
/private/module/custom_tables/chatroom/{chatroom_id}/tables/{table_id}/records/bulk - 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/records/bulk - 公司
/private/module/custom_tables/company/tables/{table_id}/records/bulk
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableEditRequired |
| 部門 | 可使用 | CustomTableEditRequired |
| 公司 | 可使用 | CustomTableEditRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 要執行混合批次的自訂資料表 UUID。 |
請求結構
BulkRecordPayload| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
actions | BulkRecordAction[] | 是 | List of insert/update/delete actions (max 100 per request) |
回應結構
BulkRecordResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
deleted | integer | 是 | Number of records deleted |
inserted | integer | 是 | Number of records inserted |
message | string | 否 | 未指定 |
updated | integer | 是 | Number of records updated |
範例
原子地新增、更新與刪除各一筆
{
"pathParams": {
"chatroom_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222"
},
"body": {
"actions": [
{
"action": "insert",
"data": {
"品項": "鉛筆",
"數量": 5
}
},
{
"action": "update",
"record_id": "33333333-3333-4333-8333-333333333333",
"data": {
"col_b2222222_2222_4222_8222_222222222222": 3
}
},
{
"action": "delete",
"record_id": "44444444-4444-4444-8444-444444444444"
}
]
}
}{
"inserted": 1,
"updated": 1,
"deleted": 1,
"message": "Bulk record operations completed successfully"
}用 expected_version 保護單一 action(樂觀鎖)
{
"pathParams": {
"chatroom_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222"
},
"body": {
"actions": [
{
"action": "update",
"record_id": "33333333-3333-4333-8333-333333333333",
"data": {
"col_b2222222_2222_4222_8222_222222222222": 3
},
"expected_version": 4
},
{
"action": "delete",
"record_id": "44444444-4444-4444-8444-444444444444"
}
]
}
}{
"inserted": 0,
"updated": 1,
"deleted": 1,
"message": "Bulk record operations completed successfully"
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 400 | 某個 action 結構不合法(例如 Action N: 'data' is required for insert);索引從 0 起算。 | |
| 400 | 某個 action 寫入的 link 值指向不存在、已被 soft delete,或被你的 row ACL 藏起來的目標。這條路由把底層的 ValueError 映成 400,所以統一的參照失敗在這裡是帶字串 detail 的 400——不是單筆通道回的 404。三種原因的訊息刻意完全相同:分開它們就等於讓寫入變成 existence oracle。 | |
| 403 | 批次含 insert action,但呼叫者沒有此表的新增權限。 | |
| 403 | 某個 action 指向的 link target 存在、也通過你的 row ACL,只被 acting room 的 channel scope 擋住。這裡的 detail 是**物件**不是字串:error 為 scp_out_of_scope、scp_scope_undeclared(你的房間在目標資料表上沒有宣告 channel scope)或 scp_rule_dangling(該表上的 channel rule 已無法解析)。請以 detail.error 分支、不要以狀態碼分支,並預期這條路由的 detail 可能是字串也可能是物件。 | |
| 409 | 資料表的 require_approval 規則把整批寫入暫存等待覆核(BulkApprovalConflict409Response;GA 預設開啟)。 | |
| 409 | 某個 update action 帶了 expected_version,而資料列當下的 version 不同。比對是在 refresh 過的資料列上、於 SELECT … FOR UPDATE 之下進行。這批是 atomic,所以什麼都沒套用——衝突之前的 action 沒有,之後的也沒有。action_index 是你送出的 actions 陣列中以 0 起算的位置。 | |
| 409 | 同一道 guard、不同的答案:當 require_approval 規則命中這一批時,expected_version 會帶進 staging 並在 staging lock 下複驗,而 atomic 呼叫端拿到的是這個、不是 version_conflict——沒有 action_index、沒有版本數字,只有被動過的 record ids。沒有 stage、也沒有執行。這條路由上不要只認 version_conflict。 | |
| 422 | expected_version 被送在 insert 或 delete action 上。它只在 update action 有效——insert 沒有前一個版本,delete 也沒有資料需要保護。在任何 action 執行之前就被 model 擋下。 | |
| 423 | 資料表正被結構遷移鎖定。 | |
| 429 | 此表或此操作者的待覆核暫存變更已達上限(staged_cap_exceeded)。 | |
| 429 | 此表或此操作者的待覆核暫存變更已達上限(staged_cap_exceeded)。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/records/bulk-insert派送最多 50,000 筆資料列的背景新增工作,立即回傳追蹤 ticket。
資料量超過同步混合批次上限,且可接受背景逐筆結果時使用。
- 聊天室
/private/module/custom_tables/chatroom/{chatroom_id}/tables/{table_id}/records/bulk-insert - 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/records/bulk-insert - 公司
/private/module/custom_tables/company/tables/{table_id}/records/bulk-insert
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableInsertRequired |
| 部門 | 可使用 | CustomTableInsertRequired |
| 公司 | 可使用 | CustomTableInsertRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 要批次新增資料列的自訂資料表 UUID。 |
worker | query | enum:legacy|batch|sqs|pubsub | 否 | 背景執行後端;可選 legacy、batch、sqs 或 pubsub,省略時使用部署預設值。 |
請求結構
BulkInsertPayload| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
created_by_ai | boolean | 否 | Whether records are created by AI |
idempotency_key | string | null | 否 | Replay protection scoped to (table, operation-kind=insert, acting actor): re-dispatching the same bulk-insert with the same idempotency_key inside the 24h ticket window returns the ORIGINAL ticket_id instead of inserting the batch a second time — makes a timed-out retry safe. A different operation (update/delete), a different actor, or a different table reusing this key is an INDEPENDENT batch and never replays this ticket. When the batch is HELD by an approval rule, a resubmit with the same key returns the SAME held ticket. For backward compatibility an empty string is treated as omitted (dedupe disabled). Values up to the established 128-character wire limit are accepted; overlong persistence keys are represented by an operation-scoped digest. A duplicate that arrives before dispatch is bound short-polls for the original ticket; if it remains pending, the endpoint returns retryable 409 with Retry-After: 1. |
match_column | string | null | 否 | Upsert mode: a column display name or internal col_<hex> id. When set, each row UPDATES the existing (non-deleted) record in this table whose match_column value equals the row's value, and inserts only when no match is found. When null (default) every row is inserted. |
records | object[] | 是 | List of record data objects keyed by column IDs (max 50000 per request) |
回應結構
BulkTaskResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
message | string | 否 | 未指定 |
replayed | boolean | null | 否 | True when this response is an idempotent replay: the idempotency_key matched a ticket-bound in-flight/completed submission for the same (table, operation-kind, actor), so ticket_id is the ORIGINAL ticket and NO new batch was dispatched. Null/false on a fresh submission that queued a new batch. |
ticket_id | string | 是 | Ticket ID |
範例
派送兩筆資料列的背景新增工作
{
"pathParams": {
"chatroom_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222"
},
"query": {
"worker": "legacy"
},
"body": {
"records": [
{
"品項": "原子筆",
"數量": 10
},
{
"品項": "橡皮擦",
"數量": 4
}
],
"created_by_ai": false,
"idempotency_key": "insert-demo-001"
}
}{
"ticket_id": "77777777-7777-4777-8777-777777777777",
"message": "Bulk insert task submitted",
"replayed": null
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 403 | 呼叫者沒有此資料表的新增權限。 | |
| 423 | 派送當下資料表正被結構遷移鎖定。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/records/bulk-update派送最多 50,000 筆局部更新,立即回傳追蹤 ticket。
大量既有資料列可獨立更新,且允許部分資料失敗時使用。
- 聊天室
/private/module/custom_tables/chatroom/{chatroom_id}/tables/{table_id}/records/bulk-update - 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/records/bulk-update - 公司
/private/module/custom_tables/company/tables/{table_id}/records/bulk-update
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableEditRequired |
| 部門 | 可使用 | CustomTableEditRequired |
| 公司 | 可使用 | CustomTableEditRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 要批次更新資料列的自訂資料表 UUID。 |
worker | query | enum:legacy|batch|sqs|pubsub | 否 | 背景執行後端;可選 legacy、batch、sqs 或 pubsub,省略時使用部署預設值。 |
請求結構
BulkUpdatePayload| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
idempotency_key | string | null | 否 | Replay protection scoped to (table, operation-kind=update, acting actor): re-dispatching the same bulk-update with the same idempotency_key inside the 24h ticket window returns the ORIGINAL ticket_id instead of applying the batch a second time — makes a timed-out retry safe. A different operation (insert/delete), a different actor, or a different table reusing this key is an INDEPENDENT batch and never replays this ticket. When the batch is HELD by an approval rule, a resubmit with the same key returns the SAME held ticket (staged change + process) instead of colliding with its own pending rows. Empty string is treated as omitted; values up to 128 characters preserve the established wire contract and use an operation-scoped digest when the persisted composite would be long. A duplicate that arrives before dispatch is bound short-polls for the original ticket; if it remains pending, the endpoint returns retryable 409 with Retry-After: 1. |
updates | BulkUpdateItem[] | 是 | List of record updates (record_id + partial data) (max 50000 per request) |
回應結構
BulkTaskResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
message | string | 否 | 未指定 |
replayed | boolean | null | 否 | True when this response is an idempotent replay: the idempotency_key matched a ticket-bound in-flight/completed submission for the same (table, operation-kind, actor), so ticket_id is the ORIGINAL ticket and NO new batch was dispatched. Null/false on a fresh submission that queued a new batch. |
ticket_id | string | 是 | Ticket ID |
範例
派送一筆資料列的背景更新工作
{
"pathParams": {
"chatroom_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222"
},
"query": {
"worker": "legacy"
},
"body": {
"updates": [
{
"record_id": "33333333-3333-4333-8333-333333333333",
"data": {
"col_b2222222_2222_4222_8222_222222222222": 8
}
}
],
"idempotency_key": "update-demo-001"
}
}{
"ticket_id": "77777777-7777-4777-8777-777777777777",
"message": "Bulk update task submitted",
"replayed": null
}用 expected_version 保護更新(樂觀鎖)
{
"pathParams": {
"chatroom_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222"
},
"query": {
"worker": "legacy"
},
"body": {
"updates": [
{
"record_id": "33333333-3333-4333-8333-333333333333",
"data": {
"col_b2222222_2222_4222_8222_222222222222": 8
},
"expected_version": 4
}
],
"idempotency_key": "update-demo-002"
}
}{
"ticket_id": "77777777-7777-4777-8777-777777777777",
"message": "Bulk update task submitted",
"replayed": null
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 403 | 呼叫者沒有此資料表的編輯權限。 | |
| 422 | payload 帶了 model 沒宣告的 key——包含把真 key 打錯字。整批都沒有送出。forbid 收斂之前這會回 200、未知 key 被無聲丟掉;如果打錯的是 expected_version,你以為有的保護其實不存在。 | |
| 423 | 派送當下資料表正被結構遷移鎖定。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/records/bulk-delete派送最多 50,000 個資料列 ID 的背景軟刪除工作,立即回傳追蹤 ticket。
需要大量移入資料列垃圾桶,且可接受逐筆失敗時使用。
- 聊天室
/private/module/custom_tables/chatroom/{chatroom_id}/tables/{table_id}/records/bulk-delete - 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/records/bulk-delete - 公司
/private/module/custom_tables/company/tables/{table_id}/records/bulk-delete
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 可使用 | CustomTableEditRequired |
| 部門 | 可使用 | CustomTableEditRequired |
| 公司 | 可使用 | CustomTableEditRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 要批次刪除資料列的自訂資料表 UUID。 |
worker | query | enum:legacy|batch|sqs|pubsub | 否 | 背景執行後端;可選 legacy、batch、sqs 或 pubsub,省略時使用部署預設值。 |
請求結構
BulkDeletePayload| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
idempotency_key | string | null | 否 | Replay protection scoped to (table, operation-kind=delete, acting actor): re-dispatching the same bulk-delete with the same idempotency_key inside the 24h ticket window returns the ORIGINAL ticket_id instead of re-running the batch — makes a timed-out retry safe. A different operation (insert/update), a different actor, or a different table reusing this key is an INDEPENDENT batch and never replays this ticket. When the batch is HELD by an approval rule, a resubmit with the same key returns the SAME held ticket (staged change + process) instead of colliding with its own pending rows. Empty string is treated as omitted; values up to 128 characters preserve the established wire contract and use an operation-scoped digest when the persisted composite would be long. A duplicate that arrives before dispatch is bound short-polls for the original ticket; if it remains pending, the endpoint returns retryable 409 with Retry-After: 1. |
record_ids | string[] | 是 | List of record IDs to soft-delete (max 50000 per request) |
回應結構
BulkTaskResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
message | string | 否 | 未指定 |
replayed | boolean | null | 否 | True when this response is an idempotent replay: the idempotency_key matched a ticket-bound in-flight/completed submission for the same (table, operation-kind, actor), so ticket_id is the ORIGINAL ticket and NO new batch was dispatched. Null/false on a fresh submission that queued a new batch. |
ticket_id | string | 是 | Ticket ID |
範例
派送一筆資料列的背景刪除工作
{
"pathParams": {
"chatroom_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222"
},
"query": {
"worker": "legacy"
},
"body": {
"record_ids": [
"44444444-4444-4444-8444-444444444444"
],
"idempotency_key": "delete-demo-001"
}
}{
"ticket_id": "77777777-7777-4777-8777-777777777777",
"message": "Bulk delete task submitted",
"replayed": null
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 403 | 呼叫者沒有此資料表的編輯權限。 | |
| 423 | 派送當下資料表正被結構遷移鎖定。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/publish-sessions為部門或公司資料表開啟由 moderator 擁有的 staging session,供後續原子性發布資料集。
當資料集必須先分批驗證,再一次對讀者可見時使用;也可選擇取代 ACL 限制後的既有 live rows。
- 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/publish-sessions - 公司
/private/module/custom_tables/company/tables/{table_id}/publish-sessions
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 未提供 | 不適用 |
| 部門 | 可使用 | CustomTableModeratorRequired |
| 公司 | 可使用 | CustomTableModeratorRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | 要發布資料的部門或公司資料表 UUID。 |
請求結構
PublishSessionCreatePayload| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
idempotency_key | string | null | 否 | Create replay protection scoped to (table, acting user): re-creating with the same key while the original session has not expired returns the SAME session (replayed=true) instead of opening a second one. An empty string is treated as omitted. |
replace_filter | StoredFilterPredicate[] | null | 否 | Which LIVE rows the commit replaces: every non-deleted record matching ALL predicates (AND) is soft-deleted in the same transaction that inserts the staged rows — additionally floored by the acting user's row ACL and SCP scope at commit time. Omitted/empty = append-only publish (no deletes). Validated (compiled) at create time; a predicate on an unknown/computed column is a 400. |
回應結構
PublishSessionCreateResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
expires_at | string (date-time) | 是 | Hard TTL (create + 24h): after this, chunks and commit are rejected and the session expires |
replayed | boolean | 否 | True when idempotency_key matched an existing non-expired session — no new session was opened |
session_id | string | 是 | Publish session UUID — path id for chunks/commit/abort/status |
範例
開啟 append-only publish session
{
"pathParams": {
"department_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222"
},
"body": {
"idempotency_key": "catalog-publish-20260820"
}
}{
"session_id": "33333333-3333-4333-8333-333333333333",
"expires_at": "2026-08-21T00:00:00Z",
"replayed": false
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 400 | replace_filter 無效、引用未知或 computed 欄位,或無法編譯。 | |
| 409 | 資料表帶有 require_approval;publish session 無法進入該 review hold。 | |
| 409 | 同一資料表的唯一 active slot 已被另一個 open 或 committing session 占用。 | |
| 409 | 資料表帶有 channel rule,但這條 moderator REST lane 沒有 acting-room carrier,因此會在開啟 session 前直接拒絕。 | |
| 423 | Schema 或 maintenance operation 正持有 table lock。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/publish-sessions/{session_id}/chunks驗證一個有編號的 chunk,並在 open publish session 內原子性取代該 chunk slot。
在 commit 完整資料集前,用來一次上傳 1 到 5,000 筆 create-shape rows。
- 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/publish-sessions/{session_id}/chunks - 公司
/private/module/custom_tables/company/tables/{table_id}/publish-sessions/{session_id}/chunks
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 未提供 | 不適用 |
| 部門 | 可使用 | CustomTableModeratorRequired |
| 公司 | 可使用 | CustomTableModeratorRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | Publish session 所屬資料表 UUID。 |
session_id | path | uuid | 是 | 開啟 publish session 時回傳的 UUID。 |
請求結構
PublishChunkPayload| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
records | object[] | 是 | Record data objects (create-path shape: display names OR internal col_<hex> keys; link/attachment cells accept the single-record create shapes). Whole session is capped at 5000 staged rows (v1). |
seq | integer | 是 | Chunk slot (0..63). Resubmitting the same seq atomically REPLACES that chunk's staged rows (retry-safe). |
回應結構
PublishChunkResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
accepted | integer | 是 | Rows staged from this chunk (== len(records)) |
staged_total | integer | 是 | Total rows currently staged across all chunks of the session |
範例
暫存前兩筆資料
{
"pathParams": {
"department_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222",
"session_id": "33333333-3333-4333-8333-333333333333"
},
"body": {
"seq": 0,
"records": [
{
"Order number": "A-1001",
"Status": "open"
},
{
"Order number": "A-1002",
"Status": "open"
}
]
}
}{
"accepted": 2,
"staged_total": 2
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 400 | 至少一筆 row 未通過 schema 或 advisory-rule 驗證;整個 chunk 會被拒絕並回傳逐列錯誤。 | |
| 403 | 呼叫者雖是 table moderator,但不是開啟此 session 的 moderator。 | |
| 409 | Session 已到期或不再是 open。 | |
| 413 | 取代這個 chunk 後,session 會超過 5,000 筆 staged rows。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/publish-sessions/{session_id}/commit派送非同步 atomic flip,在同一 transaction 內 soft-delete 已授權的 replace set,並插入所有 staged rows。
所有 chunk 都已接受,而且 session status 的 staged_count 符合預期後使用。
- 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/publish-sessions/{session_id}/commit - 公司
/private/module/custom_tables/company/tables/{table_id}/publish-sessions/{session_id}/commit
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 未提供 | 不適用 |
| 部門 | 可使用 | CustomTableModeratorRequired |
| 公司 | 可使用 | CustomTableModeratorRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | Publish session 所屬資料表 UUID。 |
session_id | path | uuid | 是 | Open publish session UUID。 |
worker | query | enum:legacy|batch|sqs|pubsub | 否 | 背景 worker lane;省略時使用部署設定的預設 worker。 |
回應結構
PublishCommitResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
replayed | boolean | 否 | True when the session was already committing/committed — the existing ticket is returned, nothing was dispatched again |
ticket_id | string | 是 | Commit worker ticket for progress tracking via GET /task/{ticket_id} |
範例
派送原子性 publish commit
{
"pathParams": {
"department_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222",
"session_id": "33333333-3333-4333-8333-333333333333"
},
"query": {
"worker": "legacy"
}
}{
"ticket_id": "44444444-4444-4444-8444-444444444444",
"replayed": false
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 400 | Session 尚未暫存任何 row。 | |
| 403 | 呼叫者雖是 moderator,但不是此 session 的建立者。 | |
| 409 | Session 已到期、已 abort,或因其他原因不是 open。 | |
| 423 | Schema 或 maintenance operation 正持有 table lock;session 仍保持 open。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/publish-sessions/{session_id}/abort刪除所有 staged rows,並釋放資料表的 active publish slot。
Open session 不再需要 commit、應直接捨棄時使用。
- 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/publish-sessions/{session_id}/abort - 公司
/private/module/custom_tables/company/tables/{table_id}/publish-sessions/{session_id}/abort
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 未提供 | 不適用 |
| 部門 | 可使用 | CustomTableModeratorRequired |
| 公司 | 可使用 | CustomTableModeratorRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | Publish session 所屬資料表 UUID。 |
session_id | path | uuid | 是 | Open publish session UUID。 |
回應結構
PublishSessionStatusResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
committed_at | string (date-time) | null | 否 | When the commit transaction landed (status == committed) |
created_at | string (date-time) | 是 | When the session was opened |
error | object | null | 否 | Structured failure detail of the last commit attempt (error_code, message, seq/row_index attribution when a staged row caused it); the session is back to `open` and retryable when set |
expires_at | string (date-time) | 是 | Hard TTL (create + 24h) |
replace_filter | StoredFilterPredicate[] | null | 否 | The replace filter captured at create; null = append-only publish |
session_id | string | 是 | Publish session UUID |
staged_count | integer | 是 | Rows currently staged (0 after commit/abort — staged rows are dropped) |
status | "open" | "committing" | "committed" | "aborted" | "expired" | 是 | open | committing | committed | aborted | expired |
table_id | string | 是 | Parent table UUID |
ticket_id | string | null | 否 | Latest commit worker ticket (null before the first commit) |
範例
中止 open session
{
"pathParams": {
"department_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222",
"session_id": "33333333-3333-4333-8333-333333333333"
}
}{
"session_id": "33333333-3333-4333-8333-333333333333",
"table_id": "22222222-2222-4222-8222-222222222222",
"status": "aborted",
"staged_count": 0,
"replace_filter": null,
"error": null,
"created_at": "2026-08-20T00:00:00Z",
"expires_at": "2026-08-21T00:00:00Z",
"committed_at": null,
"ticket_id": null
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 403 | 呼叫者雖是 moderator,但不是此 session 的建立者。 | |
| 409 | 只有 open session 能 abort;已 committing 的 session 無法由這裡取消。 | |
/private/module/custom_tables/{scope}/tables/{table_id}/publish-sessions/{session_id}回傳 staged count、生命週期狀態、ticket、時間戳、replace filter 與最近一次結構化 commit error,但不揭露 staged row 內容。
用來監控 publish,或說明為何另一位 moderator 正占用資料表的 active slot。
- 部門
/private/module/custom_tables/department/{department_id}/tables/{table_id}/publish-sessions/{session_id} - 公司
/private/module/custom_tables/company/tables/{table_id}/publish-sessions/{session_id}
範圍
| 範圍 | 是否提供 | 驗證與權限 |
|---|---|---|
| 聊天室 | 未提供 | 不適用 |
| 部門 | 可使用 | CustomTableModeratorRequired |
| 公司 | 可使用 | CustomTableModeratorRequired |
參數
| 欄位 | 位置 | 型別 | 必填 | 說明 |
|---|---|---|---|---|
table_id | path | uuid | 是 | Publish session 所屬資料表 UUID。 |
session_id | path | uuid | 是 | 要檢查的 publish session UUID。 |
回應結構
PublishSessionStatusResponse| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
committed_at | string (date-time) | null | 否 | When the commit transaction landed (status == committed) |
created_at | string (date-time) | 是 | When the session was opened |
error | object | null | 否 | Structured failure detail of the last commit attempt (error_code, message, seq/row_index attribution when a staged row caused it); the session is back to `open` and retryable when set |
expires_at | string (date-time) | 是 | Hard TTL (create + 24h) |
replace_filter | StoredFilterPredicate[] | null | 否 | The replace filter captured at create; null = append-only publish |
session_id | string | 是 | Publish session UUID |
staged_count | integer | 是 | Rows currently staged (0 after commit/abort — staged rows are dropped) |
status | "open" | "committing" | "committed" | "aborted" | "expired" | 是 | open | committing | committed | aborted | expired |
table_id | string | 是 | Parent table UUID |
ticket_id | string | null | 否 | Latest commit worker ticket (null before the first commit) |
範例
檢查 open publish session
{
"pathParams": {
"department_id": "11111111-1111-4111-8111-111111111111",
"table_id": "22222222-2222-4222-8222-222222222222",
"session_id": "33333333-3333-4333-8333-333333333333"
}
}{
"session_id": "33333333-3333-4333-8333-333333333333",
"table_id": "22222222-2222-4222-8222-222222222222",
"status": "open",
"staged_count": 2,
"replace_filter": null,
"error": null,
"created_at": "2026-08-20T00:00:00Z",
"expires_at": "2026-08-21T00:00:00Z",
"committed_at": null,
"ticket_id": null
}錯誤
| 狀態 | 發生條件 | 錯誤本文 |
|---|---|---|
| 404 | Session 不存在於此資料表,或屬於另一張資料表。 | |