07 — flare-im-core 业务扩展点与 API 接入
1. 结论
flare-im-core 的业务扩展必须走显式扩展面,不允许核心服务直接依赖业务 crate。生产推荐按能力类型选择接入方式:
| 类型 | 接入面 | 适用场景 | 是否影响主链 |
|---|---|---|---|
| 生命周期校验 | HookPlugin.Call / PreSendHook | 好友关系、黑名单、内容风控、租户策略 | pre_send 可拒绝 |
| 生命周期旁路 | post_send / delivery / recall Hook | 审计、指标、合规归档、运营分析 | 默认不阻塞 |
| 命令/查询扩展 | ExtensionPlugin.Call / CapabilityService.Dispatch | 链接预览、翻译、业务查询、管理操作 | 由调用方决定 |
| 同步扩展 | SyncService.ExecuteSync + 注入端口 | 群目录、通讯录、用户资料增量 | 不改消息 seq |
| 写后投影 | 业务 Domain Event + bridge | Social 写成功后建会话、发系统消息 | 业务侧控制 |
| 业务接入埋点 | BusinessProbeEvent / BusinessProbeSink | BI、审计、计费、推荐、风控特征 | 不阻塞 |
| HTTP BFF | flare-api-gateway | App/管理后台访问 Core 能力 | 只做边界适配 |
核心约束:
request_id负责幂等和追踪,不等于message_id。message_id是消息全局标识,不等于会话内seq。seq只由 IM Core 在会话维度分配,业务服务不得生成或回退。cursor用于读模型同步,不得替代消息seq。- 所有服务间调用必须透传
Ctx:x-trace-id、x-request-id、x-tenant-id、x-user-id。
2. 扩展点清单
| 扩展点 | Proto / Trait | 触发时机 | 业务可做 | 禁止事项 |
|---|---|---|---|---|
pre_send | PreSendHookRequest / PreSendHook | 消息校验后、seq 分配前 | 拒绝发送、补充草稿元数据、路由建议 | 分配 seq、直接写消息存储 |
post_send | PostSendHookRequest / PostSendHook | 消息推入主链后 | 审计、统计、合规归档、异步通知 | 依赖其完成后再对客户端确认 |
delivery | DeliveryHookRequest / DeliveryHook | 下行送达后 | 送达指标、渠道分析 | 修改消息事实 |
recall | RecallHookRequest / RecallHook | 撤回流程 | 审计、权限补充检查 | 绕过 MessageActionService |
message_read | MessageReadHookRequest / MessageReadHook | 已读水位更新后 | 已读率、重要消息阅读审计 | 修改游标/未读权威状态 |
message_reaction | MessageReactionHookRequest / MessageReactionHook | reaction 变更时 | 表态白名单、互动统计、推荐特征 | 修改消息内容 |
conversation_lifecycle | ConversationLifecycleHookRequest / ConversationLifecycleHook | 会话状态事实提交后 | 外部目录投影、生命周期审计 | 失败后回滚已提交事实 |
conversation_member | ConversationMemberHookRequest / ConversationMemberHook | 成员变更时 | 成员审计、风控、版本通知 | 把业务目录完整资料写入 Core |
GetConversationParticipantsHook | Rust trait | 需要参与者列表时 | 从业务目录提供成员列表 | 把好友列表当会话参与者 |
CapabilityService.Dispatch | DispatchCapabilityRequest | 显式能力调用 | 业务能力路由 | 替代生命周期 Hook |
ExtensionPlugin.Call | GenericRequest + Any | 显式 operation 调用 | 业务查询/命令插件 | 硬编码到 Core |
SyncService.ExecuteSync | SyncRequest | 客户端同步 | 群目录、通讯录、资料增量 | 混用消息 last_seq |
MessageSendService.SendSystemMessage | gRPC | 业务写后通知 | 系统消息、通知消息 | 业务普通聊天绕过客户端上行链路 |
ConversationManageService | gRPC | 业务目录变化后 | 建会话、成员变更投影 | 在 Social 内维护消息 unread |
ConversationReadService.ListConversationParticipants | gRPC / gateway | 成员页、@ 候选人、参与者增量 | 分页读取 Core 参与者投影 | 把群目录完整业务资料塞入 Core |
BusinessProbeSink | Rust port / MQ adapter | Core 事实观测 | 输出标准业务埋点 | 在 Sink 中反向调用 Core 主链 |
3. HookPlugin API
服务定义:
| 项 | 说明 |
|---|---|
| Package | flare.capability.v1 |
| Service | HookPlugin |
| RPC | Call(GenericRequest) returns (GenericResponse) |
GenericRequest 约定:
| 字段 | 说明 |
|---|---|
operation | Hook 类型,例如 flare.hook.v1.pre_send |
request_id | 幂等键,必须与 metadata 可关联 |
metadata | 轻量路由/灰度/签名字段 |
payload | google.protobuf.Any,内嵌具体 Hook Request |
常用 operation:
| operation | payload | 默认失败策略 |
|---|---|---|
flare.hook.v1.pre_send | PreSendHookRequest | 强校验,推荐 fail-fast |
flare.hook.v1.post_send | PostSendHookRequest | 旁路,推荐 fail-open |
flare.hook.v1.delivery | DeliveryHookRequest | 旁路,推荐 fail-open |
flare.hook.v1.recall | RecallHookRequest | 视权限模型决定 |
flare.hook.v1.message_read | MessageReadHookRequest | 旁路,推荐 fail-open |
flare.hook.v1.message_reaction | MessageReactionHookRequest | 视表态策略决定 |
flare.hook.v1.conversation_lifecycle | ConversationLifecycleHookRequest | 事实后旁路,推荐 fail-open |
flare.hook.v1.conversation_member | ConversationMemberHookRequest | 视成员变更发起方决定 |
pre_send 的业务语义:
- Orchestrator 已完成基础消息校验。
- 尚未分配最终
seq,业务不能依赖seq。 - Hook 可以返回
allow = false拒绝发送。 - Hook 可以回写
draft.metadata或annotations,但必须由宿主决定哪些字段进入持久化事实。 - 业务拒绝应返回机器可读
deny_reason_code,例如SOCIAL_PRESEND_DENIED。
4. Capability / Extension API
CapabilityService 面向能力目录、授权和命令分发:
| RPC | 用途 |
|---|---|
ListCapabilities | 列出当前可用能力 |
ListUserCapabilities | 查询用户可用能力 |
Dispatch | 按 capability_id 分发命令 |
GrantUserCapability / RevokeUserCapability | 授权管理 |
SetTenantCapabilitySwitch | 租户级开关 |
RegisterPluginEndpoint / DeregisterPluginEndpoint | 插件实例注册 |
ExtensionPlugin.Call 面向通用 operation:
| 命名建议 | 示例 |
|---|---|
{domain}.{subsystem}.{action} | social.sync.group_directory |
{domain}.{capability}.v{n}.{action} | link.preview.v1 |
使用原则:
- 能力调用必须带
tenant_id、user_id、conversation_id、request_id。 - 大 payload 不应塞进
payload_json;应先落对象存储或业务存储,再传引用。 - operation 必须版本化或保持向后兼容。
- 长耗时任务应返回 accepted / task_id,不阻塞 IM 主链。
5. 服务间 gRPC API
| API | 归属 | 使用者 | 说明 |
|---|---|---|---|
RouterUpstreamService.RouteMessage | signaling route | 长连接网关 | 客户端上行入口 |
MessageSendService.SendMessage | orchestrator | route / gateway 内部 | 普通消息发送 |
MessageSendService.SendSystemMessage | orchestrator | bridge / 后台 | 系统消息 |
MessageActionService.RecallMessage | orchestrator | gateway / 后台 | 撤回消息 |
ConversationManageService | conversation | bridge / 管理面 | 会话和成员投影 |
ConversationReadService | conversation | gateway / sync | 会话读模型 |
StorageReaderService | storage-reader | query / sync | 历史消息读取 |
SyncService.ExecuteSync | sync-orchestrator | SDK / gateway | 多端同步 |
MediaService | media | gateway / SDK | 媒体上传、处理、引用 |
CapabilityService | capability | gateway / orchestrator | 能力目录和分发 |
HookPlugin | capability / business hook | orchestrator | 生命周期回调 |
ExtensionPlugin | business plugin | capability / 工具面 | 扩展命令/查询 |
6. 扩展接入决策
| 需求 | 推荐接入 | 原因 |
|---|---|---|
| 发送前校验好友/群权限 | pre_send Hook | 必须在 seq 分配前拒绝 |
| 发消息后写审计日志 | post_send Hook | 不影响主链确认 |
| 好友通过后自动创建单聊 | Social Domain Event + bridge | 业务写模型成功后投影 IM |
| 群成员变更同步到会话参与者 | bridge 调 ConversationManageService | 会话投影由 Core 管 |
| 客户端拉群目录增量 | SyncService.ExecuteSync 注入 Social 端口 | 与消息同步解耦 |
| 客户端发现成员变化 | 对比 participant_version 后拉 ConversationParticipants | 大群成员同步不污染消息 seq |
| 业务做 BI/计费/推荐特征 | BusinessProbeEvent + MQ/Hook/Capability | 非侵入式观察 Core 事实 |
| 链接预览 | CapabilityService.Dispatch + message event enrich | 命令型能力,非消息存储 |
| 管理后台调用 Core | flare-api-gateway | 统一认证、错误、返回格式 |
更完整的消息/会话接入点、群体变更和 Core 独立运行策略见 docs/integration/09-message-conversation-access-points.md(内部稿,未在站点发布)。 业务接入埋点模型见 10-business-instrumentation.md。
7. 生产要求
- 幂等:所有写操作使用
request_id或业务事件 ID 去重。 - 顺序:业务不得生成或覆盖消息
seq;会话内顺序只认 Core 分配结果。 - 超时:主链 Hook 超时必须短,
pre_send建议 100-500ms。 - 降级:强一致门禁 fail-fast;审计、指标、通知 fail-open。
- 观测:Hook/Extension 必须输出
trace_id、request_id、tenant_id、operation、耗时、结果。 - 安全:Hook body 里的用户字段不能替代认证;服务端必须从 metadata / token 还原可信身份。