Initial commit of akmon project
This commit is contained in:
167
push-receiver-service/SUPABASE_ADAPTATION.md
Normal file
167
push-receiver-service/SUPABASE_ADAPTATION.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Supabase 数据库适配说明
|
||||
|
||||
## 概述
|
||||
|
||||
推送消息接收服务的数据库结构已适配现有的 `ak_users` 和 `ak_devices` 表结构,以避免重复创建表和数据冲突。所有推送消息相关的表都使用 `ps_` 前缀命名。
|
||||
|
||||
## 主要变更
|
||||
|
||||
### 1. 移除独立表
|
||||
- ❌ 移除独立的 `devices` 表
|
||||
- ❌ 移除独立的 `users` 表
|
||||
- ✅ 使用现有的 `public.ak_devices` 表
|
||||
- ✅ 使用现有的 `public.ak_users` 表
|
||||
|
||||
### 2. 表命名规范
|
||||
- ✅ `ps_push_messages` - 推送消息主表
|
||||
- ✅ `ps_push_types` - 推送类型配置表
|
||||
- ✅ `ps_message_processing_logs` - 消息处理日志表
|
||||
- ✅ `ps_system_stats` - 系统统计表
|
||||
|
||||
### 3. 修改关联字段
|
||||
- `ps_push_messages.user_id`: VARCHAR(255) → UUID,关联到 `public.ak_users(id)`
|
||||
- `ps_push_messages.device_id`: VARCHAR(255) → UUID,关联到 `public.ak_devices(id)`
|
||||
|
||||
#### `ps_push_messages` 表结构
|
||||
```sql
|
||||
CREATE TABLE ps_push_messages (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
message_id VARCHAR(255),
|
||||
push_type VARCHAR(50) NOT NULL,
|
||||
user_id UUID REFERENCES public.ak_users(id) ON DELETE SET NULL,
|
||||
device_id UUID REFERENCES public.ak_devices(id) ON DELETE SET NULL,
|
||||
raw_data JSONB NOT NULL,
|
||||
parsed_data JSONB,
|
||||
received_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
processing_status VARCHAR(20) DEFAULT 'pending',
|
||||
-- 其他字段...
|
||||
);
|
||||
```
|
||||
|
||||
### 4. 适配表结构
|
||||
|
||||
#### `public.ak_users` 表结构
|
||||
```sql
|
||||
CREATE TABLE public.ak_users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
username VARCHAR(64) UNIQUE NOT NULL,
|
||||
email VARCHAR(128) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(256) NOT NULL,
|
||||
gender VARCHAR(16) DEFAULT 'other',
|
||||
birthday DATE,
|
||||
height_cm INT,
|
||||
weight_kg INT,
|
||||
bio TEXT,
|
||||
phone VARCHAR(32),
|
||||
avatar_url TEXT,
|
||||
region_id UUID REFERENCES public.ak_regions(id),
|
||||
school_id UUID REFERENCES public.ak_schools(id),
|
||||
grade_id UUID REFERENCES public.ak_grades(id),
|
||||
class_id UUID REFERENCES public.ak_classes(id),
|
||||
role VARCHAR(32) DEFAULT 'student',
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now(),
|
||||
auth_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
preferred_language UUID REFERENCES public.ak_languages(id)
|
||||
);
|
||||
```
|
||||
|
||||
#### `public.ak_devices` 表结构
|
||||
```sql
|
||||
CREATE TABLE public.ak_devices (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES public.ak_users(id) ON DELETE CASCADE,
|
||||
device_type VARCHAR(32) NOT NULL,
|
||||
device_name VARCHAR(64),
|
||||
device_mac VARCHAR(64),
|
||||
bind_time TIMESTAMPTZ DEFAULT now(),
|
||||
status VARCHAR(16) DEFAULT 'active',
|
||||
extra JSONB
|
||||
);
|
||||
```
|
||||
|
||||
### 5. 数据库操作调整
|
||||
|
||||
#### 设备信息处理
|
||||
```javascript
|
||||
// 旧方式:自动创建/更新设备
|
||||
await this.upsertDevice(deviceData);
|
||||
|
||||
// 新方式:检查并更新现有设备状态
|
||||
await this.upsertDevice({
|
||||
device_id: deviceData.device_id, // 必须是现有设备的 UUID
|
||||
metadata: deviceData.metadata
|
||||
});
|
||||
```
|
||||
|
||||
#### 用户信息处理
|
||||
```javascript
|
||||
// 旧方式:自动创建/更新用户
|
||||
await this.upsertUser(userData);
|
||||
|
||||
// 新方式:检查现有用户(不自动创建)
|
||||
await this.upsertUser({
|
||||
user_id: userData.user_id // 必须是现有用户的 UUID
|
||||
});
|
||||
```
|
||||
|
||||
## API 调用变更
|
||||
|
||||
### 推送消息接口
|
||||
```javascript
|
||||
// 发送推送消息时,user_id 和 device_id 必须使用 UUID 格式
|
||||
const response = await fetch('/api/push/message', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': 'your-api-key'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: 'HEALTH',
|
||||
data: {
|
||||
user_id: '123e4567-e89b-12d3-a456-426614174000', // UUID 格式
|
||||
device_id: '987fcdeb-51a2-43d7-8f9e-123456789abc', // UUID 格式
|
||||
H: 72, // 心率
|
||||
O: 98, // 血氧
|
||||
T: 36.5 // 体温
|
||||
}
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
如果推送消息中包含不存在的 user_id 或 device_id:
|
||||
- 消息仍会被存储到 `push_messages` 表
|
||||
- 会在日志中记录警告信息
|
||||
- 不会自动创建用户或设备记录
|
||||
|
||||
## 部署注意事项
|
||||
|
||||
### 1. 数据库初始化
|
||||
确保在执行 `database/supabase-init.sql` 之前,现有的 `ak_users` 和 `ak_devices` 表已经存在。
|
||||
|
||||
### 2. 外键约束
|
||||
推送消息表与现有表建立了外键关联:
|
||||
- `ps_push_messages.user_id` → `public.ak_users(id)`
|
||||
- `ps_push_messages.device_id` → `public.ak_devices(id)`
|
||||
|
||||
### 3. 权限设置
|
||||
确保 Supabase Service Role 对现有表有适当的访问权限。
|
||||
|
||||
## 数据完整性
|
||||
|
||||
### 推送消息存储
|
||||
- ✅ 所有推送消息都会完整存储
|
||||
- ✅ 支持 user_id 或 device_id 为 NULL 的情况
|
||||
- ✅ 通过外键约束保证数据一致性
|
||||
|
||||
### 统计和查询
|
||||
- ✅ 可以通过关联查询获取用户和设备的详细信息
|
||||
- ✅ 统计功能完全兼容现有表结构
|
||||
|
||||
## 使用建议
|
||||
|
||||
1. **用户和设备管理**:通过专门的用户管理和设备管理接口创建和维护用户、设备信息
|
||||
2. **推送消息**:只负责接收和存储推送消息,不处理用户/设备的创建
|
||||
3. **数据关联**:通过外键关联获取完整的用户和设备信息
|
||||
4. **监控告警**:监控日志中关于不存在用户/设备的警告信息
|
||||
Reference in New Issue
Block a user