gitdataai/room.md

815 lines
22 KiB
Markdown

# Room 模块设计文档
## 1. 概述
`Room` 模块是本系统核心的协作与消息通信功能模块,提供稳定、高效、可扩展的实时消息平台。系统采用 Rust (Actix-web) 后端 + React 19 前端的技术栈,通过 WebSocket 实现实时通信,集成了 AI 代理进行智能协作。
### 技术栈
- **后端**: Rust + Actix-web + SeaORM + Redis + NATS
- **前端**: React 19 + TypeScript + Tailwind CSS
- **实时通信**: WebSocket (自定义协议)
- **消息队列**: NATS (事件分发)
- **缓存**: Redis (序列号管理、去重)
---
## 2. 数据模型
### 2.1 核心表结构
#### `room` - 房间表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID (v7) | 主键,时间排序 |
| project | UUID | 所属项目 |
| room_name | VARCHAR(128) | 房间名称 |
| public | BOOLEAN | 是否公开房间 |
| category | UUID (nullable) | 所属分类 |
| created_by | UUID | 创建者 |
| created_at | TIMESTAMPTZ | 创建时间 |
| last_msg_at | TIMESTAMPTZ | 最后消息时间 |
#### `room_message` - 消息表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID (v7) | 主键 |
| seq | BIGINT | 全局序列号(递增) |
| room | UUID | 所属房间 |
| sender_type | ENUM | `member` / `ai` / `system` |
| sender_id | UUID (nullable) | 发送者 ID |
| thread | UUID (nullable) | 所属线程 |
| in_reply_to | UUID (nullable) | 回复的消息 ID |
| content | TEXT | 消息内容 |
| content_type | ENUM | `text` / `markdown` / `code` / `mention` |
| edited_at | TIMESTAMPTZ (nullable) | 编辑时间 |
| send_at | TIMESTAMPTZ | 发送时间 |
| revoked | TIMESTAMPTZ (nullable) | 撤回时间 |
| revoked_by | UUID (nullable) | 撤回操作者 |
#### `room_member` - 房间成员表
| 字段 | 类型 | 说明 |
|------|------|------|
| room | UUID | 房间 ID |
| user | UUID | 用户 ID |
| role | ENUM | `Owner` / `Admin` / `Member` |
| first_msg_in | TIMESTAMPTZ (nullable) | 首次发消息时间 |
| joined_at | TIMESTAMPTZ (nullable) | 加入时间 |
| last_read_seq | BIGINT (nullable) | 已读序列号 |
| do_not_disturb | BOOLEAN | 免打扰 |
| dnd_start_hour | INT (nullable) | DND 开始小时 |
| dnd_end_hour | INT (nullable) | DND 结束小时 |
#### `room_category` - 频道分类表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| project | UUID | 所属项目 |
| name | VARCHAR(64) | 分类名称 |
| position | INT | 排序位置 |
#### `room_thread` - 线程表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| room | UUID | 所属房间 |
| parent_message | UUID | 父消息 ID |
| created_by | UUID | 创建者 |
| created_at | TIMESTAMPTZ | 创建时间 |
#### `room_ai` - AI 配置表
| 字段 | 类型 | 说明 |
|------|------|------|
| room | UUID | 房间 ID |
| model | UUID | AI 模型 ID |
| version | VARCHAR (nullable) | 模型版本 |
| call_count | INT | 调用次数 |
| last_call_at | TIMESTAMPTZ (nullable) | 最后调用时间 |
| history_limit | INT | 上下文历史限制 |
| system_prompt | TEXT | 系统提示词 |
| temperature | FLOAT | 温度参数 |
| max_tokens | INT | 最大 token 数 |
| use_exact | BOOLEAN | 精确模式 |
| think | BOOLEAN | 思考模式 |
| stream | BOOLEAN | 流式输出 |
| min_score | FLOAT (nullable) | 最小分数阈值 |
#### `room_message_reaction` - 消息反应表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| message | UUID | 消息 ID |
| user | UUID | 用户 ID |
| emoji | VARCHAR(32) | emoji |
| created_at | TIMESTAMPTZ | 创建时间 |
#### `room_pin` - 置顶消息表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| room | UUID | 房间 ID |
| message | UUID | 消息 ID |
| pinned_by | UUID | 置顶者 |
| pinned_at | TIMESTAMPTZ | 置顶时间 |
### 2.2 消息内容类型
```typescript
type MessageContentType = 'text' | 'markdown' | 'code' | 'mention';
type MessageSenderType = 'member' | 'ai' | 'system';
```
---
## 3. WebSocket 通信协议
### 3.1 协议格式
#### 请求
```typescript
interface WsRequest {
type: 'request';
request_id: string; // 唯一请求 ID
action: WsAction; // 操作类型
params?: WsRequestParams;
}
```
#### 响应
```typescript
interface WsResponse {
type: 'response';
request_id: string;
action: string;
data?: WsResponseData;
error?: WsError;
}
```
### 3.2 Action 列表
#### 房间管理
| Action | 说明 | 权限 |
|--------|------|------|
| `room.list` | 获取房间列表 | Member |
| `room.get` | 获取房间详情 | Member |
| `room.create` | 创建房间 | Admin |
| `room.update` | 更新房间 | Admin |
| `room.delete` | 删除房间 | Admin |
| `room.subscribe` | 订阅房间事件 | Member |
| `room.unsubscribe` | 取消订阅 | Member |
#### 消息管理
| Action | 说明 | 权限 |
|--------|------|------|
| `message.list` | 获取消息列表(分页) | Member |
| `message.create` | 发送消息 | Member |
| `message.update` | 编辑消息 | Owner |
| `message.revoke` | 撤回消息 | Owner |
| `message.get` | 获取单条消息 | Member |
| `message.search` | 搜索消息 | Member |
#### 成员管理
| Action | 说明 | 权限 |
|--------|------|------|
| `member.list` | 获取成员列表 | Member |
| `member.add` | 添加成员 | Admin |
| `member.remove` | 移除成员 | Admin |
| `member.leave` | 离开房间 | Member |
| `member.update_role` | 更新角色 | Admin |
| `member.set_read_seq` | 设置已读位置 | Member |
#### 分类管理
| Action | 说明 | 权限 |
|--------|------|------|
| `category.list` | 获取分类列表 | Member |
| `category.create` | 创建分类 | Admin |
| `category.update` | 更新分类 | Admin |
| `category.delete` | 删除分类 | Admin |
#### 线程管理
| Action | 说明 | 权限 |
|--------|------|------|
| `thread.list` | 获取线程列表 | Member |
| `thread.create` | 创建线程 | Member |
| `thread.messages` | 获取线程消息 | Member |
#### 反应管理
| Action | 说明 | 权限 |
|--------|------|------|
| `reaction.add` | 添加反应 | Member |
| `reaction.remove` | 移除反应 | Owner |
| `reaction.list_batch` | 批量获取反应 | Member |
#### 置顶管理
| Action | 说明 | 权限 |
|--------|------|------|
| `pin.list` | 获取置顶列表 | Member |
| `pin.add` | 添加置顶 | Admin |
| `pin.remove` | 移除置顶 | Admin |
#### AI 管理
| Action | 说明 | 权限 |
|--------|------|------|
| `ai.list` | 获取 AI 配置列表 | Member |
| `ai.upsert` | 创建/更新 AI 配置 | Admin |
| `ai.delete` | 删除 AI 配置 | Admin |
#### 通知管理
| Action | 说明 | 权限 |
|--------|------|------|
| `notification.list` | 获取通知列表 | Member |
| `notification.mark_read` | 标记已读 | Member |
| `notification.mark_all_read` | 全部标记已读 | Member |
| `notification.archive` | 归档通知 | Member |
#### 提及管理
| Action | 说明 | 权限 |
|--------|------|------|
| `mention.list` | 获取提及列表 | Member |
| `mention.read_all` | 全部标记已读 | Member |
### 3.3 实时事件推送
```typescript
type WsEventType =
| 'room.created'
| 'room.updated'
| 'room.deleted'
| 'message.created'
| 'message.updated'
| 'message.revoked'
| 'member.joined'
| 'member.left'
| 'member.role_changed'
| 'thread.created'
| 'reaction.updated'
| 'pin.updated';
```
---
## 4. 后端架构
### 4.1 目录结构
```
libs/room/src/
├── lib.rs # 模块入口
├── service.rs # RoomService 主服务
├── room.rs # 房间 CRUD
├── message.rs # 消息管理
├── member.rs # 成员管理
├── category.rs # 分类管理
├── thread.rs # 线程管理
├── reaction.rs # 反应管理
├── pin.rs # 置顶管理
├── ai.rs # AI 配置管理
├── notification.rs # 通知管理
├── search.rs # 搜索功能
├── connection.rs # WebSocket 连接管理
├── room_ai_queue.rs # AI 队列锁
├── error.rs # 错误类型
├── types.rs # 请求/响应类型
├── helpers.rs # 辅助函数
├── metrics.rs # 指标收集
├── ws_context.rs # WebSocket 上下文
└── draft_and_history.rs # 草稿和编辑历史
```
### 4.2 核心服务 RoomService
```rust
pub struct RoomService {
db: DatabaseConnection,
cache: AppCache,
queue: NatsContext,
ai_client: AiClient,
rate_limiter: RateLimiter,
log: Logger,
}
```
### 4.3 并发控制
- **物理并发限制**: `tokio::sync::Semaphore`
- **消息序列号**: Redis INCR 原子递增
- **消息去重**: `DashMap<UUID, HashSet<i64>>` 内存缓存
- **AI 队列锁**: Redis 分布式锁 (`ai:room:queue:lock:{room_id}`)
### 4.4 AI 队列机制
```rust
// Redis 键结构
ai:room:queue:{room_id} // 队列
ai:room:queue:seq:{room_id} // 序号
ai:room:queue:lock:{room_id} // 分布式锁
ai:room:queue:ticket:{room_id}:{ticket_id} // 票据
// 锁参数
LOCK_TTL_MS: 120_000 // 锁超时 2 分钟
TICKET_TTL_MS: 90_000 // 票据超时 1.5 分钟
MAX_BACKOFF_MS: 200 // 最大退避 200ms
```
### 4.5 定时任务
- **空闲房间清理**: 30 天无消息的房间标记为归档
- **频率限制刷新**: 每分钟重置计数
- **陈旧指标清理**: 定期清理过期数据
---
## 5. 前端架构
### 5.1 目录结构
```
src/
├── components/room/
│ ├── DiscordServerSidebar.tsx # 服务器图标侧边栏 (72px)
│ ├── DiscordChannelSidebar.tsx # 可折叠频道列表
│ ├── DiscordChatPanel.tsx # 主聊天面板
│ ├── DiscordMemberList.tsx # 成员列表 (带在线状态)
│ ├── message/
│ │ ├── MessageList.tsx # 消息列表
│ │ ├── MessageInput.tsx # 消息输入框
│ │ ├── MessageBubble.tsx # 消息气泡
│ │ └── MessageActions.tsx # 消息操作菜单
│ ├── RoomThreadPanel.tsx # 线程侧边栏
│ ├── RoomMentionPanel.tsx # 提及面板
│ ├── RoomPinBar.tsx # 置顶栏
│ ├── RoomMessageSearch.tsx # 消息搜索
│ ├── RoomSettingsPanel.tsx # 设置面板
│ ├── RoomAiAuthBanner.tsx # AI 认证提示
│ ├── RoomAiTasksPanel.tsx # AI 任务面板
│ └── ...
├── contexts/
│ └── room-context.tsx # 房间状态管理
└── lib/
└── ws-protocol.ts # WebSocket 协议定义
```
### 5.2 React Context 状态管理
```typescript
interface RoomContextValue {
// 房间状态
rooms: RoomResponse[];
currentRoom: RoomResponse | null;
roomsLoading: boolean;
// 消息状态
messages: MessageWithMeta[];
threads: RoomThreadResponse[];
// 成员状态
members: RoomMember[];
membersLoading: boolean;
// AI 配置
roomAiConfigs: RoomAiResponse[];
// WebSocket 状态
wsStatus: 'open' | 'connecting' | 'disconnected';
wsError: Error | null;
wsClient: WebSocketClient | null;
// 操作方法
sendMessage: (content: string, inReplyTo?: string) => Promise<void>;
editMessage: (messageId: string, content: string) => Promise<void>;
revokeMessage: (messageId: string) => Promise<void>;
updateRoom: (roomId: string, data: Partial<RoomUpdateRequest>) => Promise<void>;
refreshThreads: () => Promise<void>;
}
```
### 5.3 Discord 风格 UI 布局
```
┌─────────────────────────────────────────────────────────────────┐
│ [Icon] │ # channel-name [🔍][👤] │
├──────────┼─────────────────────────────────────────┬────────────┤
│ │ ┌─────────────────────────────────┐ │ │
│ Category │ │ Message List │ │ Members │
│ ────────│ │ (with virtual scrolling) │ │ Online(3) │
│ # gen │ │ │ │ ● user1 │
│ # dev │ │ user1 [10:30] Hello! │ │ ● user2 │
│ # ai │ │ ↳ user2 [10:32] Hi! │ │ │
│ │ │ │ │ Offline(5)│
│ Category │ │ 🤖 AI [10:33] Thinking... │ │ ○ user3 │
│ ────────│ │ │ │ │
│ 🔒 priv │ └─────────────────────────────────┘ │ │
│ ├─────────────────────────────────────────┤ │
│ │ [+] Type a message... [@][📎] │ │
└──────────┴─────────────────────────────────────────┴────────────┘
72px Flex: 1 240px
```
### 5.4 消息数据流
```
用户输入 → MessageInput
WebSocket.send({ action: 'message.create', params: { content, room_id } })
后端处理 → Redis INCR seq → DB insert → NATS publish
WebSocket.push({ event: 'message.created', data: message })
RoomContext.handleMessage() → setMessages(prev => [...prev, message])
MessageList 渲染
```
---
## 6. API 端点 (REST)
### 6.1 房间管理
```
GET /api/projects/{project}/rooms # 房间列表
GET /api/projects/{project}/rooms/{room} # 房间详情
POST /api/projects/{project}/rooms # 创建房间
PATCH /api/projects/{project}/rooms/{room} # 更新房间
DELETE /api/projects/{project}/rooms/{room} # 删除房间
```
### 6.2 消息管理
```
GET /api/rooms/{room}/messages # 消息列表 (分页)
GET /api/rooms/{room}/messages/{message} # 单条消息
POST /api/rooms/{room}/messages # 发送消息
PATCH /api/rooms/{room}/messages/{message} # 编辑消息
DELETE /api/rooms/{room}/messages/{message} # 撤回消息
GET /api/rooms/{room}/messages/search # 搜索消息
GET /api/rooms/{room}/messages/{message}/history # 编辑历史
```
### 6.3 AI 端点
```
GET /api/rooms/{room}/ai # AI 配置列表
POST /api/rooms/{room}/ai # 创建 AI 配置
PATCH /api/rooms/{room}/ai/{model} # 更新 AI 配置
DELETE /api/rooms/{room}/ai/{model} # 删除 AI 配置
```
---
## 7. 关键设计原则
| 原则 | 实现方式 |
|------|----------|
| 高内聚低耦合 | 模块化服务层、清晰的领域边界 |
| 异步非阻塞 | Tokio async/await、Redis 异步客户端 |
| 事件驱动 | NATS Pub/Sub 解耦组件 |
| 强类型安全 | TypeScript + Rust 编译期检查 |
| 分层架构 | Service → Repository → Database |
| 鲁棒性优先 | 完善的错误处理、限流、资源回收 |
---
## 8. 已实现功能清单
### 8.1 核心功能 ✅
- [x] 房间 CRUD (创建/读取/更新/删除)
- [x] 消息 CRUD (发送/编辑/撤回/历史)
- [x] 成员管理 (邀请/移除/角色变更)
- [x] 频道分类 (创建/排序/折叠)
- [x] 线程回复 (创建线程/线程消息)
- [x] 消息反应 (emoji 反应)
- [x] 消息置顶
- [x] 消息搜索
- [x] 未读计数
### 8.2 实时功能 ✅
- [x] WebSocket 长连接
- [x] 消息实时推送
- [x] 成员状态同步
- [x] 在线状态显示
- [x] 消息去重
- [x] IndexedDB 离线缓存
- [x] 虚拟滚动列表 (@tanstack/react-virtual)
### 8.3 AI 集成 ✅
- [x] AI 模型配置
- [x] AI 消息发送
- [x] 系统提示词
- [x] 上下文历史限制
- [x] 流式输出支持
- [x] AI 队列锁
### 8.4 富媒体消息 ✅
- [x] 消息内容类型: text, image, audio, video, file
- [x] Tiptap 富文本编辑器 (IMEditor)
- [x] FileNode Tiptap 扩展 (文件/图片节点)
- [x] 文件上传状态管理 (uploading/done/error)
- [x] Markdown 支持
### 8.5 全文搜索 ✅
- [x] PostgreSQL 全文索引 (GIN + tsvector)
- [x] 搜索 API (room_message_search)
- [x] 分页与结果计数
### 8.6 通知系统 ✅
- [x] 提及通知
- [x] 线程通知
- [x] DND 免打扰时段 (do_not_disturb, dnd_start/end_hour)
### 8.4 用户体验 ✅
- [x] 消息草稿自动保存
- [x] @提及功能
- [x] 回复引用
- [x] 消息时间格式化
- [x] Discord 风格 UI
- [x] 侧边栏折叠
- [x] 成员列表按角色着色
---
## 9. 已完成功能 (详细技术方案)
### 9.1 富媒体消息支持 ✅
#### 9.1.1 图片消息
```
技术实现:
- 前端: FileNode.tsx Tiptap 扩展,支持 inline 文件节点
- 富媒体消息类型: MessageContentType::Image, Audio, Video, File
- 文件上传: Tiptap IMEditor 支持拖拽上传
- 状态管理: uploading/done/error 三种状态
代码位置:
- src/components/room/message/editor/FileNode.tsx (Tiptap 文件节点)
- src/components/room/message/editor/IMEditor.tsx (富文本编辑器)
```
#### 9.1.2 消息内容类型 ✅
```
已实现的消息类型:
- Text (text)
- Image (image)
- Audio (audio)
- Video (video)
- File (file)
代码位置:
- libs/models/rooms/mod.rs (MessageContentType enum)
```
### 9.2 历史消息优化 ✅
#### 9.2.1 虚拟滚动列表
```
技术实现:
- @tanstack/react-virtual + useVirtualizer
- 按需渲染可见区域消息 (overscan: 30)
- 动态高度估算 (estimateMessageRowHeight)
- 日期分隔符自动插入
- 滚动位置保持 (加载更多时)
代码位置:
- src/components/room/message/MessageList.tsx
功能特性:
- [x] IntersectionObserver 自动加载更多
- [x] 滚动位置恢复
- [x] 滚动到底部按钮
- [x] 日期分组分隔符
```
#### 9.2.2 IndexedDB 离线缓存 ✅
```
技术实现:
- IndexedDB 本地持久化存储
- 双索引: by_room, by_room_seq
- 支持离线消息恢复
- 自动保存/加载消息
API:
- saveMessage(msg) # 保存单条
- saveMessages(roomId, msgs) # 批量保存
- loadMessages(roomId) # 加载房间消息
- loadOlderMessagesFromIdb() # 加载历史消息
- getMaxSeq(roomId) # 获取最大序列号 (去重)
代码位置:
- src/lib/storage/indexed-db.ts
- src/contexts/room-context.tsx (集成缓存)
```
### 9.3 全文搜索 ✅
#### 9.3.1 PostgreSQL 全文索引
```
技术实现:
- content_tsv TSVECTOR 列
- GIN 索引 (idx_room_message_content_tsv)
- plainto_tsquery('simple', query) 全文搜索
代码位置:
- libs/room/src/search.rs (room_message_search)
- libs/migrate/sql/m20250628_000080_add_message_reactions_and_search.sql
搜索功能:
- [x] 全文搜索 API
- [x] 分页支持 (limit, offset)
- [x] 结果计数 (total)
- [x] 显示名称解析
```
### 9.4 通知系统完善 ✅
#### 9.4.1 多维度通知配置 ✅
```
技术实现:
- room_member 表新增字段:
- do_not_disturb: BOOLEAN (免打扰开关)
- dnd_start_hour: INT (DND 开始时间, 0-23)
- dnd_end_hour: INT (DND 结束时间, 0-23)
数据库迁移:
- libs/migrate/m20250628_000078_add_room_member_do_not_disturb.rs
代码位置:
- libs/models/rooms/room_member.rs
```
#### 9.4.2 通知系统
```
已实现功能:
- [x] 提及通知 (Mention)
- [x] 线程通知 (Thread)
- [x] DND 免打扰时段
- [x] 通知列表 API
- [x] 标记已读 API
代码位置:
- libs/room/src/notification.rs
- libs/service/user/notification.rs
```
---
## 10. 待实现功能
### 10.1 富媒体消息完善
```
待实现:
1. [ ] 对象存储集成 (S3/MinIO)
2. [ ] 文件下载 API
3. [ ] 图片预览 Modal
4. [ ] 视频播放器集成
5. [ ] Office 文档预览
6. [ ] 文件大小/类型验证
7. [ ] 图片压缩 (WebWorker)
```
### 10.2 全文搜索增强
```
待实现:
1. [ ] 时间范围筛选
2. [ ] 用户筛选 (@username)
3. [ ] 文件类型筛选 (content_type)
4. [ ] 搜索历史记录
5. [ ] 结果高亮
6. [ ] 正则搜索支持
7. [ ] 数据库触发器自动更新 tsvector
```
### 10.3 推送通知
```
待实现:
1. [ ] Web Push 集成 (service worker)
2. [ ] 移动端推送
3. [ ] 通知中心 UI
4. [ ] 未读计数 Badge
5. [ ] 关键词提醒
```
### 10.4 性能优化
```
待实现:
1. [ ] room_message 表分区 (按时间)
2. [ ] 读写分离
3. [ ] 房间列表缓存 (Redis)
4. [ ] 成员列表缓存
5. [ ] Redis Pipeline 批量操作
6. [ ] 组件代码分割 (React.lazy)
7. [ ] 图片懒加载
```
### 10.5 AI 增强功能
```
待实现:
1. [ ] AI 连续对话上下文管理
2. [ ] AI 会话历史管理
3. [ ] AI 切换对话线程
4. [ ] AI 输出 Markdown 渲染优化
5. [ ] AI 工具调用扩展 (消息引用/代码执行/搜索)
6. [ ] 定时 AI 任务
7. [ ] 会议纪要生成
```
### 10.6 国际化 (i18n)
```
待实现:
1. [ ] 前端 i18n (react-i18next)
2. [ ] 后端 i18n (rust-i18n)
3. [ ] 提取 UI 字符串
4. [ ] 语言切换器
5. [ ] 日期/时间本地化
6. [ ] RTL 语言支持
```
---
## 11. 测试计划
### 11.1 单元测试
- [ ] RoomService 业务逻辑测试
- [ ] 消息序列号生成测试
- [ ] 权限检查测试
- [ ] React Hooks 测试
### 11.2 集成测试
- [ ] WebSocket 连接测试
- [ ] 数据库事务测试
- [ ] Redis 缓存测试
- [ ] NATS 消息分发测试
### 11.3 E2E 测试
- [ ] 房间创建流程
- [ ] 消息发送与接收
- [ ] 消息编辑与撤回
- [ ] AI 对话流程
---
## 12. 部署与运维
### 11.1 环境变量
```
# 数据库
DATABASE_URL=postgresql://user:pass@host:5432/db
# Redis
REDIS_URL=redis://host:6379
# NATS
NATS_URL=nats://host:4222
# 对象存储
S3_ENDPOINT=https://s3.example.com
S3_BUCKET=room-media
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=xxx
# AI
OPENAI_API_KEY=sk-xxx
OPENROUTER_API_KEY=xxx
```
### 11.2 Kubernetes 配置
```
# Room Service Deployment
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "500m"
# HPA 自动扩缩容
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
```
### 11.3 监控指标
- WebSocket 连接数
- 消息吞吐量 (msg/s)
- AI 调用延迟
- Redis 缓存命中率
- 数据库查询延迟
---
## 13. 安全考虑
### 12.1 权限模型
```
项目权限 → 房间权限 → 成员角色
Admin/Owner → Admin/Owner/Member
```
### 12.2 输入验证
- 消息内容长度限制 (MAX: 10000 chars)
- 文件大小限制 (MAX: 100MB)
- 文件类型白名单
### 12.3 CSRF/XSS 防护
- WebSocket 请求携带 JWT
- 消息内容转义
- 文件名 sanitize