消费与责任链:jawn 如何把一条队列消息加工成结构化日志
30 秒导读: 边缘代理把每次 LLM 调用塞进队列后(见 02),后端服务 jawn 要把这条又生又乱的原始消息,加工成能落库、能算钱、能触发 webhook 的结构化日志。它的做法是一条 14 环的责任链(chain-of-responsibility):消息像流水线上的工件,依次经过认证、限流、读体、算成本……每个工位只补一块字段,任何一环判定"此消息不该继续"就地熔断。本章讲清这条流水线的形状和每个工位干什么;真正把数据写进数据库的
LoggingHandler细节留给 04,在线评估/webhook/PostHog 等旁路留给 05。
1. 这是什么(零基础也能懂)
一句话定义
jawn 的消费侧 = "队列 → 结构化日志"的加工车间。 它一头连着队列(Kafka 或 SQS),把边缘代理投进来的原始调用记录成批拉出来,送进一条责任链逐环加工,最后成批写进三处存储。
它解决什么问题
边缘代理(worker)为了不阻塞用户请求,只做了最少的事:把"这次调用长什么样"打包丢进队列就返回了(见 02)。于是队列里的每条消息都是半成品——只有一个 API key 字符串、一份 heliconeMeta、一份 log 元数据,请求/响应的大 body 还躺在 S3 里没读回来,成本没算、模型名没规整、限流没判。
把这些半成品补全成"可查询、可计费、可告警"的成品,就是消费侧的活。
为什么用"责任链"而不是一个大函数
因为加工步骤多、且彼此有顺序约束:得先认证拿到组织身份,才能去 S3 按组织 ID 找 body;得先把 body 读回来解析,才能算 token 和成本;得先算完成本,计费旁路才有数可上报。
把每一步写成一个独立 handler、用 setNext 串起来,好处是:
- 每个 handler 只关心自己那一小块,易读易测(每个都有独立单测)。
- 顺序在一个地方声明清楚(
LogManager),调整流程就是挪一行。