From b3e1140348a13f1fd155a1c8cecad3c8794fca08 Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 9 Oct 2026 00:50:13 +0800 Subject: [PATCH] docs: plan gateway outbound channel replacing inbound dial model --- AGENTS.md | 2 +- docs/gateway-outbound-channel-plan.md | 69 +++++++++++++++++++++++++++ docs/realtime-event-push-plan.md | 4 ++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 docs/gateway-outbound-channel-plan.md diff --git a/AGENTS.md b/AGENTS.md index f75b287..31385d0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,7 +58,7 @@ 账号事件监听:仅支持抖音,自有账号默认关闭,在“我的账号”的“监听状态”列逐个开启,未登录环境不能开启。互动通知复用已验证的抖音网页 NoticeFrontier 实时信号,不另建抖音私有协议客户端;实时信号立即读取详情,历史通知列表仅用于完整核对补漏。网关与后台在原端口通过 `/v1/channel` WS 共享连接推送多账号事件,保存成功后确认,断线重订阅并补送,不保留 HTTP GET 事件轮询回退。历史列表每页 50 条,is_mark_read=0,不标记已读,原始 JSON 在 Python 解码以保留 64 位 ID。只记录点赞、评论、关注、转发,私信在独立收件箱同步与展示,不并入事件聚合,不自动互动。监听依赖已登录且运行中的浏览器;按账号固定页面并核验 UID,支持多标签页。分组读取位置、开启边界和事件在同一事务保存,提交成功后确认,重复投递去重;开关代次拒绝关闭期间的旧投递;首次开启、重新开启和服务重启均补齐平台仍可返回的全部历史和漏收记录,包括关闭期间通知,正常运行约每 5 分钟完整核对一次。开启时间只用于历史标记,不作为丢弃依据,补入保留平台原时间;不按头部位置或 100 页上限截断完整核对。开启设置不等于接收正常,状态应展示实际读取结果、最后成功时间及错误或可能遗漏。左侧“事件聚合”只展示当前已开启账号的已接收互动通知,按发生时间倒序,缺少发生时间置末尾,同时间按事件 ID 倒序,支持账号、类型、接收时间范围筛选和分页,复用现有 creator SSE 通知即时刷新并明确显示断线;关闭后保留历史但隐藏,重新开启后可查看。缺失发生时间不能用接收时间冒充;真实验收必须核对平台、数据库和页面同一通知,不把读取成功或平台合并后的重复互动当作新事件通过。 -网关通信方向:首期仅迁移事件推送与确认,其他 HTTP 业务通信保留;后续全部迁移到同一个 WS 通道,包括控制、状态及文件传输,每项迁移完成即删除对应 HTTP 路由,不保留兼容回退,最终仅保留标准 WS 握手入口、不增加端口。规划见 `docs/realtime-event-push-plan.md`。 +网关通信方向:网关部署在用户内网、公网入站不可达,全部业务通信由网关主动出站建立 WS 连接(`/v1/agent`,key 认证)承载:同步操作创建任务并等待结果(网关离线即失败),异步任务平台持久化积压、上线后补发;事件推送与确认复用同一连接;旧 HTTP 直连与定时探活全部删除,不保留兼容回退。全量任务即执行记录,平台可查每网关任务队列状态。规划见 `docs/gateway-outbound-channel-plan.md`。 事件聚合资料:互动用户仅展示真实昵称,不展示 UID,以平台返回的 secUID 链接主页,不使用数字 UID 猜测主页;列表仅展示发生时间,不展示接收时间列,但保留按接收时间计算的范围筛选。事件类型使用彩色 Tag 区分:点赞粉色、评论蓝色、关注紫色、转发橙色;来源使用彩色 Tag 区分:同步金色、通知青色,保留文字说明。“账号”列置于第一列,列表及筛选选项仅显示昵称。内容列限定在表格宽度内,长文本自动换行并直接完整展示,不截断、不折叠、不提供“展开”入口,不得撑宽页面。对应作品展示 48px 小封面并链接抖音作品详情,图文使用 note 地址;缺封面保留作品入口,缺资料明确标示。通知中的作品封面复用 `<作者 UID>/<作品 ID>.<图片扩展名>` 本地缓存,不创建占位账号或作品,不回退展示远程图片。历史核对可补齐已保存事件的用户与作品资料,但只更新同一互动 UID、同一作品 ID 的资料,不改原事件时间、内容、历史标记或去重规则;封面下载在事件保存后独立处理,不阻塞 WS 接收、保存或确认;只更新同一作品的封面错误并通知页面,不改变事件内容、时间、历史标记或检查点。封面下载失败单独记录和展示,不能阻断通知保存,也不能伪装成已缓存。 diff --git a/docs/gateway-outbound-channel-plan.md b/docs/gateway-outbound-channel-plan.md new file mode 100644 index 0000000..c5f5ddc --- /dev/null +++ b/docs/gateway-outbound-channel-plan.md @@ -0,0 +1,69 @@ +# 网关出站通道规划(反转连接方向) + +取代 `realtime-event-push-plan.md` 的通道方向设计。该文档的事件采集、订阅管理、确认语义继续有效;传输层按本文反转。 + +## 前提修正 + +平台部署在公网,网关部署在用户内网(NAT 后,公网入站不可达)。"后台拨号连网关"(HTTP 直连与 `/v1/channel` WS)在真实部署形态下不可行。只有网关能出站连接平台。 + +## 目标形态 + +- 平台为每个网关签发 `access_key`(网关管理页生成、明文回显供配置)。 +- 网关进程通过环境变量/启动参数配置平台地址与 key,主动出站建立 WS 连接(`/v1/agent`),断线自动重连(退避)。 +- 平台与网关的全部业务通信复用这一条网关发起的连接;旧 HTTP 直连、定时探活整体删除,不留回退。 +- 局域网部署同样成立(网关连平台的内网地址),一套模型覆盖所有形态。 + +## 通道消息 + +平台 ⇄ 网关帧(JSON,单条连接按网关隔离): + +| 方向 | 类型 | 说明 | +| --- | --- | --- | +| 网关→平台 | `hello` | 认证(连接层 Bearer key)后首帧:网关版本、能力 | +| 网关→平台 | `heartbeat` | 周期健康上报:版本、运行中浏览器数;平台据此维护 online/last_seen_at | +| 平台→网关 | `task` | `{id, method, path, payload}`,method/path 复用原 HTTP 语义 | +| 网关→平台 | `result` | `{id, status, body, error}`;网关对重复 task id 幂等拒绝 | +| 网关→平台 | `event` | 事件投递批次(原 deliveries 语义,含 subscription/alias) | +| 平台→网关 | `event_ack` | 平台事务保存成功后确认;未确认批次网关保留、重连后重推 | + +## 统一任务模型 + +所有后台→网关通信都是持久化任务(`gateway_task` 表): + +- 同步操作(前端按钮触发):创建任务 → 网关在线则下发并等待 result(超时明确失败)→ 返回调用方。**网关离线时同步操作立即失败并提示,不入队等待**。 +- 异步任务(采集、事件类):创建任务 → 积压;下发器按网关分组、按 id 序补发,网关上线后执行。 +- 下发后连接中断的任务标记 `failed`(连接中断,结果未确认),不自动重发有副作用的操作;仍为 `pending` 的任务继续等待。 +- 全量任务即执行记录:方法/路径、状态、错误、响应码、耗时;响应体不落库(结果语义在业务表中)。保留策略后续再定(TODO)。 + +## 数据库(迁移 1058) + +- `gateway`:删除 `endpoint`/`health_status`/`last_check_reason`/`last_checked_at`;新增 `access_key`、`online`、`last_seen_at`、`version`。 +- 新表 `gateway_task`:`gateway_id`、`method`、`path`、`payload jsonb`、`status(pending|dispatched|succeeded|failed)`、`response_status`、`error`、`response_bytes`、`timeout_seconds`、创建/下发/完成时间。 +- `browser_env.gateway_id` 等关联不变;账号与网关的绑定关系不变。 + +## 平台侧 + +- fiber `/v1/agent` WS 升级(fasthttp/websocket),连接层 key 认证,单网关单连接会话注册表。 +- `gatewayCall`/`gatewayCallWithLimit` 实现替换为「创建任务 + 等待 result」,签名不变,全部业务调用点代码不动。 +- 事件流:session 收 `event` 帧按 alias 路由到监听 worker,worker 事务保存后回 `event_ack`;原 `/v1/channel` 拨号代码删除。 +- 健康状态由会话维护(在线/离线/从未连接),定时探活代码删除。 + +## 网关侧 + +- 新增出站 agent:连接、认证、重连退避、心跳线程、任务分发线程池、事件推送线程(复用 SubscriptionManager 变更通知与未确认重推)。 +- `_route` 业务分发逻辑抽为纯函数供任务分发调用;HTTP 监听(含 `/healthz`、`/v1/channel`)整体删除;`proxy.py` 数据面保留。 +- 配置:`CREATOR_PLATFORM_URL`、`CREATOR_GATEWAY_KEY` 环境变量(启动参数等价)。 + +## 前端(网关管理) + +- 创建/编辑:名称 + 生成/重置 key(回显平台地址与 key 的配置指引)。 +- 列表:在线状态(在线/离线/从未连接)、版本、任务队列 pending 计数。 +- 执行记录:每网关任务列表分页(时间、方法+路径、状态 Tag、耗时、错误)。 + +## 测试与完成标准 + +- Go:认证/会话/心跳、任务下发等待超时、离线失败、断线中断、pending 补发、result 落库、event 路由与 ack;race 检查。 +- Python:出站连接、认证失败、重连、task 分发(含重复 id 幂等)、result 回传、event 推送与未确认重推、心跳。 +- Web:网关管理改造、执行记录分页;antd lint 清零、build 通过。 +- 迁移 1058:新库、旧库升级、重复启动三态验证。 +- 单元覆盖率 ≥ 65%;不编写/运行 E2E。 diff --git a/docs/realtime-event-push-plan.md b/docs/realtime-event-push-plan.md index 2134a32..4fa13ce 100644 --- a/docs/realtime-event-push-plan.md +++ b/docs/realtime-event-push-plan.md @@ -1,3 +1,7 @@ +# 网关出站通道规划(反转连接方向) + +> 2026-10-08 起本文件保留事件采集/订阅/确认语义部分;通道方向设计已被 `gateway-outbound-channel-plan.md` 取代(网关出站连接,旧直连模式废弃)。 + # 实时事件推送规划 ## 目标与首期边界