概述
Daemon WebSocket API 为 Daemon 客户端提供持久的双向连接,用于实时接收和处理消息。与 REST API 的轮询模式不同,WebSocket 连接允许 Shannon 将传入消息(来自 Slack、LINE 或系统事件)直接推送到已连接的 Daemon。 该协议的核心是基于 Claim 的消息分发模型:Shannon 将消息广播到所有符合条件的连接,Daemon 竞争获取独占处理权后再进行回复。Endpoint
认证
认证在 WebSocket 升级之前执行,使用与 REST Endpoint 相同的中间件。连接生命周期
1
HTTP 升级
客户端发送
GET /v1/ws/messages 并携带认证 Header。服务端验证凭据后进行协议升级。2
WebSocket 建立
服务端升级为 WebSocket 连接(gorilla/websocket,4KB 读写缓冲区,CheckOrigin 允许所有来源)。
3
连接确认
服务端发送
connected 消息确认连接就绪。4
双向消息通信
双方交换 JSON 消息。服务端分发传入消息;客户端执行 Claim、处理并回复。
5
心跳保活
服务端每 20 秒发送 WebSocket Ping。客户端必须在 60 秒内响应 Pong,否则连接将被关闭。
连接参数
消息信封
所有消息(双向)遵循统一的信封格式:服务端到客户端消息
connected
WebSocket 连接建立后立即发送。
message
分发给客户端处理的入站消息。这是主要的消息类型,携带来自 Channel Webhook(Slack、LINE)或系统事件的消息。
MessagePayload 字段
system
来自 Shannon 的系统级通知。
claim_ack
对客户端 claim 请求的响应,指示 Claim 是否成功。
客户端到服务端消息
claim
请求独占处理某条消息。同一消息只有一个客户端能成功 Claim。
progress
在处理已 Claim 的消息时发送心跳/进度更新。这会延长 Claim 的有效期,防止超时。
reply
发送已 Claim 消息的处理结果。Shannon 会将其路由回来源 Channel(Slack、LINE 等)。
ReplyPayload 字段
disconnect
优雅地关闭连接。
Claim 流程
Claim 流程是分布式消息处理的核心协议。它确保即使多个 Daemon 同时连接,每条消息也只由一个 Daemon 处理。1
消息分发
当消息到达时(通过 Channel Webhook 或系统),Gateway 将其分发给按
tenant:user 索引的所有符合条件的 WebSocket 连接。2
Claim 竞争
每个想要处理该消息的 Daemon 发送包含
message_id 的 claim 请求。3
原子决议
Gateway 在 Redis 中原子地执行 Claim(
SETNX)。第一个客户端获胜;其他客户端收到 {"granted": false}。4
消息处理
获胜的 Daemon 处理消息。可以选择发送
progress 消息来延长 Claim 有效期并报告处理进度。5
发送回复
Daemon 发送包含处理结果的
reply。Shannon 将其路由回来源 Channel。Claim 元数据
当消息被 Claim 时,Gateway 在 Redis 中存储元数据,TTL 为 60 秒:待处理消息元数据的 TTL 为 90 秒。如果已 Claim 的消息在 60 秒内未回复,Claim 将过期,消息可被重新分发。
Hub 架构
WebSocket Hub 管理所有活跃连接,采用以下路由策略:- Tenant-User 索引 — 连接按
"tenant:user"键索引,实现定向分发 - 线程粘性路由 — 来自同一线程(
"channel_type:thread_id")的消息尽可能路由到同一连接 - Redis 支持的 Claim — 分布式 Claim 决议确保多个 Gateway 实例间的一致性
回复路由
当 Gateway 收到 Daemon 的reply 时,根据 Claim 元数据路由响应:
- Workflow 回复 — 如果 Claim 元数据中存在
workflow_id,Gateway 会通过 Signal 通知关联的 Temporal Workflow - Channel 回复 — 否则,回复被路由回来源 Channel(Slack 消息、LINE Push 消息等)
错误处理
下一步
Channels API
管理 Slack 和 LINE 的 Channel 集成
流式
通过 Server-Sent Events 进行任务流式传输