Files
imks/AGENTS.md
T
zhenyi 0dbac480ae feat(telemetry): integrate OpenTelemetry observability stack with health metrics
- Add OpenTelemetry SDK, OTLP exporter, Prometheus integration
- Implement connection tracking with active/total/disconnection metrics
- Add health endpoint with uptime and connection counts
- Integrate tracing spans for socket events and engine messages
- Add metrics collection for event handling duration
- Update health endpoint to include live runtime state
- Add graceful telemetry shutdown in main function
- Implement engine session active metrics tracking
- Add namespace-specific attributes to connection metrics
- Introduce message edit history retrieval endpoint
- Add scheduled message CRUD operations and dispatcher
- Update Socket.IO event registration with observability
- Refactor component update to remove dead code allowance
- Add comprehensive environment variables documentation
- Implement detailed development guidelines in AGENTS.md
2026-06-11 13:53:29 +08:00

805 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md — 开发规范 / Development Guidelines
> 本文件为所有 AI 编码助手(Claude Code、pi、Cursor 等)提供统一的开发指导。
> This file provides unified development guidelines for all AI coding assistants.
**最后更新 / Last Updated**: 2026-06-11
---
## 目录 / Table of Contents
1. [语言 / Language](#1-语言--language)
2. [代码风格 / Code Style](#2-代码风格--code-style)
3. [禁止模式 / Forbidden Patterns](#3-禁止模式--forbidden-patterns)
4. [错误处理 / Error Handling](#4-错误处理--error-handling)
5. [安全规范 / Security](#5-安全规范--security)
6. [数据库规范 / Database](#6-数据库规范--database)
7. [Socket.IO 事件规范 / Socket.IO Event Conventions](#7-socketio-事件规范--socketio-event-conventions)
8. [日志与可观测性 / Logging & Observability](#8-日志与可观测性--logging--observability)
9. [性能规范 / Performance](#9-性能规范--performance)
10. [测试规范 / Testing](#10-测试规范--testing)
11. [Git 规范 / Git Workflow](#11-git-规范--git-workflow)
12. [工作流程 / Workflow](#12-工作流程--workflow)
13. [架构决策记录 / ADR](#13-架构决策记录--adr)
14. [审查清单 / Review Checklist](#14-审查清单--review-checklist)
---
## 1. 语言 / Language
**Always respond in Chinese (中文).** Use the user's language for all conversations and explanations. Code, commands, and technical terms can remain in English.
始终使用中文回复。代码、命令和技术术语可以保留英文。
---
## 2. 代码风格 / Code Style
### 2.1 基本原则 / Basic Principles
| 规则 | 说明 |
|---|---|
| 遵循现有风格 | Follow existing project conventions |
| 有意义命名 | Use meaningful variable names; avoid single-letter names except loop counters |
| 函数长度 | Keep functions under **50 lines**; split complex logic into smaller functions |
| 嵌套深度 | Maximum nesting depth: **3 levels**; use early returns to flatten logic |
| 注释 | Add comments for complex logic only; prefer self-documenting code |
| 文档注释 | Public items must have `///` doc comments; private items only when logic is non-obvious |
### 2.2 Rust 最佳实践 / Rust Best Practices
```rust
// ✅ 正确 / Correct
fn get_message(id: Uuid) -> Result<Message, sqlx::Error> {
let msg = db.find_message(id).await?; // 使用 ? 传播错误
Ok(msg)
}
// ❌ 错误 / Incorrect
fn get_message(id: Uuid) -> Message {
db.find_message(id).await.unwrap() // 禁止 unwrap()
}
```
| 规则 | 说明 |
|---|---|
| 错误传播 | Use `?` operator for error propagation; never use `unwrap()` or `expect()` in non-test code |
| `unsafe` | Avoid `unsafe` blocks; if necessary, add a `// SAFETY:` comment explaining why |
| `clone()` | Minimize `clone()` usage; prefer references or `Arc` for shared ownership |
| 魔法数字 | No magic numbers; define named constants with `const` |
| 硬编码字符串 | No hardcoded strings for config/status; use enums or constants |
| 死代码 | Remove dead code; don't leave commented-out code blocks |
| 未完成代码 | Don't commit `unimplemented!()`, `todo!()`, or `FIXME` without a tracking issue |
### 2.3 导入规范 / Import Guidelines
```rust
// 标准库 → 第三方 crate → 本地模块
// stdlib → third-party crates → local modules
use std::sync::Arc;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::models::message::Message;
use crate::socket::packet::Packet;
```
### 2.4 模型设计规范 / Model Design Guidelines
imks 的 models 层采用 **一文件一实体** 的拆分策略:
```
models/
├── mod.rs # 模块声明 + 公开 re-export
├── message.rs # 核心 Message + MessageDetail + AuthorInfo + MessageType
├── message_attachment.rs # 附件
├── message_bookmark.rs # 书签/收藏
├── message_draft.rs # 草稿
├── message_edit.rs # 编辑历史
├── message_embed.rs # 富媒体嵌入 + EmbedField
├── message_mention.rs # @提及
├── message_pin.rs # 置顶消息
├── message_poll.rs # 投票 + Option + Vote
├── message_reaction.rs # 表情反应
├── message_read_state.rs # 已读状态
└── message_thread.rs # 消息线程
```
每个模型文件包含:
- Row struct`sqlx::FromRow`
- Summary/detail structAPI 响应用,带 `From` 转换)
- 查询 SQL 常量(`$1, $2...` 占位符)
- `CREATE_TABLE_SQL` 迁移 DDL + 索引
- `#[cfg(test)]` 序列化/转换测试
---
## 3. 禁止模式 / Forbidden Patterns
以下代码模式在项目中严格禁止:
| 禁止项 | 说明 |
|-------------------------------|------------------------------------------------|
| `// ── xxxx ──────────` | 禁止使用此类分隔线注释 |
| `unwrap()` / `expect()` (非测试) | 在非测试代码中禁止使用;使用 `?``unwrap_or` 等安全替代 |
| `panic!()` / `unreachable!()` | 除极少数不可能到达的分支外禁止使用 |
| 未处理的 `todo!()` | 不得提交包含 `todo!()` 的代码,除非有对应的 issue 追踪 |
| 注释掉的代码 | 不得提交被注释的代码块;使用 Git 历史追溯 |
| 过深嵌套 (≥4层) | 使用 early return、`match``map`/`and_then` 扁平化逻辑 |
| 过长函数 (>50行) | 拆分为更小的、职责单一的函数 |
| 魔法数字 | 使用 `const` 定义命名常量 |
| 硬编码字符串 | 使用枚举或常量定义配置值/状态值 |
| 死代码 | 删除未使用的代码、导入和变量 |
| `Box<dyn Error>` 在公共 API | 使用具体错误类型替代 trait object |
---
## 4. 错误处理 / Error Handling
### 4.1 错误类型体系 / Error Type System
imks 使用统一的 `ImksError` 枚举和 `ImksResult<T>` 类型别名,与 appks 的 `AppError`/`AppResult` 保持一致风格。
```rust
// error.rs — 统一错误类型
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ImksError {
// Protocol layer (engine)
#[error("invalid engine packet type: {0}")]
InvalidEnginePacketType(u8),
#[error("invalid engine packet type char: {0}")]
InvalidEnginePacketTypeChar(char),
#[error("empty engine packet")]
EmptyEnginePacket,
#[error("invalid base64: {0}")]
InvalidBase64(#[from] base64::DecodeError),
#[error("invalid utf8 in packet: {0}")]
InvalidPacketUtf8(#[from] FromUtf8Error),
#[error("engine serialization error: {0}")]
EngineSerialization(String),
// Transport upgrade
#[error("session not found for upgrade")]
UpgradeSessionNotFound,
#[error("session already closed, cannot upgrade")]
UpgradeSessionClosed,
#[error("invalid session state for upgrade")]
UpgradeInvalidState,
// Socket.IO layer
#[error("invalid socket packet type: {0}")]
InvalidSocketPacketType(u8),
#[error("invalid socket packet type char: {0}")]
InvalidSocketPacketTypeChar(char),
#[error("empty socket packet")]
EmptySocketPacket,
#[error("invalid socket packet format: {0}")]
InvalidSocketPacketFormat(String),
#[error("missing namespace in socket packet")]
MissingNamespace,
#[error("invalid attachment count in binary event")]
InvalidAttachmentCount,
// Socket namespace
#[error("namespace error: {0}")]
Namespace(String),
#[error("socket not found: {0}")]
SocketNotFound(String),
#[error("failed to send packet to socket: channel full")]
SocketSendFull,
// Adapter layer
#[error("adapter redis error: {0}")]
AdapterRedis(String),
#[error("adapter nats error: {0}")]
AdapterNats(String),
#[error("adapter message bus error: {0}")]
AdapterMessageBus(String),
#[error("adapter serialization error: {0}")]
AdapterSerialization(String),
#[error("adapter room error: {0}")]
AdapterRoom(String),
// Database
#[error("database error: {0}")]
Database(#[from] sqlx::Error),
// gRPC
#[error("gRPC error: {0}")]
GrpcStatus(#[from] tonic::Status),
#[error("gRPC transport error: {0}")]
GrpcTransport(#[from] tonic::transport::Error),
// Serialization
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
// Auth
#[error("auth error: {0}")]
Auth(String),
#[error("token expired")]
TokenExpired,
// General
#[error("not found: {0}")]
NotFound(String),
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("internal error: {0}")]
Internal(String),
}
pub type ImksResult<T> = Result<T, ImksError>;
```
### 4.2 错误处理原则 / Error Handling Principles
| 原则 | 说明 |
|-----------|-------------------------------------------------------------------|
| 统一类型 | 所有公共 API 返回 `ImksResult<T>`,不暴露子模块错误 |
| 显式处理 | Handle all errors explicitly; no silent failures |
| `From` 转换 | 外部库错误通过 `#[from]` 自动转换,减少 `map_err` 样板 |
| 异步传播 | Use `?` operator; don't suppress errors in spawned tasks |
| 通道满 | Handle `mpsc::TrySendError` gracefullybuffer or log),don't panic |
| gRPC 错误 | Map `tonic::Status``ImksError::Grpc` |
### 4.3 错误日志格式 / Error Logging Format
```rust
// 记录错误时包含完整上下文
tracing::error!(
error = %err,
socket_sid = %sid,
event = %event_name,
"Failed to handle socket event"
);
```
### 4.4 现有子模块迁移 / Migration from Submodule Errors
当前部分子模块使用独立的 `thiserror` enum`PacketError``AdapterError`),需要逐步迁移到 `ImksError`
```rust
// 旧 / Old
pub enum PacketError { ... }
pub fn decode(data: &str) -> Result<Packet, PacketError> { ... }
// 新 / New
pub fn decode(data: &str) -> ImksResult<Packet> {
// 内部仍可用 thiserror,对外转为 ImksError
inner_decode(data).map_err(|e| ImksError::Packet(e.to_string()))
}
```
---
## 5. 安全规范 / Security
> 用户认证、授权、密码管理、2FA 等企业级安全由 appks 统一处理。
> imks 作为内部消息服务,仅负责消息层面的安全。
### 5.1 基础安全 / Basic Security
| 规则 | 说明 |
|---------|-----------------------------------------------------------------|
| 密钥管理 | Never hardcode secrets or API keys; use environment variables |
| 输入验证 | Always validate and sanitize user input(消息体、事件名、namespace path |
| SQL 注入 | Use parameterized queriessqlx handles this automatically |
| gRPC 安全 | appks ↔ imks 的 gRPC 连接应使用 mTLS,防止密钥在传输中被截获 |
### 5.2 JWT 验证双模式 / Dual-Mode JWT Verification
imks 支持两种 JWT 验证模式(详见 `rpc.md`):
| 模式 | 方式 | 延迟 | 适用场景 |
|------------|---------------------------------------|-----|------------|
| **RPC 验证** | 调用 appks `TokenService.VerifyToken()` | 实时 | 敏感操作 |
| **本地验证** | 启动时拉取 `GetSigningKeys()` 缓存到本地 | 零延迟 | 高频操作(消息收发) |
推荐策略:普通操作(发消息、读频道)→ 本地验证,敏感操作 → RPC 验证。
### 5.3 连接安全 / Connection Security
| 要求 | 说明 |
|--------|------------------------------------------------|
| 命名空间验证 | 验证 namespace path`/` 开头,≤256 字符,无控制字符),防止 DoS |
| 消息体大小 | 限制单条消息大小(`EngineConfig.max_payload` |
| 速率限制 | 按 socket 限制消息发送频率 |
---
## 6. 数据库规范 / Database
### 6.1 基础规范 / Basic Rules
| 规则 | 说明 |
|---------|------------------------------------------------------------------|
| 参数化查询 | Always use parameterized queries (sqlx does this by default) |
| 迁移规范 | All schema changes must go through migration files in `migrate/` |
| UUID v7 | 所有主键使用 UUID v7(时间有序),便于索引和游标分页 |
| 软删除 | 使用 `deleted_at` 字段进行软删除,不用硬删除 |
| 去规范化 | 对于高频读取的聚合字段(如 `total_votes``unread_count`),可在表中冗余存储 |
### 6.2 imks 管理的数据库表 / imks-Managed Tables
imks 仅管理消息相关表,用户/频道/成员/权限等由 appks 核心服务管理。
| 表 | 对应模型文件 | 说明 |
|-----------------------|--------------------------------|-------------------|
| `message` | `models/message.rs` | 核心消息表(由 appks 创建) |
| `message_attachment` | `models/message_attachment.rs` | 文件附件 |
| `message_embed` | `models/message_embed.rs` | 富媒体嵌入 |
| `message_embed_field` | `models/message_embed.rs` | 嵌入字段 |
| `message_poll` | `models/message_poll.rs` | 投票 |
| `message_poll_option` | `models/message_poll.rs` | 投票选项 |
| `message_poll_vote` | `models/message_poll.rs` | 投票记录 |
| `message_pin` | `models/message_pin.rs` | 置顶消息 |
| `message_read_state` | `models/message_read_state.rs` | 已读状态 |
| `message_draft` | `models/message_draft.rs` | 草稿 |
| `message_edit` | `models/message_edit.rs` | 编辑历史 |
### 6.3 性能优化 / Performance Optimization
| 规则 | 说明 |
|-------------|---------------------------------------------------------------------------------|
| N+1 防护 | Use `JOIN` or batch queries instead of N+1 patterns |
| 游标分页 | Use UUID v7 cursor-based pagination`WHERE id < $3 ORDER BY id DESC`),不用 OFFSET |
| 索引规范 | Add indexes for frequently queried columns; document index rationale |
| ON CONFLICT | Use `INSERT ... ON CONFLICT` for upsert patternsdraft、read_state |
---
## 7. Socket.IO 事件规范 / Socket.IO Event Conventions
### 7.1 事件命名 / Event Naming
imks 使用 Socket.IO 协议进行实时通信,事件名遵循以下约定:
```
// 客户端 → 服务端(发送操作)
"message:send" // 发送消息
"message:edit" // 编辑消息
"message:delete" // 删除消息
"typing:start" // 开始输入
"typing:stop" // 停止输入
"reaction:add" // 添加反应
"reaction:remove" // 移除反应
// 服务端 → 客户端(推送事件)
"message:new" // 新消息
"message:updated" // 消息已更新
"message:deleted" // 消息已删除
"typing" // 用户输入状态
"reaction:updated" // 反应已更新
"presence:update" // 在线状态变更
```
### 7.2 事件数据结构 / Event Data Structure
```json
// 客户端发送消息事件
// Client sends: "message:send"
{
"channel_id": "01909a...",
"body": "hello world",
"thread_id": null,
"reply_to_message_id": null
}
// 服务端广播新消息
// Server broadcasts: "message:new"
{
"id": "01909b...",
"channel_id": "01909a...",
"author": { "id": "...", "username": "alice" },
"body": "hello world",
"created_at": "2026-06-11T10:00:00Z",
"reactions": {},
"attachment_count": 0
}
```
### 7.3 房间(Room)机制 / Room Mechanism
```rust
// channel_id 作为房间名,频道内消息只广播给加入该房间的 sockets
// Use channel_id as room name; messages broadcast only to sockets in that room
namespace.emit_to_room(&channel_id, "message:new", message_data).await;
```
### 7.4 适配器(Adapter)模式 / Adapter Pattern
imks 通过 Adapter trait 支持水平扩展,将 Socket.IO 事件广播到多节点:
```
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Node 1 │────→│ NATS / │←────│ Node 2 │
│ (imks) │ │ Redis │ │ (imks) │
└─────────┘ └─────────┘ └─────────┘
```
| Adapter | 适用场景 |
|---|---|
| `LocalAdapter` | 单节点开发/测试 |
| `RedisAdapter` | 生产环境 Redis Pub/Sub |
| `NatsAdapter` | 生产环境 NATS(更低延迟) |
---
## 8. 日志与可观测性 / Logging & Observability
### 8.1 日志规范 / Logging Standards
```rust
// 使用 tracing crate 进行结构化日志
use tracing::{info, warn, error, debug};
info!(
socket_sid = %socket.sid,
engine_sid = %socket.engine_sid,
namespace = %namespace.path,
"Socket connected"
);
warn!(
socket_sid = %sid,
"Adapter register error: {}",
e
);
error!(
error = %err,
engine_sid = %sid,
"Failed to handle engine message"
);
```
| 级别 | 用途 |
|---------|-------------------------------------|
| `error` | 错误需要立即关注(连接失败、数据库错误) |
| `warn` | 异常但可恢复的情况(adapter 注册失败、socket 发送失败) |
| `info` | 关键业务操作记录(连接/断开、命名空间创建) |
| `debug` | 开发调试信息(数据包收发详情) |
| `trace` | 详细执行路径 |
### 8.2 关键指标 / Key Metrics
| 指标 | 说明 |
|------------|-----------------------------------------------------|
| 活跃连接数 | Active WebSocket + Polling + WebTransport sessions |
| 消息吞吐量 | Messages sent/received per second |
| 广播延迟 | P50/P95/P99 broadcast latency across nodes |
| 事件处理延迟 | Event handling time (receive → broadcast → deliver) |
| Adapter 延迟 | NATS/Redis broadcast delay between nodes |
| 连接错误率 | Connection failure rate |
| 数据库查询延迟 | Message insert/select latency |
### 8.3 健康检查 / Health Check
```json
// GET /health
{
"status": "healthy",
"version": "0.1.0",
"uptime": 3600,
"checks": {
"postgres": { "status": "up", "latency_ms": 5 },
"redis": { "status": "up", "latency_ms": 2 },
"nats": { "status": "up", "latency_ms": 1 },
"appks_grpc": { "status": "up", "latency_ms": 3 }
}
}
```
---
## 9. 性能规范 / Performance
### 9.1 实时消息 SLA / Real-time Messaging SLA
| 指标 | 目标 |
|--------------|---------------|
| 消息端到端延迟(P50 | <50ms |
| 消息端到端延迟(P95 | <200ms |
| 消息端到端延迟(P99 | <500ms |
| 连接建立时间 | <100ms |
| 消息吞吐量(单节点) | >10,000 msg/s |
| 错误率 | <0.1% |
### 9.2 性能原则 / Performance Principles
| 原则 | 说明 |
|------|---------------------------------------------------------------------|
| 零拷贝 | Minimize data copying; use references where possible |
| 批量操作 | Batch adapter broadcasts; use pipelining for Redis |
| 无锁优先 | Use `DashMap` (lock-free) for hot-path data; `RwLock` for cold-path |
| 背压控制 | Use bounded `mpsc::channel` (256) to prevent memory blowout |
| 连接复用 | Reuse gRPC channels to appks |
### 9.3 优化策略 / Optimization Strategies
| 场景 | 策略 |
|---------|----------------------------------|
| 跨节点广播 | NATS<1ms P50)优于 Redis~2ms P50 |
| 消息持久化 | 异步写入 + 批量 COMMIT |
| 会话查找 | `DashMap` 直接查找,无锁竞争 |
| gRPC 调用 | 连接池 + 本地密钥缓存减少 RPC 往返 |
---
## 10. 测试规范 / Testing
### 10.1 基础要求 / Basic Requirements
| 规则 | 说明 |
|--------|-------------------------------------------------------------|
| 新功能 | All new features must have unit tests |
| Bug 修复 | Bug fixes must include regression tests |
| 模型测试 | All model files must have serialization/conversion tests |
| 测试隔离 | Tests must be independent and not depend on execution order |
### 10.2 测试命令 / Test Commands
```bash
cargo test # 运行所有测试
cargo test --lib # 仅运行 lib 测试
cargo test models:: # 运行 models 模块测试
cargo test socket::parser:: # 运行 socket parser 测试
cargo test -- --nocapture # 显示输出
```
### 10.3 测试文件组织 / Test File Organization
```
tests/
├── engine_io_tests.rs # Engine.IO 协议测试
├── socket_io_tests.rs # Socket.IO 协议测试
├── adapter_tests.rs # Adapter 测试
└── session_tests.rs # 会话管理测试
# 单元测试 (inline)
models/message.rs → #[cfg(test)] mod tests { ... }
models/message_poll.rs → #[cfg(test)] mod tests { ... }
socket/parser.rs → #[cfg(test)] mod tests { ... }
engine/codec.rs → #[cfg(test)] mod tests { ... }
```
---
## 11. Git 规范 / Git Workflow
### 11.1 提交信息格式 / Commit Message Format
使用 Angular 风格,全部英文:
```
<type>(<scope>): <subject>
[optional body]
[optional footer]
```
| Type | 说明 |
|------------|--------|
| `feat` | 新功能 |
| `fix` | Bug 修复 |
| `refactor` | 重构 |
| `docs` | 文档 |
| `test` | 测试 |
| `chore` | 构建/工具 |
| `perf` | 性能优化 |
| `style` | 代码格式 |
**示例 / Examples:**
```
feat(models): add MessagePin, MessageReadState, MessageDraft, MessageEdit models
fix(socket): handle namespace validation on connect
refactor(engine): extract session store to dedicated module
docs(readme): add architecture overview
test(parser): add edge cases for binary event decoding
chore(deps): update tonic to 0.14
```
### 11.2 提交原则 / Commit Principles
| 原则 | 说明 |
|--------|----------------------------------------------------------|
| 原子提交 | Each commit should address one concern |
| 完整性 | Each commit should leave the codebase in a working state |
| 禁止强制推送 | Never force push to main branch |
| 提交前检查 | Run `cargo check` and `cargo test` before committing |
### 11.3 分支策略 / Branch Strategy
| 分支 | 用途 |
|-------------|--------|
| `main` | 生产就绪代码 |
| `feat/*` | 功能开发 |
| `fix/*` | Bug 修复 |
| `release/*` | 发布准备 |
---
## 12. 工作流程 / Workflow
### 12.1 开发流程 / Development Process
1. **理解先于编写** — Read before write; understand context first
2. **最小变更** — Minimal changes; don't refactor unrelated code
3. **验证变更** — Verify after changes; run tests or check output
4. **文档同步** — Update documentation when changing public APIs
### 12.2 AI 助手工作规范 / AI Assistant Guidelines
| 规则 | 说明 |
|--------|-----------------------------------------------------|
| 先读后写 | Always read existing code before making changes |
| 最小侵入 | Make minimal changes; don't refactor unrelated code |
| 验证结果 | Run `cargo check` or `cargo test` after changes |
| 解释变更 | Explain what you changed and why |
| 询问不确定 | Ask when unsure about requirements |
| 遵守禁止模式 | Never use `// ── xxxx ──────────` style comments |
### 12.3 常用命令 / Common Commands
```bash
cargo build # 构建
cargo check # 快速检查(推荐开发时使用)
cargo test # 运行测试
cargo test --lib # 仅运行 lib 测试
cargo clippy # Lint 检查
cargo fmt # 格式化
cargo doc --no-deps # 生成文档
```
---
## 13. 架构决策记录 / ADR
架构决策记录存放在 `docs/adr/` 目录下,使用 Markdown 格式。
### 当前决策 / Current Decisions
| ADR | 标题 | 状态 |
|---|---|---|
| — | Socket.IO 作为实时通信协议 | Accepted |
| — | UUID v7 作为主键实现游标分页 | Accepted |
| — | 双模式 JWT 验证(本地 + RPC | Accepted |
| — | Adapter 模式支持多节点水平扩展 | Accepted |
| — | 消息表由 appks 管理,imks 仅扩展富内容表 | Accepted |
### ADR 模板 / ADR Template
```markdown
# ADR-NNN: 标题
## 状态
Accepted | Superseded | Deprecated
## 背景
描述问题背景
## 决策
描述做出的决策
## 后果
描述正面和负面影响
```
---
## 14. 审查清单 / Review Checklist
### 代码审查 / Code Review
- [ ] 代码风格符合项目规范(无 `// ──` 分隔线)
- [ ] 没有使用禁止模式(unwrap、panic、todo 等)
- [ ] 错误处理完整(?传播、具体类型)
- [ ] 安全考虑已处理(JWT 验证模式选择正确)
- [ ] 性能影响已评估(无 N+1、无阻塞调用)
- [ ] 测试已添加(model 文件必须有测试)
- [ ] 文档已更新(新 struct 有 doc comment
### PR 审查 / PR Review
- [ ] 提交信息符合 Angular 风格
- [ ] 每个提交只关注一个问题
- [ ] 变更范围合理
- [ ] 没有遗留的 TODO/FIXME
- [ ] `cargo check``cargo test` 通过
### 发布前审查 / Pre-release Review
- [ ] 所有测试通过
- [ ] 无 clippy warning
- [ ] 迁移 SQL 已包含在 `migrate/`
- [ ] 依赖安全审计通过(`cargo audit`
---
## 附录 / Appendix
### 项目架构速查 / Quick Architecture Reference
```
imks — IM 实时消息服务 / Real-time Messaging Service
┌──────────────────────────────────────────────┐
│ imks │
│ │
│ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ engine/ │ │ socket/ │ │
│ │ │ │ │ │
│ │ • websocket │ │ • server (Socket.IO) │ │
│ │ • webtransport│ │ • namespace (rooms) │ │
│ │ • polling │ │ • parser (protocol) │ │
│ │ • session │ │ • adapter (scale-out) │ │
│ │ • packet │ │ ├─ local │ │
│ │ • codec │ │ ├─ redis │ │
│ │ • heartbeat │ │ └─ nats │ │
│ │ • server │ │ • message_bus │ │
│ └─────────────┘ │ • session_store │ │
│ └─────────────────────────┘ │
│ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ models/ │ │ pb/ │ │
│ │ │ │ │ │
│ │ 12 个消息 │ │ gRPC client stubs │ │
│ │ 领域模型 │ │ → appks TokenService │ │
│ │ │ │ → appks ChannelService │ │
│ │ message │ │ → appks MemberService │ │
│ │ attachment │ │ → appks PermissionService│ │
│ │ embed/poll │ │ │ │
│ │ reaction │ │ │ │
│ │ thread/pin │ │ │ │
│ │ draft/edit │ │ │ │
│ │ mention │ │ │ │
│ │ bookmark │ │ │ │
│ │ read_state │ │ │ │
│ └─────────────┘ └─────────────────────────┘ │
│ │
│ ┌─────────────┐ │
│ │ migrate/ │ │
│ │ │ │
│ │ SQL 迁移 │ │
│ └─────────────┘ │
└─────────────────────┬────────────────────────┘
│ gRPC
┌──────────────────────────────────────────────┐
│ appks (core) │
│ │
│ TokenService │ ChannelService │ MemberSvc │
│ PermissionSvc │ WebhookSvc │ EmojiSvc │
│ │
│ Postgres (users, channels, members, ...) │
│ Redis (JWT keys, sessions, rate limiting) │
└──────────────────────────────────────────────┘
```
### 基础设施速查 / Infrastructure Quick Reference
| 服务 | 用途 | 协议/库 |
|---|---|---|
| Postgres | 消息数据持久化 | sqlx |
| Redis | Adapter 广播 / 会话存储 | fred |
| NATS | Adapter 广播(低延迟替代) | async-nats |
| appks gRPC | JWT 验证 / 频道/成员/权限查询 | tonic |
### 传输层对比 / Transport Comparison
| 传输 | 适用场景 | 特点 |
|------------------|-------------------|--------------------|
| **Polling** | 浏览器不支持 WS 时的降级 | 兼容性最好,延迟高 |
| **WebSocket** | 主流浏览器/移动端 | 全双工,低延迟 |
| **WebTransport** | 现代浏览器(Chrome 97+) | 基于 QUIC,多路复用,不队头阻塞 |
---
*This document is maintained by the development team. For questions or suggestions, please open an issue.*