新闻详情

新闻详情

首页 / 资讯中心 / 详情

Chatto一条消息的完整旅程:从CreateMessage到实时投递与持久化Worker全链路剖析

发布时间:2026/10/1 15:27:33来源:尧图网络
Chatto一条消息的完整旅程:从CreateMessage到实时投递与持久化Worker全链路剖析
Chatto一条消息的完整旅程从CreateMessage到实时投递与持久化Worker全链路剖析【免费下载链接】chattoA fully-featured team and group chat application that you can easily selfhost.项目地址: https://gitcode.com/gh_mirrors/chatt/chattoChatto 是一款功能完整、可自托管的团队与群组聊天应用chat application。当你按下回车发出第一条消息时背后发生了一次跨越API 网关 → 权限校验 → 事件溯源提交 → NATS JetStream 持久化 → WebSocket 实时投递 → 异步 Worker的全链路旅行。这篇文章用最少的代码、最多的直觉带你走完全程 。一、整体架构为什么是事件溯源 NATS JetStream理解消息旅程前先记住 Chatto 的三个架构基石详见 docs/ARCHITECTURE.md基石作用事件溯源Event Sourcing消息不是写一行数据库记录而是向 EVT 事件流追加一条不可变事实NATS JetStream 作为主存储所有持久化事实都写入EVT流同时充当审计日志与投影来源ADR-001逐用户加密 加密擦除消息正文以加密形式存储账号删除即可粉碎全部数据ADR-007一句话概括消息 一次追加事件append投递 一次流式扇出fanout通知和视频处理 事后异步 Worker。二、第一站CreateMessageAPI 接收请求前端通过 ConnectRPC 调用MessageService.CreateMessage。请求里带着房间 ID、正文、附件资产 ID、线程根消息、链接预览令牌等信息。入口实现在 messages.go它只做三件轻事确认调用者身份requireCaller把传输层参数转成核心层输入交给MessageModel.PostMessage拿到提交后的事件水合hydrate成可直接渲染的Message资源返回给调用者。注意这一步返回给你的消息和你稍后在实时流里收到的是同一条事件的两个视图——先读后写read-your-writes不靠轮询靠的就是这次同步返回。三、第二站权限校验与预检Preflight真正的决策逻辑集中在 message_model.go 的PostMessage中它分两阶段把关3.1 授权Authorization你必须是房间成员需要message.post普通发言、message.post-in-thread线程回复等对应权限带附件还须通过CanAttachFiles检查线程回复会额外检查线程根归属与读权限。3.2 输入预检PreflightPost在上传任何二进制附件之前先验证正文长度上限、in_reply_to目标存在且是消息、链接预览格式、线程根不是嵌套回复等message_model.go。为什么要预检如果先上传了 100MB 视频才告诉你没权限那笔存储开销就白费了。一个有趣的细节如果房间开启了仅线程模式顶层发言会被自动改写成创建新线程applyAutomaticThreadCreation。四、第三站提交事件到 EVT 流OCC 与原子批量写入核心写入在 messages.go 的ChattoCore.PostMessage。这里发生的是整条链路里最硬核的一步 一条消息 一个原子事件批次一条带附件的线程回复实际会在一个原子 OCC 批次里同时提交message_body加密后的正文ADR-011 将正文与帖子拆成两个事件便于编辑时安全擦除旧正文message_posted帖子事实线程回显如勾选同时发送到频道的第二条message_postedthread_created若是新线程每个附件的asset_attached视频资产的asset_processing_started为第五站的 Worker 埋下工作单。任何一项发生冲突整批回滚重试——要么全成要么全不成。 OCC乐观并发控制写入时校验我读到的房间状态是否还是最新乐观并发控制ADR-016。并发发同一房间的两条消息不冲突但 Slow Mode 下同一作者的并发发言会触发整批重试。授权决策在提交时再跑一次防止检查通过到提交之间权限被撤。 物理写入evtstream.Publisher 用 protobuf 编码事件由通用框架 encoded_event_log.go 以不透明字节写入EVT流Subject 形如evt.room.{roomId}.message_posted完整清单见 subjects-and-events.md。五、第四站实时投递——从 Republish 到 WebSocket消息持久化的同一瞬间JetStream 的RePublish配置会把已提交事件转发到live.evt.主题——这就是实时与持久化共享同一条事实流的关键ADR-094 区分了持久事件与瞬时 pubsub 事件两种信封。5.1 进程级事件中枢MyEventsHub每个 Chatto 进程只维护两条NATS 订阅live.evt.与live.sync.而非每个用户一条ADR-049。中枢负责等待本地投影就绪保证授权判断基于最新成员/权限状态逐用户授权过滤非房间成员、没有message.read权限的人直接看不到这条消息把同一份不可变事件扇出到各用户会话队列——慢客户端只会被单独断开不影响他人。5.2 WebSocket 协议 4/api/realtime客户端收到的是二进制 protobuf 的RealtimeEvent公共事件联合ADR-093消息事件自带body_plaintext明文正文供立即展示——EVT 里存的永远是密文。协议 4 还提供有界重放ADR-091断线重连时凭 15 分钟有效期的加密游标补齐缺口游标失效则回落到全量快照绝不半截重放后静默跳过。详见 realtime-delivery.md。六、第五站客户端投影与消息对账前端收到实时事件后并不是直接贴上去就完事用事件里的 ID、作者、明文正文先插入临时时间线行秒级可见TimelineSync 把受影响的消息 ID 收集 10 毫秒再用BatchGetMessages一次批量读取权威资源同一份权威消息同时刷新房间时间线、线程面板、文件页与置顶列表。这个临时行 批量对账设计让消息既快乐观渲染又准以服务端投影为准ADR-048。七、幕后 Worker通知物化与视频处理消息提交不等待给 N 个收件人发通知也不等待视频转码——这两件事都交给持久化 Worker 异步完成durable-effects.mdWorker触发事实做什么通知物化器chatto-notification-materializer-v1帖子事实 当前投影派生提及/回复通知写入 90 天期的NOTIFICATIONS流确认输出持久化后才确认源事件推送投递器chatto-notification-alert-delivery-v1notifications.signalled校验 DND、订阅归属后走 Web Push写入终态alert_resolved资产处理单元asset-processingruntime unitasset_processing_started运行 ffmpeg 生成缩略图与 HLS 分段上传后发布终态清单所有 Worker 都由框架模块 durable_worker.go 提供有界拉取消费者执行进度心跳、延迟重试、毒丸终止、崩溃重投递、多副本共享投递ADR-069。也就是说进程崩溃后未完成的视频转码和通知会自己长回来。八、一图流一条消息的一生按下回车 → CreateMessage (ConnectRPC) 确认身份、转换参数 → Preflight 授权 成员/权限/Slow Mode 预检 → 原子批次写入 EVT 流 正文密文 posted 附件 线程事实OCC → Republish → live.evt. 持久化即实时源 → MyEventsHub 扇出 逐用户授权 → 会话队列 → WebSocket /api/realtime 明文正文即时渲染 → 客户端批量对账 临时行替换为权威消息 → 异步 Worker 通知物化 / Web Push / 视频转码九、延伸阅读源码导航 想动手验证这些路径值得收藏API 入口cli/internal/connectapi/messages.go消息模型与授权cli/internal/core/message_model.go核心事件写入cli/internal/core/messages.go事件发布器cli/internal/evtstream/publisher.go事件日志框架Apache-2.0 共享模块pkg/events/encoded_event_log.go实时事件协议proto/chatto/realtime/v1/实时投递架构文档docs/architecture/realtime-delivery.md主题与事件清单docs/architecture/subjects-and-events.md持久化效果Worker清单docs/architecture/durable-effects.md写在最后Chatto 的消息链路把正确性事件溯源 OCC 原子批次、实时性进程级中枢 有界重放和可靠性崩溃可恢复的持久化 Worker拆成了三个各司其职的层。看懂这一条消息的旅程你就基本看懂了整个 Chatto 服务端。【免费下载链接】chattoA fully-featured team and group chat application that you can easily selfhost.项目地址: https://gitcode.com/gh_mirrors/chatt/chatto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Rust所有权详解:Move、Borrow与Lifetime图解 2026/10/1 18:45:03

Rust所有权详解:Move、Borrow与Lifetime图解

刚接触 Rust 的人,十有八九第一道坎就是所有权。我记得自己第一次遇到borrow of moved value这个错误时,整个人是懵的:我明明只是把一个变量赋值给了另一个变量,凭啥原来那个就不能用了?后来又陆续被借用检查器教育了无…

阅读更多 →
KMP算法详解:从next数组手推到代码实现,彻底搞懂字符串匹配 2026/10/1 18:45:03

KMP算法详解:从next数组手推到代码实现,彻底搞懂字符串匹配

我在学习字符串匹配的时候,第一次接触 KMP 算法,说实话是有心理阴影的。网上帖子看了不少,next 数组的计算方法五花八门,有说从 1 开始的,有说从 0 开始的,还有说整体右移再补负一的,同一段代码…

阅读更多 →
综合能源系统多能流计算:统一牛顿-拉夫逊求解与Matlab实践 2026/10/1 18:45:03

综合能源系统多能流计算:统一牛顿-拉夫逊求解与Matlab实践

先说两句题外的。 “区域综合能源系统电气热能流计算”这个名字看着吓人,拆开之后做的事情其实很单纯:一个网络里同时跑着电、天然气、热三种能量,我们要把它们的稳态分布一次性算出来。传统电力潮流算的是电压和相角,气网算的是…

阅读更多 →
DirectX9c示例包实战:从zip解压到D3D9渲染环境搭建 2026/10/1 18:44:56

DirectX9c示例包实战:从zip解压到D3D9渲染环境搭建

简介:DirectX 9c初始化示例项目,面向DirectX 9初学者和传统游戏编程爱好者,展示如何通过Visual Studio 2012搭建基础游戏框架并完成Direct3D初始化。资源包共8个文件、仅5KB大小,涵盖cpp源码、vcxproj工程配置、filters源文件组织…

阅读更多 →
Qoder AI IDE 完全上手:安装配置、Credits计费与高效开发实战 2026/10/1 18:44:55

Qoder AI IDE 完全上手:安装配置、Credits计费与高效开发实战

Qoder 这段时间在开发者圈子里讨论度挺高,特别是前端和全栈方向的朋友,很多从 Codex 或 Cursor 转过来的。我自己的主力编辑器从 VS Code 切到 Qoder 已经跑了两个多月,中间踩过不少坑,也摸清了它那套 credits 和模型调度的脾气。…

阅读更多 →
Hindsight 智能体记忆:MCP 协议与 Docker 部署实战 2026/10/1 18:44:42

Hindsight 智能体记忆:MCP 协议与 Docker 部署实战

1. 从“hindsight”这个词说起:为什么它值得单独拿出来聊 第一次看到“hindsight”作为项目名,我脑子里蹦出来的不是词典释义,而是自己踩过的一个坑。早些年做对话系统,用户问“我上周说的那个偏好还算数吗”,系统一脸…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉