Files
akmon/push-receiver-service/SUPABASE_ADAPTATION.md
2026-01-20 08:04:15 +08:00

5.1 KiB
Raw Blame History

Supabase 数据库适配说明

概述

推送消息接收服务的数据库结构已适配现有的 ak_usersak_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 表结构

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 表结构

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 表结构

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. 数据库操作调整

设备信息处理

// 旧方式:自动创建/更新设备
await this.upsertDevice(deviceData);

// 新方式:检查并更新现有设备状态
await this.upsertDevice({
    device_id: deviceData.device_id, // 必须是现有设备的 UUID
    metadata: deviceData.metadata
});

用户信息处理

// 旧方式:自动创建/更新用户  
await this.upsertUser(userData);

// 新方式:检查现有用户(不自动创建)
await this.upsertUser({
    user_id: userData.user_id  // 必须是现有用户的 UUID
});

API 调用变更

推送消息接口

// 发送推送消息时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_usersak_devices 表已经存在。

2. 外键约束

推送消息表与现有表建立了外键关联:

  • ps_push_messages.user_idpublic.ak_users(id)
  • ps_push_messages.device_idpublic.ak_devices(id)

3. 权限设置

确保 Supabase Service Role 对现有表有适当的访问权限。

数据完整性

推送消息存储

  • 所有推送消息都会完整存储
  • 支持 user_id 或 device_id 为 NULL 的情况
  • 通过外键约束保证数据一致性

统计和查询

  • 可以通过关联查询获取用户和设备的详细信息
  • 统计功能完全兼容现有表结构

使用建议

  1. 用户和设备管理:通过专门的用户管理和设备管理接口创建和维护用户、设备信息
  2. 推送消息:只负责接收和存储推送消息,不处理用户/设备的创建
  3. 数据关联:通过外键关联获取完整的用户和设备信息
  4. 监控告警:监控日志中关于不存在用户/设备的警告信息