搜尋完整文件

輸入關鍵字,例如 idempotency、proposal lifecycle 或權限。

選擇 開啟
English
瀏覽文件

Relay · Limits

限制、錯誤與 backpressure

Relay 會在執行 conversation action 前拒絕超出限制的工作。Client 應依回傳的 retry window 等待;send result 不確定時保留原 message nonce;authorization 或 validation failure 則應視為狀態問題,不是單純的 transport failure。

目前的 default budget

以下是目前的 self-hosted default。Deployment operator 可以為每個 tenant 取代這些設定。

BudgetScopeDefault
Message writeTenant 內單一 user每秒 10 次
Message write整個 tenant每秒 100 次
WebSocket frameChannel 內單一 user每秒 30 次
WebSocket joinUser 的獨立 join scope每秒 30 次
Attachment presignTenant 內單一 user每分鐘 30 次
Attachment presign整個 tenant每分鐘 600 次
Attachment download URLTenant 內單一 user每分鐘 120 次
Search queryTenant 內單一 user每分鐘 60 次
Search query整個 tenant每分鐘 600 次
Host credential syncTenant每秒 20 次
Host credential syncSource IP每秒 60 次
Outbound host webhookTenant 與 destination URL每秒 50 次

Message write budget 適用於 REST message create、edit、retract、pin、unpin 與 reaction mutation。WebSocket message send、edit、retract 與 reaction event 使用相同的 user 與 tenant budget,並額外套用 per-channel frame budget。Pin 與 unpin event 只使用 frame budget。

Channel creation、membership change、channel close、metadata update、notification mute 與一般 read 目前沒有共用的 general request budget。Search 與 attachment operation 使用各自的 limit。

REST rate-limit response

Message、search、upload 或 download request 超過限制時,回傳 429 Too Many Requests

HTTP/1.1 429 Too Many Requests
Retry-After: 2
Content-Type: application/json

{
  "error": "rate_limited"
}

Retry-After 是由剩餘 window 向上取整的秒數。至少等待這段時間再 retry。

Host credential sync 也會回傳 429,但目前使用 errors array,且沒有 Retry-After。這是 response consistency gap,不是另一種 retry guarantee。

WebSocket rate-limit response

Channel 內的 event 會以毫秒回傳等待時間:

{
  "error": "rate_limited",
  "retry_after_ms": 847
}

這個 shape 適用於 message write,以及 cursor update、pin、thread read、typing indicator 等受 frame limit 的 event。

Channel join 超過限制時只回傳:

{
  "reason": "rate_limited"
}

Join response 沒有 retry value。再次 join 前應使用帶 jitter 的 backoff,不能形成 tight reconnect loop。

常見 HTTP status code

Status意義Client action
400Admin 或 operator request 格式錯誤修正 request shape
401Credential 缺少、過期、撤銷或無效Refresh 或更換 credential
403Actor 缺少 membership 或 permissionRetry 前重新驗證 host authorization
404Resource 不存在,或被 tenant 與 resource scope 隱藏不能假設另一個 tenant 內存在該 resource
409Resource lifecycle 與 operation 衝突決定下一步前先 refresh current state
410Attachment 已 tombstone移除過期的 attachment reference
422Domain validation 失敗修正 payload 或 product state
429Rate budget 已耗盡等待 retry window
500Relay 無法完成 requestOperation 有 idempotency strategy 時才 retry

大部分 conversation endpoint 使用 array 回傳 error:

{
  "errors": ["forbidden"]
}

Rate-limit、search 與 attachment controller 則使用 singular error field。Client 目前必須支援兩種 envelope。Unified error code 與 response schema 尚未實作。

依 operation 決定 retry

Message creation 遇到 timeout、disconnect、429 或可重試的 5xx 時,保留原 nonce。如果第一次 attempt 已 commit,Relay 會回傳既有 message,不會建立第二則。

Read operation 可以在等待指定 window 後 retry。Edit、reaction、membership change、channel lifecycle action 與 attachment operation 則應先判斷上一次 attempt 是否 commit,因為這些 operation 不一定提供 client idempotency key。

不要用完全相同的條件 retry 401403404409422。Credential、permission、resource、lifecycle 或 payload condition 必須先改變。

Operator override

Operator 可以透過 admin API 取代 tenant 的 stored override:

PUT /api/admin/tenants/{tenant_id}/rate_limits
X-Admin-Token: <admin-token>
Content-Type: application/json

{
  "rate_limits": {
    "user_message": {
      "scale_ms": 1000,
      "limit": 20
    },
    "tenant_message": {
      "scale_ms": 1000,
      "limit": 200
    }
  }
}

這個 request 會取代完整 override map。Omitted budget 會使用 deployment default。傳入 empty map 會清除所有 override。每個 value 都必須包含正整數 scale_mslimit field。

這個 endpoint 需要 deployment admin token,不是 tenant self-service control plane。

Backpressure boundary

超過限制的 synchronous REST 與 WebSocket operation,會在 conversation action 執行前被拒絕。Relay 不會把這些 client request 排入 queue 延後執行。

Post-commit WebSocket fan-out、host webhook delivery、search indexing 與 adapter egress 使用 durable internal handoff。Outbound budget 耗盡的 host webhook 會延後,不會立刻 drop。這能保護 request latency,但不保證 maximum delivery delay。

Message order 仍以 channel-local seq 為準,不能使用 worker completion 或 webhook arrival order。

Product boundary

目前的 limiter 使用 node-local ETS counter。Multi-node deployment 中,每個 Relay node 各自計數,因此上表不是 cluster-wide aggregate ceiling。

Cluster-wide rate accounting、channel 與 membership operation 的完整 coverage、統一的 error envelope、標準化 limit 與 remaining header,以及 WebSocket join 的 retry value 仍屬於 product work。

這些 default 描述目前的 deployment behavior,不代表 managed-service quota 或 SLA。