优化部署流程

This commit is contained in:
eafonyang
2026-06-30 13:50:29 +08:00
parent a52adf7e27
commit 23f712cf86
9 changed files with 362 additions and 204 deletions
+55 -59
View File
@@ -34,12 +34,10 @@
## 更新摘要 ## 更新摘要
**所做更改** **所做更改**
- 新增设备持久化子系统:user_device、user_active 表及配套处理器和任务 - 更新OTA表结构定义:删除了pawVerCode、pawVerName、pawUrl、pawMd5四列,OTA表现在包含id、verCode、verName、url、md5、force、desc、model、hw、target、beta、startTime、endTime、status等核心字段,简化了数据库结构
- 新增 OTA 固件升级子系统:ota、black_list、ota_target_device 表及配套仓库层 - 更新数据模型文档以反映OTA表结构的简化
- 更新架构图以反映新的数据流和处理流程 - 更新实体关系图和字段定义
- 新增设备上报接口和定时持久化任务 - 更新数据访问模式和业务逻辑说明
- 新增 OTA 升级查询接口和复杂业务逻辑处理
- 更新数据访问模式以支持新的业务场景
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
@@ -56,7 +54,7 @@
## 简介 ## 简介
本文件面向 Luxsin 应用 API 的数据库与数据模型,系统化梳理实体关系、字段定义、索引与约束、数据访问模式、缓存与搜索集成、性能优化、数据生命周期与迁移路径,并给出品牌(Brand)与型号(Model)实体的设计理念与业务逻辑说明。文档同时覆盖数据库连接配置、查询优化建议、数据安全与隐私要求以及访问控制要点。 本文件面向 Luxsin 应用 API 的数据库与数据模型,系统化梳理实体关系、字段定义、索引与约束、数据访问模式、缓存与搜索集成、性能优化、数据生命周期与迁移路径,并给出品牌(Brand)与型号(Model)实体的设计理念与业务逻辑说明。文档同时覆盖数据库连接配置、查询优化建议、数据安全与隐私要求以及访问控制要点。
**更新** 本次更新反映了数据库架构的重大扩展,新增了设备持久化和 OTA 固件升级两大核心功能模块,包括 user_device、user_active、ota、black_list、ota_target_device 五个新表及其配套的处理逻辑 **更新** 本次更新反映了OTA表结构的重大简化,删除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,保留了核心的固件升级信息字段,提高了数据库结构的简洁性和可维护性
## 项目结构 ## 项目结构
本项目采用分层架构:入口程序负责初始化配置、数据库、搜索引擎与缓存;路由层组织 HTTP 接口;处理器层封装业务接口;仓库层实现数据访问;模型层承载数据结构;搜索与缓存模块作为外部依赖集成。 本项目采用分层架构:入口程序负责初始化配置、数据库、搜索引擎与缓存;路由层组织 HTTP 接口;处理器层封装业务接口;仓库层实现数据访问;模型层承载数据结构;搜索与缓存模块作为外部依赖集成。
@@ -129,7 +127,7 @@ TASK_DP --> REPO_D
- [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50) - [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50)
- [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51) - [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51)
- [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83) - [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83)
- [internal/handler/ota.go:1-133](file://internal/handler/ota.go#L1-L133) - [internal/handler/ota.go:1-145](file://internal/handler/ota.go#L1-L145)
- [internal/repository/brand.go:1-51](file://internal/repository/brand.go#L1-L51) - [internal/repository/brand.go:1-51](file://internal/repository/brand.go#L1-L51)
- [internal/repository/model.go:1-95](file://internal/repository/model.go#L1-L95) - [internal/repository/model.go:1-95](file://internal/repository/model.go#L1-L95)
- [internal/repository/device.go:1-88](file://internal/repository/device.go#L1-L88) - [internal/repository/device.go:1-88](file://internal/repository/device.go#L1-L88)
@@ -138,7 +136,7 @@ TASK_DP --> REPO_D
- [internal/model/model.go:1-15](file://internal/model/model.go#L1-L15) - [internal/model/model.go:1-15](file://internal/model/model.go#L1-L15)
- [internal/model/user_device.go:1-12](file://internal/model/user_device.go#L1-L12) - [internal/model/user_device.go:1-12](file://internal/model/user_device.go#L1-L12)
- [internal/model/user_active.go:1-13](file://internal/model/user_active.go#L1-L13) - [internal/model/user_active.go:1-13](file://internal/model/user_active.go#L1-L13)
- [internal/model/ota.go:1-43](file://internal/model/ota.go#L1-L43) - [internal/model/ota.go:1-63](file://internal/model/ota.go#L1-L63)
- [internal/task/device_persist.go:1-167](file://internal/task/device_persist.go#L1-L167) - [internal/task/device_persist.go:1-167](file://internal/task/device_persist.go#L1-L167)
**章节来源** **章节来源**
@@ -148,27 +146,27 @@ TASK_DP --> REPO_D
## 核心组件 ## 核心组件
- 数据库表 model:存储耳机型号信息,包含唯一组合索引以保证品牌+型号的唯一性。 - 数据库表 model:存储耳机型号信息,包含唯一组合索引以保证品牌+型号的唯一性。
- 设备持久化表:user_device(设备信息持久化)、user_active(设备活跃度统计) - 设备持久化表:user_device(设备信息持久化)、user_active(设备活跃度统计)
- OTA 升级表:ota(固件升级信息)、black_list(黑名单)、ota_target_device(定向设备) - OTA 升级表:ota(固件升级信息,已简化结构)、black_list(黑名单)、ota_target_device(定向设备)
- 模型对象 Brand 与 Model:分别映射品牌与型号的 JSON 字段与数据库列。 - 模型对象 Brand 与 Model:分别映射品牌与型号的 JSON 字段与数据库列。
- 仓库层:提供按品牌名或型号名检索的查询方法,支持模糊匹配与精确匹配。 - 仓库层:提供按品牌名或型号名检索的查询方法,支持模糊匹配与精确匹配。
- 处理器层:暴露 HTTP 接口,支持返回 JSON 或 Base64 编码响应。 - 处理器层:暴露 HTTP 接口,支持返回 JSON 或 Base64 编码响应。
- 配置层:集中加载数据库、搜索引擎与缓存的连接参数,并进行基本校验。 - 配置层:集中加载数据库、搜索引擎与缓存的连接参数,并进行基本校验。
- 基础设施:MySQL 连接池配置、Redis 客户端、Meilisearch 搜索客户端。 - 基础设施:MySQL 连接池配置、Redis 客户端、Meilisearch 搜索客户端。
**更新** 新增设备持久化和 OTA 升级两大功能模块,包含完整的数据模型、业务逻辑和处理流程 **更新** OTA表结构已简化,删除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,保留了核心的固件升级信息字段
**章节来源** **章节来源**
- [sql/model.sql:20-38](file://sql/model.sql#L20-L38) - [sql/model.sql:20-38](file://sql/model.sql#L20-L38)
- [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35) - [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35)
- [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208) - [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208)
- [sql/ota.sql:20-47](file://sql/ota.sql#L20-L47) - [sql/ota.sql:20-40](file://sql/ota.sql#L20-L40)
- [sql/black_list.sql:20-33](file://sql/black_list.sql#L20-L33) - [sql/black_list.sql:20-30](file://sql/black_list.sql#L20-L30)
- [sql/ota_target_device.sql:20-34](file://sql/ota_target_device.sql#L20-L34) - [sql/ota_target_device.sql:20-31](file://sql/ota_target_device.sql#L20-L31)
- [internal/model/brand.go:1-7](file://internal/model/brand.go#L1-L7) - [internal/model/brand.go:1-7](file://internal/model/brand.go#L1-L7)
- [internal/model/model.go:1-15](file://internal/model/model.go#L1-L15) - [internal/model/model.go:1-15](file://internal/model/model.go#L1-L15)
- [internal/model/user_device.go:1-12](file://internal/model/user_device.go#L1-L12) - [internal/model/user_device.go:1-12](file://internal/model/user_device.go#L1-L12)
- [internal/model/user_active.go:1-13](file://internal/model/user_active.go#L1-L13) - [internal/model/user_active.go:1-13](file://internal/model/user_active.go#L1-L13)
- [internal/model/ota.go:1-43](file://internal/model/ota.go#L1-L43) - [internal/model/ota.go:1-63](file://internal/model/ota.go#L1-L63)
- [internal/repository/brand.go:1-51](file://internal/repository/brand.go#L1-L51) - [internal/repository/brand.go:1-51](file://internal/repository/brand.go#L1-L51)
- [internal/repository/model.go:1-95](file://internal/repository/model.go#L1-L95) - [internal/repository/model.go:1-95](file://internal/repository/model.go#L1-L95)
- [internal/repository/device.go:1-88](file://internal/repository/device.go#L1-L88) - [internal/repository/device.go:1-88](file://internal/repository/device.go#L1-L88)
@@ -176,7 +174,7 @@ TASK_DP --> REPO_D
- [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50) - [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50)
- [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51) - [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51)
- [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83) - [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83)
- [internal/handler/ota.go:1-133](file://internal/handler/ota.go#L1-L133) - [internal/handler/ota.go:1-145](file://internal/handler/ota.go#L1-L145)
- [internal/config/database.go:1-72](file://internal/config/database.go#L1-L72) - [internal/config/database.go:1-72](file://internal/config/database.go#L1-L72)
- [internal/config/meilisearch.go:1-51](file://internal/config/meilisearch.go#L1-L51) - [internal/config/meilisearch.go:1-51](file://internal/config/meilisearch.go#L1-L51)
- [internal/config/redis.go:1-57](file://internal/config/redis.go#L1-L57) - [internal/config/redis.go:1-57](file://internal/config/redis.go#L1-L57)
@@ -212,7 +210,7 @@ note over H,RC : "可选:对热点数据进行缓存读写<br/>设备上报:
- [internal/handler/brand.go:26-49](file://internal/handler/brand.go#L26-L49) - [internal/handler/brand.go:26-49](file://internal/handler/brand.go#L26-L49)
- [internal/handler/model.go:26-50](file://internal/handler/model.go#L26-L50) - [internal/handler/model.go:26-50](file://internal/handler/model.go#L26-L50)
- [internal/handler/device.go:27-82](file://internal/handler/device.go#L27-L82) - [internal/handler/device.go:27-82](file://internal/handler/device.go#L27-L82)
- [internal/handler/ota.go:23-132](file://internal/handler/ota.go#L23-L132) - [internal/handler/ota.go:23-144](file://internal/handler/ota.go#L23-L144)
- [internal/repository/brand.go:20-50](file://internal/repository/brand.go#L20-L50) - [internal/repository/brand.go:20-50](file://internal/repository/brand.go#L20-L50)
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61) - [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
- [internal/repository/device.go:19-87](file://internal/repository/device.go#L19-L87) - [internal/repository/device.go:19-87](file://internal/repository/device.go#L19-L87)
@@ -234,10 +232,12 @@ note over H,RC : "可选:对热点数据进行缓存读写<br/>设备上报:
- Modelid(整数,主键)、brand_name(字符串,非空)、name(字符串,非空)、form(字符串,可空)、rig(字符串,可空)、source(字符串,可空)、eq_key(字符串,可空)、create_at(时间戳,默认当前时间) - Modelid(整数,主键)、brand_name(字符串,非空)、name(字符串,非空)、form(字符串,可空)、rig(字符串,可空)、source(字符串,可空)、eq_key(字符串,可空)、create_at(时间戳,默认当前时间)
- UserDeviceid(整数,主键)、mac_addr(字符串,唯一)、model(字符串)、add_time(时间戳,默认当前时间)、ver(字符串,可空) - UserDeviceid(整数,主键)、mac_addr(字符串,唯一)、model(字符串)、add_time(时间戳,默认当前时间)、ver(字符串,可空)
- UserActiveid(整数,主键)、mac_addr(字符串)、model(字符串)、active_date(日期,主键部分)、ip_addr(字符串)、create_at(时间戳,默认当前时间) - UserActiveid(整数,主键)、mac_addr(字符串)、model(字符串)、active_date(日期,主键部分)、ip_addr(字符串)、create_at(时间戳,默认当前时间)
- OTAid(整数,主键)、verCode(整数)、verName(字符串)、url(字符串)、md5(字符串)、force(整数,默认0)、desc(字符串,可空)、model(字符串,可空)、hw(整数,默认0)、target(整数,默认0)、beta(整数,默认0)、pawVerCode(整数,默认0)、pawVerName(字符串)、pawUrl(字符串)、pawMd5(字符串)、startTime(时间戳,可空)、endTime(时间戳,可空)、status(整数,默认1) - OTAid(整数,主键)、verCode(整数)、verName(字符串)、url(字符串)、md5(字符串)、force(整数,默认0)、desc(字符串,可空)、model(字符串,可空)、hw(整数,默认0)、target(整数,默认0)、beta(整数,默认0)、startTime(时间戳,可空)、endTime(时间戳,可空)、status(整数,默认1)
- BlackListid(整数,主键)、ota_id(整数)、mac(字符串,默认空)、create_at(时间戳,默认当前时间) - BlackListid(整数,主键)、ota_id(整数)、mac(字符串,默认空)、create_at(时间戳,默认当前时间)
- OTATargetDeviceid(整数,主键)、ota_id(整数)、mac_addr(字符串)、type(整数,默认1,1-白名单;2-黑名单)、create_at(时间戳,默认当前时间) - OTATargetDeviceid(整数,主键)、ota_id(整数)、mac_addr(字符串)、type(整数,默认1,1-白名单;2-黑名单)、create_at(时间戳,默认当前时间)
**更新** OTA表结构已简化,删除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,保留了核心的固件升级信息字段。
```mermaid ```mermaid
erDiagram erDiagram
BRAND { BRAND {
@@ -281,10 +281,6 @@ string model
int hw int hw
int target int target
int beta int beta
int pawVerCode
string pawVerName
string pawUrl
string pawMd5
datetime startTime datetime startTime
datetime endTime datetime endTime
int status int status
@@ -313,12 +309,12 @@ OTA ||--o{ OTA_TARGET_DEVICE : "定向设备关联"
- [internal/model/model.go:5-14](file://internal/model/model.go#L5-L14) - [internal/model/model.go:5-14](file://internal/model/model.go#L5-L14)
- [internal/model/user_device.go:5-11](file://internal/model/user_device.go#L5-L11) - [internal/model/user_device.go:5-11](file://internal/model/user_device.go#L5-L11)
- [internal/model/user_active.go:5-12](file://internal/model/user_active.go#L5-L12) - [internal/model/user_active.go:5-12](file://internal/model/user_active.go#L5-L12)
- [internal/model/ota.go:6-25](file://internal/model/ota.go#L6-L25) - [internal/model/ota.go:30-45](file://internal/model/ota.go#L30-L45)
- [internal/model/ota.go:28-42](file://internal/model/ota.go#L28-L42) - [internal/model/ota.go:47-62](file://internal/model/ota.go#L47-L62)
- [sql/model.sql:24-35](file://sql/model.sql#L24-L35) - [sql/model.sql:24-35](file://sql/model.sql#L24-L35)
- [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32) - [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32)
- [sql/user_active.sql:24-32](file://sql/user_active.sql#L24-L32) - [sql/user_active.sql:24-32](file://sql/user_active.sql#L24-L32)
- [sql/ota.sql:24-44](file://sql/ota.sql#L24-L44) - [sql/ota.sql:24-40](file://sql/ota.sql#L24-L40)
- [sql/black_list.sql:24-30](file://sql/black_list.sql#L24-L30) - [sql/black_list.sql:24-30](file://sql/black_list.sql#L24-L30)
- [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31) - [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31)
@@ -327,13 +323,13 @@ OTA ||--o{ OTA_TARGET_DEVICE : "定向设备关联"
- [internal/model/model.go:1-15](file://internal/model/model.go#L1-L15) - [internal/model/model.go:1-15](file://internal/model/model.go#L1-L15)
- [internal/model/user_device.go:1-12](file://internal/model/user_device.go#L1-L12) - [internal/model/user_device.go:1-12](file://internal/model/user_device.go#L1-L12)
- [internal/model/user_active.go:1-13](file://internal/model/user_active.go#L1-L13) - [internal/model/user_active.go:1-13](file://internal/model/user_active.go#L1-L13)
- [internal/model/ota.go:1-43](file://internal/model/ota.go#L1-L43) - [internal/model/ota.go:1-63](file://internal/model/ota.go#L1-L63)
- [sql/model.sql:20-38](file://sql/model.sql#L20-L38) - [sql/model.sql:20-38](file://sql/model.sql#L20-L38)
- [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35) - [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35)
- [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208) - [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208)
- [sql/ota.sql:20-47](file://sql/ota.sql#L20-L47) - [sql/ota.sql:20-40](file://sql/ota.sql#L20-L40)
- [sql/black_list.sql:20-33](file://sql/black_list.sql#L20-L33) - [sql/black_list.sql:20-30](file://sql/black_list.sql#L20-L30)
- [sql/ota_target_device.sql:20-34](file://sql/ota_target_device.sql#L20-L34) - [sql/ota_target_device.sql:20-31](file://sql/ota_target_device.sql#L20-L31)
### 数据库表结构与约束 ### 数据库表结构与约束
- 表名:model、user_device、user_active、ota、black_list、ota_target_device - 表名:model、user_device、user_active、ota、black_list、ota_target_device
@@ -346,15 +342,15 @@ OTA ||--o{ OTA_TARGET_DEVICE : "定向设备关联"
- 分区表:user_active 表按 active_date 进行范围分区,包含 170 个分区 - 分区表:user_active 表按 active_date 进行范围分区,包含 170 个分区
- 存储引擎与字符集:InnoDB、utf8mb4、排序规则 0900_ai_ci - 存储引擎与字符集:InnoDB、utf8mb4、排序规则 0900_ai_ci
**更新** 新增了三个分区表和多个唯一索引约束,增强了数据完整性和查询性能 **更新** OTA表结构已简化,删除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,保留了核心的固件升级信息字段
**章节来源** **章节来源**
- [sql/model.sql:20-38](file://sql/model.sql#L20-L38) - [sql/model.sql:20-38](file://sql/model.sql#L20-L38)
- [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35) - [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35)
- [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208) - [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208)
- [sql/ota.sql:20-47](file://sql/ota.sql#L20-L47) - [sql/ota.sql:20-40](file://sql/ota.sql#L20-L40)
- [sql/black_list.sql:20-33](file://sql/black_list.sql#L20-L33) - [sql/black_list.sql:20-30](file://sql/black_list.sql#L20-L30)
- [sql/ota_target_device.sql:20-34](file://sql/ota_target_device.sql#L20-L34) - [sql/ota_target_device.sql:20-31](file://sql/ota_target_device.sql#L20-L31)
### 数据访问模式 ### 数据访问模式
- 品牌列表: - 品牌列表:
@@ -413,13 +409,13 @@ end
- OTA 升级接口:接收 model、hw、mac、beta 参数,返回合适的 OTA 升级信息 - OTA 升级接口:接收 model、hw、mac、beta 参数,返回合适的 OTA 升级信息
- 错误处理:内部错误统一返回 500 并记录日志 - 错误处理:内部错误统一返回 500 并记录日志
**更新** 新增设备上报和 OTA 升级两个核心接口,支持完整的设备管理和固件升级业务流程 **更新** OTA接口现在使用简化的OTA表结构,不再需要处理pawVerCode、pawVerName、pawUrl、pawMd5字段
**章节来源** **章节来源**
- [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50) - [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50)
- [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51) - [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51)
- [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83) - [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83)
- [internal/handler/ota.go:1-133](file://internal/handler/ota.go#L1-L133) - [internal/handler/ota.go:1-145](file://internal/handler/ota.go#L1-L145)
### 搜索与缓存集成 ### 搜索与缓存集成
- 搜索:Meilisearch 客户端按给定关键字检索,限定返回属性,支持空命中返回空数组 - 搜索:Meilisearch 客户端按给定关键字检索,限定返回属性,支持空命中返回空数组
@@ -427,7 +423,7 @@ end
- 设备缓存:使用 Redis Hash 存储设备上报信息,键为设备 MAC 地址 - 设备缓存:使用 Redis Hash 存储设备上报信息,键为设备 MAC 地址
- 持久化策略:定时任务批量处理 Redis 缓存数据,避免频繁数据库写入 - 持久化策略:定时任务批量处理 Redis 缓存数据,避免频繁数据库写入
**更新** 新增了设备信息的 Redis 缓存机制,通过定时任务实现高效的数据持久化。 **更新** OTA缓存策略保持不变,但查询逻辑已简化。
**章节来源** **章节来源**
- [internal/search/meilisearch.go:1-46](file://internal/search/meilisearch.go#L1-L46) - [internal/search/meilisearch.go:1-46](file://internal/search/meilisearch.go#L1-L46)
@@ -477,12 +473,12 @@ end
- 灰度发布:通过 beta 标识实现渐进式升级发布 - 灰度发布:通过 beta 标识实现渐进式升级发布
- 强制升级:支持强制升级策略,阻止设备继续使用旧版本 - 强制升级:支持强制升级策略,阻止设备继续使用旧版本
**新** OTA 固件升级子系统提供了完整的固件管理能力 **** OTA表结构已简化,删除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,查询逻辑相应简化
**章节来源** **章节来源**
- [internal/handler/ota.go:23-132](file://internal/handler/ota.go#L23-L132) - [internal/handler/ota.go:23-144](file://internal/handler/ota.go#L23-L144)
- [internal/repository/ota.go:19-158](file://internal/repository/ota.go#L19-L158) - [internal/repository/ota.go:19-158](file://internal/repository/ota.go#L19-L158)
- [internal/model/ota.go:6-42](file://internal/model/ota.go#L6-L42) - [internal/model/ota.go:30-45](file://internal/model/ota.go#L30-L45)
## 依赖分析 ## 依赖分析
- 处理器依赖仓库;仓库依赖数据库;应用入口依赖配置与基础设施。 - 处理器依赖仓库;仓库依赖数据库;应用入口依赖配置与基础设施。
@@ -520,7 +516,7 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50) - [internal/handler/brand.go:1-50](file://internal/handler/brand.go#L1-L50)
- [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51) - [internal/handler/model.go:1-51](file://internal/handler/model.go#L1-L51)
- [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83) - [internal/handler/device.go:1-83](file://internal/handler/device.go#L1-L83)
- [internal/handler/ota.go:1-133](file://internal/handler/ota.go#L1-L133) - [internal/handler/ota.go:1-145](file://internal/handler/ota.go#L1-L145)
- [internal/repository/brand.go:1-51](file://internal/repository/brand.go#L1-L51) - [internal/repository/brand.go:1-51](file://internal/repository/brand.go#L1-L51)
- [internal/repository/model.go:1-95](file://internal/repository/model.go#L1-L95) - [internal/repository/model.go:1-95](file://internal/repository/model.go#L1-L95)
- [internal/repository/device.go:1-88](file://internal/repository/device.go#L1-L88) - [internal/repository/device.go:1-88](file://internal/repository/device.go#L1-L88)
@@ -528,9 +524,9 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- [sql/model.sql:20-38](file://sql/model.sql#L20-L38) - [sql/model.sql:20-38](file://sql/model.sql#L20-L38)
- [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35) - [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35)
- [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208) - [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208)
- [sql/ota.sql:20-47](file://sql/ota.sql#L20-L47) - [sql/ota.sql:20-40](file://sql/ota.sql#L20-L40)
- [sql/black_list.sql:20-33](file://sql/black_list.sql#L20-L33) - [sql/black_list.sql:20-30](file://sql/black_list.sql#L20-L30)
- [sql/ota_target_device.sql:20-34](file://sql/ota_target_device.sql#L20-L34) - [sql/ota_target_device.sql:20-31](file://sql/ota_target_device.sql#L20-L31)
- [internal/task/device_persist.go:1-167](file://internal/task/device_persist.go#L1-L167) - [internal/task/device_persist.go:1-167](file://internal/task/device_persist.go#L1-L167)
## 性能考虑 ## 性能考虑
@@ -555,7 +551,7 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- user_active 表按日期分区,提高大数据量下的查询性能 - user_active 表按日期分区,提高大数据量下的查询性能
- 分区裁剪可以显著减少扫描数据量 - 分区裁剪可以显著减少扫描数据量
**更新** 新增了设备持久化和 OTA 升级场景的性能优化建议,包括 Redis 缓存策略和分区表优化 **更新** OTA查询逻辑已简化,减少了不必要的字段扫描,提高了查询效率
**章节来源** **章节来源**
- [internal/database/mysql.go:33-36](file://internal/database/mysql.go#L33-L36) - [internal/database/mysql.go:33-36](file://internal/database/mysql.go#L33-L36)
@@ -585,7 +581,7 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- 检查 OTA 表数据完整性和索引状态 - 检查 OTA 表数据完整性和索引状态
- 验证黑名单和定向设备表的数据准确性 - 验证黑名单和定向设备表的数据准确性
**更新** 新增了设备持久化和 OTA 升级相关的故障排查指南 **更新** OTA故障排查已简化,不再需要检查pawVerCode、pawVerName、pawUrl、pawMd5字段
**章节来源** **章节来源**
- [internal/config/database.go:57-71](file://internal/config/database.go#L57-L71) - [internal/config/database.go:57-71](file://internal/config/database.go#L57-L71)
@@ -595,12 +591,12 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- [internal/handler/brand.go:31-43](file://internal/handler/brand.go#L31-L43) - [internal/handler/brand.go:31-43](file://internal/handler/brand.go#L31-L43)
- [internal/handler/model.go:33-43](file://internal/handler/model.go#L33-L43) - [internal/handler/model.go:33-43](file://internal/handler/model.go#L33-L43)
- [internal/handler/device.go:45-82](file://internal/handler/device.go#L45-L82) - [internal/handler/device.go:45-82](file://internal/handler/device.go#L45-L82)
- [internal/handler/ota.go:56-132](file://internal/handler/ota.go#L56-L132) - [internal/handler/ota.go:56-144](file://internal/handler/ota.go#L56-L144)
- [internal/search/meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20) - [internal/search/meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16) - [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
## 结论 ## 结论
本设计以简洁的表结构与清晰的分层架构支撑品牌与型号的查询需求。通过搜索引擎与缓存提升检索性能,配合连接池与错误处理机制保障稳定性。**更新** 新增的设备持久化和 OTA 固件升级子系统进一步完善了系统的业务能力,通过 Redis 缓存和分区表优化提升了大规模数据处理的性能。后续可在索引策略、缓存策略与数据迁移方面进一步细化,以满足生产环境的高可用与高性能要求。 本设计以简洁的表结构与清晰的分层架构支撑品牌与型号的查询需求。通过搜索引擎与缓存提升检索性能,配合连接池与错误处理机制保障稳定性。**更新** OTA表结构的简化显著提高了数据库的简洁性和可维护性,删除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,保留了核心的固件升级信息。新增的设备持久化和 OTA 固件升级子系统进一步完善了系统的业务能力,通过 Redis 缓存和分区表优化提升了大规模数据处理的性能。后续可在索引策略、缓存策略与数据迁移方面进一步细化,以满足生产环境的高可用与高性能要求。
## 附录 ## 附录
@@ -612,12 +608,12 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- 时间字段 create_at 默认当前时间,便于审计与排序 - 时间字段 create_at 默认当前时间,便于审计与排序
- 处理器层对空结果返回空数组,避免无效数据传播 - 处理器层对空结果返回空数组,避免无效数据传播
**更新** 新增了设备和 OTA 相关的数据验证规则 **更新** OTA数据验证规则已简化,不再需要验证pawVerCode、pawVerName、pawUrl、pawMd5字段
**章节来源** **章节来源**
- [sql/model.sql:24-35](file://sql/model.sql#L24-L35) - [sql/model.sql:24-35](file://sql/model.sql#L24-L35)
- [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32) - [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32)
- [sql/ota.sql:24-44](file://sql/ota.sql#L24-L44) - [sql/ota.sql:24-40](file://sql/ota.sql#L24-L40)
- [sql/black_list.sql:24-30](file://sql/black_list.sql#L24-L30) - [sql/black_list.sql:24-30](file://sql/black_list.sql#L24-L30)
- [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31) - [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31)
- [internal/repository/brand.go:24-27](file://internal/repository/brand.go#L24-L27) - [internal/repository/brand.go:24-27](file://internal/repository/brand.go#L24-L27)
@@ -629,13 +625,13 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- 设备示例:id=1214, mac_addr="AA:BB:CC:DD:EE:FF", model="WH-1000XM4", add_time="2026-05-28 17:08:30", ver="1.2.3" - 设备示例:id=1214, mac_addr="AA:BB:CC:DD:EE:FF", model="WH-1000XM4", add_time="2026-05-28 17:08:30", ver="1.2.3"
- OTA 示例:id=48, verCode=100, verName="v1.2.3", url="http://example.com/firmware.bin", md5="d41d8cd98f00b204e9800998ecf8427e", force=1, desc="重大安全更新", model="WH-1000XM4", hw=1, target=1, beta=0, status=1 - OTA 示例:id=48, verCode=100, verName="v1.2.3", url="http://example.com/firmware.bin", md5="d41d8cd98f00b204e9800998ecf8427e", force=1, desc="重大安全更新", model="WH-1000XM4", hw=1, target=1, beta=0, status=1
**更新** 新增了设备和 OTA示例数据。 **更新** OTA示例数据已简化,移除了pawVerCode、pawVerName、pawUrl、pawMd5字段
**章节来源** **章节来源**
- [internal/model/brand.go:4-5](file://internal/model/brand.go#L4-L5) - [internal/model/brand.go:4-5](file://internal/model/brand.go#L4-L5)
- [internal/model/model.go:6-13](file://internal/model/model.go#L6-L13) - [internal/model/model.go:6-13](file://internal/model/model.go#L6-L13)
- [internal/model/user_device.go:5-11](file://internal/model/user_device.go#L5-L11) - [internal/model/user_device.go:5-11](file://internal/model/user_device.go#L5-L11)
- [internal/model/ota.go:6-25](file://internal/model/ota.go#L6-L25) - [internal/model/ota.go:30-45](file://internal/model/ota.go#L30-L45)
### 数据生命周期、保留策略与归档规则 ### 数据生命周期、保留策略与归档规则
- 建议:基于 create_at 建立分区或定期归档任务,清理长期未使用的型号数据 - 建议:基于 create_at 建立分区或定期归档任务,清理长期未使用的型号数据
@@ -644,11 +640,11 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- 归档策略:保留近一年的活跃型号,历史数据移至冷存储 - 归档策略:保留近一年的活跃型号,历史数据移至冷存储
- 审计:保留变更日志与备份周期,确保可追溯性 - 审计:保留变更日志与备份周期,确保可追溯性
**更新** 新增了设备和 OTA 数据生命周期管理建议 **更新** OTA数据生命周期管理保持不变,但查询逻辑已简化
**章节来源** **章节来源**
- [sql/user_active.sql:33-204](file://sql/user_active.sql#L33-L204) - [sql/user_active.sql:33-204](file://sql/user_active.sql#L33-L204)
- [sql/ota.sql:24-44](file://sql/ota.sql#L24-L44) - [sql/ota.sql:24-40](file://sql/ota.sql#L24-L40)
### 数据迁移路径与版本管理 ### 数据迁移路径与版本管理
- 版本化:每次结构变更生成迁移脚本,记录变更人、时间与目的 - 版本化:每次结构变更生成迁移脚本,记录变更人、时间与目的
@@ -657,12 +653,12 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- 设备数据迁移:支持从临时表导入到正式表,处理重复数据 - 设备数据迁移:支持从临时表导入到正式表,处理重复数据
- OTA 数据迁移:支持版本号递增和兼容性检查 - OTA 数据迁移:支持版本号递增和兼容性检查
**更新** 新增了设备和 OTA 数据的迁移策略 **更新** OTA数据迁移已简化,不需要处理pawVerCode、pawVerName、pawUrl、pawMd5字段的迁移。
**章节来源** **章节来源**
- [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35) - [sql/user_device.sql:20-35](file://sql/user_device.sql#L20-L35)
- [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208) - [sql/user_active.sql:20-208](file://sql/user_active.sql#L20-L208)
- [sql/ota.sql:20-47](file://sql/ota.sql#L20-L47) - [sql/ota.sql:20-40](file://sql/ota.sql#L20-L40)
### 数据安全、隐私要求与访问控制 ### 数据安全、隐私要求与访问控制
- 网络安全:数据库与搜索引擎通过内网或 VPC 访问,限制入站 IP - 网络安全:数据库与搜索引擎通过内网或 VPC 访问,限制入站 IP
@@ -671,7 +667,7 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- 设备隐私:MAC 地址等个人标识信息需遵循隐私保护法规 - 设备隐私:MAC 地址等个人标识信息需遵循隐私保护法规
- OTA 安全:固件 MD5 校验确保下载完整性,黑名单机制防止恶意设备升级 - OTA 安全:固件 MD5 校验确保下载完整性,黑名单机制防止恶意设备升级
**更新** 新增了设备和 OTA 场景下的安全要求 **更新** OTA安全机制保持不变,但查询逻辑已简化
**章节来源** **章节来源**
- [internal/config/database.go:67-69](file://internal/config/database.go#L67-L69) - [internal/config/database.go:67-69](file://internal/config/database.go#L67-L69)
@@ -697,11 +693,11 @@ TASK_DP["internal/task/device_persist.go"] --> REPO_D
- 数据一致性:通过唯一索引和事务保证数据完整性,通过分区表优化查询性能 - 数据一致性:通过唯一索引和事务保证数据完整性,通过分区表优化查询性能
- 可扩展性:模块化设计支持功能扩展,预留接口便于新业务场景接入 - 可扩展性:模块化设计支持功能扩展,预留接口便于新业务场景接入
**新** 设备持久化和 OTA 升级子系统的设计理念和业务逻辑 **** OTA设计理念保持不变,但实现逻辑已简化
**章节来源** **章节来源**
- [internal/model/user_device.go:5-11](file://internal/model/user_device.go#L5-L11) - [internal/model/user_device.go:5-11](file://internal/model/user_device.go#L5-L11)
- [internal/model/user_active.go:5-12](file://internal/model/user_active.go#L5-L12) - [internal/model/user_active.go:5-12](file://internal/model/user_active.go#L5-L12)
- [internal/model/ota.go:6-42](file://internal/model/ota.go#L6-L42) - [internal/model/ota.go:30-45](file://internal/model/ota.go#L30-L45)
- [internal/task/device_persist.go:24-167](file://internal/task/device_persist.go#L24-L167) - [internal/task/device_persist.go:24-167](file://internal/task/device_persist.go#L24-L167)
- [internal/handler/ota.go:23-132](file://internal/handler/ota.go#L23-L132) - [internal/handler/ota.go:23-144](file://internal/handler/ota.go#L23-L144)
@@ -44,11 +44,10 @@
## 更新摘要 ## 更新摘要
**变更内容** **变更内容**
- 新增分享代码处理器(ShareCodeHandler):实现EQ数据分享功能,支持创建、查询、导入、删除分享码,包含Redis缓存、分布式锁和异步持久化 - OTA处理器内部逻辑已简化:移除了paw相关字段处理,现在专注于标准OTA升级流程
- 新增等化曲线处理器(CurveHandler):实现频响曲线计算和参数化EQ生成功能,支持多种目标曲线和设备源 - 处理器接口保持不变,继续提供/api/v1/audio/ota端点
- 新增分享码持久化任务:定时将Redis中的分享码操作记录刷入MySQL数据库 - 查询逻辑已更新以适配简化的OTA结构,但仍保持原有的黑名单过滤和定向升级功能
- 新增分享码配置:支持灵活的TTL配置格式(分钟、小时、天) - 数据库结构保持不变,仍包含ota、black_list、ota_target_device表
- 更新路由集成:分享码和等化曲线功能已集成到/audio路由组中
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
@@ -168,7 +167,7 @@ MODELLIST --> ENCODE
- **型号查询处理器**:按品牌或型号关键字查询型号列表,现在依赖 ModelRepository 实例。 - **型号查询处理器**:按品牌或型号关键字查询型号列表,现在依赖 ModelRepository 实例。
- **型号检索处理器**:基于 Meilisearch 执行全文检索,依赖搜索客户端实例。 - **型号检索处理器**:基于 Meilisearch 执行全文检索,依赖搜索客户端实例。
- **设备上报处理器**:接收设备信息(MAC、型号、版本、来源 IP),依赖 Redis 客户端。 - **设备上报处理器**:接收设备信息(MAC、型号、版本、来源 IP),依赖 Redis 客户端。
- **OTA固件升级处理器**:处理固件升级请求,支持黑名单过滤、目标设备分布和版本选择等OTA固件升级能力。 - **OTA固件升级处理器**:处理固件升级请求,支持黑名单过滤、目标设备分布和版本选择等OTA固件升级能力。**已简化内部逻辑,移除了paw相关字段处理**。
- **等化曲线处理器**:处理频响曲线计算和参数化EQ生成,支持多种目标曲线和设备源。 - **等化曲线处理器**:处理频响曲线计算和参数化EQ生成,支持多种目标曲线和设备源。
- **分享代码处理器**:处理EQ数据分享功能,支持创建、查询、导入、删除分享码。 - **分享代码处理器**:处理EQ数据分享功能,支持创建、查询、导入、删除分享码。
@@ -457,6 +456,8 @@ RespOK --> End
- [internal/handler/device.go:14-85](file://internal/handler/device.go#L14-L85) - [internal/handler/device.go:14-85](file://internal/handler/device.go#L14-L85)
### OTA固件升级处理器(OTAHandler ### OTA固件升级处理器(OTAHandler
**更新** OTA处理器内部逻辑已简化,移除了paw相关字段处理,现在专注于标准OTA升级流程。
- **职责**:处理固件升级请求,支持黑名单过滤、目标设备分布和版本选择等OTA固件升级能力。 - **职责**:处理固件升级请求,支持黑名单过滤、目标设备分布和版本选择等OTA固件升级能力。
- **输入参数** - **输入参数**
- 查询字符串:model(必填) - 查询字符串:model(必填)
@@ -475,6 +476,7 @@ RespOK --> End
- 黑名单或定向设备检查失败返回统一内部错误 - 黑名单或定向设备检查失败返回统一内部错误
- **数据模型**OTA、BlackList、OTATargetDevice - **数据模型**OTA、BlackList、OTATargetDevice
- **依赖注入**:通过 NewOTAHandler 构造函数注入 OTARepository 和 zap.Logger - **依赖注入**:通过 NewOTAHandler 构造函数注入 OTARepository 和 zap.Logger
- **API端点**/audio/ota(保持不变)
```mermaid ```mermaid
flowchart TD flowchart TD
@@ -902,6 +904,7 @@ ALL --> LOG["zap.Logger"]
- 关注"query ota failed"、"check black list failed"、"check target device failed"等错误日志。 - 关注"query ota failed"、"check black list failed"、"check target device failed"等错误日志。
- 检查数据库连接,确认ota、black_list、ota_target_device表存在且结构正确。 - 检查数据库连接,确认ota、black_list、ota_target_device表存在且结构正确。
- 验证OTA状态、硬件版本号、灰度标识等字段是否符合预期。 - 验证OTA状态、硬件版本号、灰度标识等字段是否符合预期。
- **更新**:OTA处理器内部逻辑已简化,不再处理paw相关字段,如遇相关错误请检查其他字段。
- **等化曲线异常** - **等化曲线异常**
- 校验必填参数 brand、name 是否传入且格式正确。 - 校验必填参数 brand、name 是否传入且格式正确。
- 关注"get curve point failed"、"get model curve failed"等错误日志。 - 关注"get curve point failed"、"get model curve failed"等错误日志。
@@ -946,7 +949,7 @@ ALL --> LOG["zap.Logger"]
- /audio/getModel -> ModelHandler.GetModel - /audio/getModel -> ModelHandler.GetModel
- /audio/modelList -> ModelListHandler.ModelList - /audio/modelList -> ModelListHandler.ModelList
- /audio/reportDevInfo -> DeviceHandler.ReportDevInfo - /audio/reportDevInfo -> DeviceHandler.ReportDevInfo
- /audio/ota -> OTAHandler.GetOTA - /audio/ota -> OTAHandler.GetOTA**已简化内部逻辑**
- /audio/getCurve -> CurveHandler.GetCurve - /audio/getCurve -> CurveHandler.GetCurve
- /audio/modelCurve -> CurveHandler.ModelCurve - /audio/modelCurve -> CurveHandler.ModelCurve
- /audio/shareCreate -> ShareCodeHandler.ExportShareCode - /audio/shareCreate -> ShareCodeHandler.ExportShareCode
@@ -984,6 +987,11 @@ ALL --> LOG["zap.Logger"]
- black_list表:存储OTA黑名单 - black_list表:存储OTA黑名单
- ota_target_device表:存储OTA定向设备 - ota_target_device表:存储OTA定向设备
- share_code_log表:存储分享码操作日志 - share_code_log表:存储分享码操作日志
- **OTA处理器内部逻辑更新**
- 移除了paw相关字段处理,专注于标准OTA升级流程
- 保持原有API端点:/audio/ota
- 查询逻辑已更新以适配简化的OTA结构
- 仍支持黑名单过滤和定向升级功能
- **常用调用示例(路径引用)** - **常用调用示例(路径引用)**
- 品牌查询:[internal/handler/brand.go:25](file://internal/handler/brand.go#L25) - 品牌查询:[internal/handler/brand.go:25](file://internal/handler/brand.go#L25)
- 型号查询:[internal/handler/model.go:25](file://internal/handler/model.go#L25) - 型号查询:[internal/handler/model.go:25](file://internal/handler/model.go#L25)
@@ -31,20 +31,20 @@
- [pkg/encode/base64.go](file://pkg/encode/base64.go) - [pkg/encode/base64.go](file://pkg/encode/base64.go)
- [sql/model.sql](file://sql/model.sql) - [sql/model.sql](file://sql/model.sql)
- [sql/ota.sql](file://sql/ota.sql) - [sql/ota.sql](file://sql/ota.sql)
- [sql/ota_target_device.sql](file://sql/ota_target_device.sql)
- [sql/black_list.sql](file://sql/black_list.sql)
- [sql/share_code_log.sql](file://sql/share_code_log.sql) - [sql/share_code_log.sql](file://sql/share_code_log.sql)
- [sql/user_device.sql](file://sql/user_device.sql) - [sql/user_device.sql](file://sql/user_device.sql)
- [sql/user_active.sql](file://sql/user_active.sql) - [sql/user_active.sql](file://sql/user_active.sql)
- [sql/ota_target_device.sql](file://sql/ota_target_device.sql)
- [cmd/server/main.go](file://cmd/server/main.go) - [cmd/server/main.go](file://cmd/server/main.go)
</cite> </cite>
## 更新摘要 ## 更新摘要
**变更内容** **变更内容**
- 新增分享代码数据模型(ShareCodeData)和相关处理流程 - OTA模型字段简化:移除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,OTA结构现在更加简洁
- 新增目标数据模型(Target),支持曲线目标配置 - OTA模型现在包含核心字段:verCode、verName、url、md5、force、desc、model、hw、target、beta、startTime、endTime、status
- 增强OTA模型,支持布尔值序列化和更多字段 - 数据库表结构同步更新,移除了对应的冗余列
- 新增分享码持久化任务和Redis缓存机制 - 仓库层和处理器层相应调整,移除了对冗余字段的处理
- 扩展路由配置以支持分享码相关API端点
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
@@ -158,7 +158,7 @@ CACHE --> SHARE_TTL
- [internal/handler/brand.go:19-50](file://internal/handler/brand.go#L19-L50) - [internal/handler/brand.go:19-50](file://internal/handler/brand.go#L19-L50)
- [internal/handler/model.go:19-51](file://internal/handler/model.go#L19-L51) - [internal/handler/model.go:19-51](file://internal/handler/model.go#L19-L51)
- [internal/handler/model_list.go:19-57](file://internal/handler/model_list.go#L19-L57) - [internal/handler/model_list.go:19-57](file://internal/handler/model_list.go#L19-L57)
- [internal/handler/ota.go:14-133](file://internal/handler/ota.go#L14-L133) - [internal/handler/ota.go:14-145](file://internal/handler/ota.go#L14-L145)
- [internal/handler/device.go:15-83](file://internal/handler/device.go#L15-L83) - [internal/handler/device.go:15-83](file://internal/handler/device.go#L15-L83)
- [internal/handler/share_code.go:1-383](file://internal/handler/share_code.go#L1-L383) - [internal/handler/share_code.go:1-383](file://internal/handler/share_code.go#L1-L383)
- [internal/handler/curve.go:1-582](file://internal/handler/curve.go#L1-L582) - [internal/handler/curve.go:1-582](file://internal/handler/curve.go#L1-L582)
@@ -170,7 +170,7 @@ CACHE --> SHARE_TTL
- [internal/repository/curve.go:1-66](file://internal/repository/curve.go#L1-L66) - [internal/repository/curve.go:1-66](file://internal/repository/curve.go#L1-L66)
- [internal/model/brand.go:3-7](file://internal/model/brand.go#L3-L7) - [internal/model/brand.go:3-7](file://internal/model/brand.go#L3-L7)
- [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15) - [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15)
- [internal/model/ota.go:5-67](file://internal/model/ota.go#L5-L67) - [internal/model/ota.go:5-63](file://internal/model/ota.go#L5-L63)
- [internal/model/user_device.go:5-12](file://internal/model/user_device.go#L5-L12) - [internal/model/user_device.go:5-12](file://internal/model/user_device.go#L5-L12)
- [internal/model/user_active.go:5-13](file://internal/model/user_active.go#L5-L13) - [internal/model/user_active.go:5-13](file://internal/model/user_active.go#L5-L13)
- [internal/model/share_code.go:14-25](file://internal/model/share_code.go#L14-L25) - [internal/model/share_code.go:14-25](file://internal/model/share_code.go#L14-L25)
@@ -180,11 +180,12 @@ CACHE --> SHARE_TTL
- [internal/config/database.go:17-72](file://internal/config/database.go#L17-L72) - [internal/config/database.go:17-72](file://internal/config/database.go#L17-L72)
- [internal/config/share_code_ttl.go:12-60](file://internal/config/share_code_ttl.go#L12-L60) - [internal/config/share_code_ttl.go:12-60](file://internal/config/share_code_ttl.go#L12-L60)
- [sql/model.sql:20-38](file://sql/model.sql#L20-L38) - [sql/model.sql:20-38](file://sql/model.sql#L20-L38)
- [sql/ota.sql:23-44](file://sql/ota.sql#L23-L44) - [sql/ota.sql:23-40](file://sql/ota.sql#L23-L40)
- [sql/ota_target_device.sql:23-31](file://sql/ota_target_device.sql#L23-L31)
- [sql/black_list.sql:23-30](file://sql/black_list.sql#L23-L30)
- [sql/share_code_log.sql:8-23](file://sql/share_code_log.sql#L8-L23) - [sql/share_code_log.sql:8-23](file://sql/share_code_log.sql#L8-L23)
- [sql/user_device.sql:23-32](file://sql/user_device.sql#L23-L32) - [sql/user_device.sql:23-32](file://sql/user_device.sql#L23-L32)
- [sql/user_active.sql:23-32](file://sql/user_active.sql#L23-L32) - [sql/user_active.sql:23-32](file://sql/user_active.sql#L23-L32)
- [sql/ota_target_device.sql:23-31](file://sql/ota_target_device.sql#L23-L31)
- [internal/task/device_persist.go:14-167](file://internal/task/device_persist.go#L14-L167) - [internal/task/device_persist.go:14-167](file://internal/task/device_persist.go#L14-L167)
- [internal/task/share_code_persist.go:1-232](file://internal/task/share_code_persist.go#L1-L232) - [internal/task/share_code_persist.go:1-232](file://internal/task/share_code_persist.go#L1-L232)
@@ -230,7 +231,7 @@ CACHE --> SHARE_TTL
**章节来源** **章节来源**
- [internal/model/brand.go:3-7](file://internal/model/brand.go#L3-L7) - [internal/model/brand.go:3-7](file://internal/model/brand.go#L3-L7)
- [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15) - [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15)
- [internal/model/ota.go:5-67](file://internal/model/ota.go#L5-L67) - [internal/model/ota.go:5-63](file://internal/model/ota.go#L5-L63)
- [internal/model/share_code.go:14-25](file://internal/model/share_code.go#L14-L25) - [internal/model/share_code.go:14-25](file://internal/model/share_code.go#L14-L25)
- [internal/model/target.go:5-14](file://internal/model/target.go#L5-L14) - [internal/model/target.go:5-14](file://internal/model/target.go#L5-L14)
- [internal/model/user_device.go:5-12](file://internal/model/user_device.go#L5-L12) - [internal/model/user_device.go:5-12](file://internal/model/user_device.go#L5-L12)
@@ -244,7 +245,7 @@ CACHE --> SHARE_TTL
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50) - [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51) - [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
- [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57) - [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57)
- [internal/handler/ota.go:23-133](file://internal/handler/ota.go#L23-L133) - [internal/handler/ota.go:23-145](file://internal/handler/ota.go#L23-L145)
- [internal/handler/device.go:27-83](file://internal/handler/device.go#L27-L83) - [internal/handler/device.go:27-83](file://internal/handler/device.go#L27-L83)
- [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383) - [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383)
- [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582) - [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582)
@@ -402,42 +403,41 @@ ModelRepository --> Model : "返回"
### OTA 固件升级模型 ### OTA 固件升级模型
- **设计理念** - **设计理念**
- OTA模型用于管理固件升级信息,支持强制升级、灰度发布、定向升级等功能。 - OTA模型用于管理固件升级信息,支持强制升级、灰度发布、定向升级等功能。
- **更新**OTA模型已简化,移除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,现在只包含核心升级信息字段。
- **字段定义与约束** - **字段定义与约束**
- OTA模型: - OTA模型:
- id:整数,主键,自增。 - id:整数,主键,自增。
- verCode:整数,版本号,用于排序。 - VerCode:整数,版本号,用于排序。
- verName:字符串,版本名称。 - VerName:字符串,版本名称。
- url:字符串,固件下载地址。 - URL:字符串,固件下载地址。
- md5:字符串,固件MD5校验值。 - MD5:字符串,固件MD5校验值。
- forceBoolInt,是否强制升级(true/false)。 - ForceBoolInt,是否强制升级(true/false)。
- desc:字符串指针,升级描述。 - Desc:字符串指针,升级描述。
- model:字符串指针,对应设备型号。 - Model:字符串指针,对应设备型号。
- hw:整数,硬件版本号。 - HW:整数,硬件版本号。
- targetBoolInt,是否定向升级(true/false)。 - TargetBoolInt,是否定向升级(true/false)。
- betaBoolInt,是否灰度发布(true/false)。 - BetaBoolInt,是否灰度发布(true/false)。
- pawVerCode:整数,配套软件版本号 - StartTime:时间戳指针,升级开始时间
- pawVerName:字符串,配套软件版本名称 - EndTime:时间戳指针,升级结束时间
- pawUrl:字符串,配套软件下载地址 - Status:整数,状态(1-可用,0-不可用)
- pawMD5:字符串,配套软件MD5校验值。
- startTime:时间戳指针,升级开始时间。
- endTime:时间戳指针,升级结束时间。
- status:整数,状态(1-可用,0-不可用)。
- BlackList模型: - BlackList模型:
- id:整数,主键,自增。 - id:整数,主键,自增。
- ota_id:整数,关联OTA记录ID。 - OTAID:整数,关联OTA记录ID。
- mac:字符串,设备MAC地址。 - Mac:字符串,设备MAC地址。
- create_at:时间戳,创建时间。 - CreateAt:时间戳,创建时间。
- OTATargetDevice模型: - OTATargetDevice模型:
- id:整数,主键,自增。 - id:整数,主键,自增。
- ota_id:整数,关联OTA记录ID。 - OTAID:整数,关联OTA记录ID。
- mac_addr:字符串,设备MAC地址。 - MacAddr:字符串,设备MAC地址。
- type:整数,类型(1-白名单,2-黑名单)。 - Type:整数,类型(1-白名单,2-黑名单)。
- create_at:时间戳,创建时间。 - CreateAt:时间戳,创建时间。
- **业务含义** - **业务含义**
- 支持复杂的固件升级策略,包括强制升级、灰度发布、定向升级和黑名单管理。 - 支持复杂的固件升级策略,包括强制升级、灰度发布、定向升级和黑名单管理。
- 简化的字段结构提高了数据模型的清晰度和维护性。
- **数据库映射** - **数据库映射**
- 表名:ota、black_list、ota_target_device。 - 表名:ota、black_list、ota_target_device。
- 字段:完整映射关系详见数据库表结构。 - 字段:完整映射关系详见数据库表结构。
- **更新**OTA表不再包含pawVerCode、pawVerName、pawUrl、pawMd5字段。
- **ORM 映射配置** - **ORM 映射配置**
- 使用 sql.NullString 和 sql.NullTime 扫描可空列。 - 使用 sql.NullString 和 sql.NullTime 扫描可空列。
- BoolInt类型支持数据库整型与JSON布尔值的双向转换。 - BoolInt类型支持数据库整型与JSON布尔值的双向转换。
@@ -449,37 +449,33 @@ ModelRepository --> Model : "返回"
```mermaid ```mermaid
classDiagram classDiagram
class OTA { class OTA {
+int id +int ID
+int verCode +int VerCode
+string verName +string VerName
+string url +string URL
+string md5 +string MD5
+BoolInt force +BoolInt Force
+*string desc +*string Desc
+*string model +*string Model
+int hw +int HW
+BoolInt target +BoolInt Target
+BoolInt beta +BoolInt Beta
+int pawVerCode +*time StartTime
+string pawVerName +*time EndTime
+string pawUrl +int Status
+string pawMD5
+*time startTime
+*time endTime
+int status
} }
class BlackList { class BlackList {
+int id +int ID
+int ota_id +int OTAID
+string mac +string Mac
+time create_at +time CreateAt
} }
class OTATargetDevice { class OTATargetDevice {
+int id +int ID
+int ota_id +int OTAID
+string mac_addr +string MacAddr
+int type +int Type
+time create_at +time CreateAt
} }
class OTARepository { class OTARepository {
-db *sql.DB -db *sql.DB
@@ -495,15 +491,15 @@ OTARepository --> OTATargetDevice : "返回"
``` ```
**图表来源** **图表来源**
- [internal/model/ota.go:29-67](file://internal/model/ota.go#L29-L67) - [internal/model/ota.go:29-63](file://internal/model/ota.go#L29-L63)
- [internal/repository/ota.go:19-159](file://internal/repository/ota.go#L19-L159) - [internal/repository/ota.go:19-159](file://internal/repository/ota.go#L19-L159)
- [sql/ota.sql:24-44](file://sql/ota.sql#L24-L44) - [sql/ota.sql:24-40](file://sql/ota.sql#L24-L40)
- [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31) - [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31)
**章节来源** **章节来源**
- [internal/model/ota.go:5-67](file://internal/model/ota.go#L5-L67) - [internal/model/ota.go:5-63](file://internal/model/ota.go#L5-L63)
- [internal/repository/ota.go:19-159](file://internal/repository/ota.go#L19-L159) - [internal/repository/ota.go:19-159](file://internal/repository/ota.go#L19-L159)
- [sql/ota.sql:23-44](file://sql/ota.sql#L23-L44) - [sql/ota.sql:23-40](file://sql/ota.sql#L23-L40)
- [sql/ota_target_device.sql:23-31](file://sql/ota_target_device.sql#L23-L31) - [sql/ota_target_device.sql:23-31](file://sql/ota_target_device.sql#L23-L31)
### 分享码数据模型 ### 分享码数据模型
@@ -714,6 +710,7 @@ DeviceRepository --> UserActive : "返回"
- **OTA处理器特殊逻辑** - **OTA处理器特殊逻辑**
- 支持参数校验、黑名单检查、定向设备检查等复杂业务逻辑。 - 支持参数校验、黑名单检查、定向设备检查等复杂业务逻辑。
- 根据不同情况返回不同的OTA升级信息。 - 根据不同情况返回不同的OTA升级信息。
- **更新**:OTA处理器现在处理简化的字段结构,移除了对paw*字段的处理。
- **设备处理器特殊逻辑** - **设备处理器特殊逻辑**
- 将设备信息写入Redis缓存,支持异步持久化。 - 将设备信息写入Redis缓存,支持异步持久化。
- 提供设备信息上报接口。 - 提供设备信息上报接口。
@@ -760,7 +757,7 @@ H-->>C : "200 OK + EQ数据"
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50) - [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51) - [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
- [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57) - [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57)
- [internal/handler/ota.go:23-133](file://internal/handler/ota.go#L23-L133) - [internal/handler/ota.go:23-145](file://internal/handler/ota.go#L23-L145)
- [internal/handler/device.go:27-83](file://internal/handler/device.go#L27-L83) - [internal/handler/device.go:27-83](file://internal/handler/device.go#L27-L83)
- [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383) - [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383)
- [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582) - [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582)
@@ -777,6 +774,7 @@ H-->>C : "200 OK + EQ数据"
- 支持按model+hw+beta+status=1查询最新OTA记录。 - 支持按model+hw+beta+status=1查询最新OTA记录。
- 支持黑名单检查和定向设备检查。 - 支持黑名单检查和定向设备检查。
- 提供多种查询策略以适应不同的升级场景。 - 提供多种查询策略以适应不同的升级场景。
- **更新**:OTA查询现在使用简化的字段列表,移除了对paw*字段的查询。
- **设备查询** - **设备查询**
- 支持按MAC地址查询设备信息。 - 支持按MAC地址查询设备信息。
- 支持按MAC地址和日期查询活跃记录。 - 支持按MAC地址和日期查询活跃记录。
@@ -882,7 +880,7 @@ Task_Share --> Redis
- [internal/handler/brand.go:14-50](file://internal/handler/brand.go#L14-L50) - [internal/handler/brand.go:14-50](file://internal/handler/brand.go#L14-L50)
- [internal/handler/model.go:14-51](file://internal/handler/model.go#L14-L51) - [internal/handler/model.go:14-51](file://internal/handler/model.go#L14-L51)
- [internal/handler/model_list.go:14-57](file://internal/handler/model_list.go#L14-L57) - [internal/handler/model_list.go:14-57](file://internal/handler/model_list.go#L14-L57)
- [internal/handler/ota.go:14-133](file://internal/handler/ota.go#L14-L133) - [internal/handler/ota.go:14-145](file://internal/handler/ota.go#L14-L145)
- [internal/handler/device.go:15-83](file://internal/handler/device.go#L15-L83) - [internal/handler/device.go:15-83](file://internal/handler/device.go#L15-L83)
- [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383) - [internal/handler/share_code.go:15-383](file://internal/handler/share_code.go#L15-L383)
- [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582) - [internal/handler/curve.go:27-582](file://internal/handler/curve.go#L27-L582)
@@ -909,6 +907,7 @@ Task_Share --> Redis
- UserActive表对(mac_addr, active_date)建立联合索引,支持按日期分区查询。 - UserActive表对(mac_addr, active_date)建立联合索引,支持按日期分区查询。
- share_code_log表对(mac_addr, share_code, create_at)建立索引,支持分享码查询。 - share_code_log表对(mac_addr, share_code, create_at)建立索引,支持分享码查询。
- 查询时优先按品牌名匹配,减少 LIKE 的范围。 - 查询时优先按品牌名匹配,减少 LIKE 的范围。
- **更新**:OTA查询现在使用简化的字段列表,减少了不必要的字段扫描。
- **扫描与内存** - **扫描与内存**
- 使用 sql.NullString 扫描可空列,避免零值歧义;转换为指针字符串减少冗余存储。 - 使用 sql.NullString 扫描可空列,避免零值歧义;转换为指针字符串减少冗余存储。
- OTA模型使用BoolInt类型处理布尔值,支持数据库整型与JSON布尔值的双向转换。 - OTA模型使用BoolInt类型处理布尔值,支持数据库整型与JSON布尔值的双向转换。
@@ -927,7 +926,7 @@ Task_Share --> Redis
**章节来源** **章节来源**
- [sql/model.sql:34-35](file://sql/model.sql#L34-L35) - [sql/model.sql:34-35](file://sql/model.sql#L34-L35)
- [sql/ota.sql:24-44](file://sql/ota.sql#L24-L44) - [sql/ota.sql:24-40](file://sql/ota.sql#L24-L40)
- [sql/share_code_log.sql:20-23](file://sql/share_code_log.sql#L20-L23) - [sql/share_code_log.sql:20-23](file://sql/share_code_log.sql#L20-L23)
- [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32) - [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32)
- [sql/user_active.sql:24-32](file://sql/user_active.sql#L24-L32) - [sql/user_active.sql:24-32](file://sql/user_active.sql#L24-L32)
@@ -957,6 +956,7 @@ Task_Share --> Redis
- 检查Redis:确认设备信息、分享码数据是否正确写入Redis缓存。 - 检查Redis:确认设备信息、分享码数据是否正确写入Redis缓存。
- 监控任务:确认设备持久化任务和分享码持久化任务是否按预期执行。 - 监控任务:确认设备持久化任务和分享码持久化任务是否按预期执行。
- 检查分布式锁:确认分享码操作的分布式锁状态和超时处理。 - 检查分布式锁:确认分享码操作的分布式锁状态和超时处理。
- **更新**:检查OTA表结构,确认paw*字段不存在,验证简化的字段结构。
**章节来源** **章节来源**
- [internal/config/database.go:57-72](file://internal/config/database.go#L57-L72) - [internal/config/database.go:57-72](file://internal/config/database.go#L57-L72)
@@ -965,12 +965,16 @@ Task_Share --> Redis
- [internal/handler/model_list.go:39-42](file://internal/handler/model_list.go#L39-L42) - [internal/handler/model_list.go:39-42](file://internal/handler/model_list.go#L39-L42)
- [internal/handler/ota.go:31-48](file://internal/handler/ota.go#L31-L48) - [internal/handler/ota.go:31-48](file://internal/handler/ota.go#L31-L48)
- [internal/handler/device.go:33-39](file://internal/handler/device.go#L33-L39) - [internal/handler/device.go:33-39](file://internal/handler/device.go#L33-L39)
- [internal/handler/share_code.go:46-81](file://internal/handler/share_code.go#L46-81) - [internal/handler/share_code.go:46-81](file://internal/handler/share_code.go#L46-L81)
- [internal/handler/curve.go:302-368](file://internal/handler/curve.go#L302-L368) - [internal/handler/curve.go:302-368](file://internal/handler/curve.go#L302-L368)
- [internal/response/response.go:30-37](file://internal/response/response.go#L30-L37) - [internal/response/response.go:30-37](file://internal/response/response.go#L30-L37)
## 结论 ## 结论
本项目的数据模型设计简洁明确:Brand 与 Model 分别承担品牌与型号的维度,通过仓库层的原生 SQL 访问实现高效查询;处理器层统一响应与可选编码,提升传输效率与前端体验。新增的分享码功能、目标曲线模型和增强的OTA模型进一步完善了系统的数据模型体系,支持复杂的固件升级策略、设备信息跟踪、用户行为分析和EQ数据分享功能。数据库层面通过唯一索引与合理字段设计保障一致性与性能。Redis缓存层提供了高性能的临时数据存储和分布式锁机制。建议在后续迭代中引入显式的校验与转换层,增强健壮性与可维护性,同时考虑添加更多的监控指标和告警机制。 本项目的数据模型设计简洁明确:Brand 与 Model 分别承担品牌与型号的维度,通过仓库层的原生 SQL 访问实现高效查询;处理器层统一响应与可选编码,提升传输效率与前端体验。新增的分享码功能、目标曲线模型和增强的OTA模型进一步完善了系统的数据模型体系,支持复杂的固件升级策略、设备信息跟踪、用户行为分析和EQ数据分享功能。数据库层面通过唯一索引与合理字段设计保障一致性与性能。Redis缓存层提供了高性能的临时数据存储和分布式锁机制。
**更新**:OTA模型经过简化重构,移除了pawVerCode、pawVerName、pawUrl、pawMd5四个冗余字段,现在只包含核心升级信息,提高了数据模型的清晰度和维护性。新的字段结构更加简洁,减少了不必要的数据冗余,同时保持了完整的升级策略支持能力。
建议在后续迭代中引入显式的校验与转换层,增强健壮性与可维护性,同时考虑添加更多的监控指标和告警机制。
## 附录 ## 附录
@@ -979,8 +983,9 @@ Task_Share --> Redis
- 字段:id(主键)、brand_name、name、form、rig、source、eq_key、create_at。 - 字段:id(主键)、brand_name、name、form、rig、source、eq_key、create_at。
- 约束:唯一索引 (brand_name, name)。 - 约束:唯一索引 (brand_name, name)。
- **表:ota** - **表:ota**
- 字段:id(主键)、verCode、verName、url、md5、force、desc、model、hw、target、beta、pawVerCode、pawVerName、pawUrl、pawMd5、startTime、endTime、status。 - 字段:id(主键)、verCode、verName、url、md5、force、desc、model、hw、target、beta、startTime、endTime、status。
- 约束:无显式约束。 - 约束:无显式约束。
- **更新**:移除了pawVerCode、pawVerName、pawUrl、pawMd5字段。
- **表:black_list** - **表:black_list**
- 字段:id(主键)、ota_id、mac、create_at。 - 字段:id(主键)、ota_id、mac、create_at。
- 约束:无显式约束。 - 约束:无显式约束。
@@ -1003,33 +1008,29 @@ Task_Share --> Redis
- Model.id ↔ model.id - Model.id ↔ model.id
- Model.brandName ↔ model.brand_name - Model.brandName ↔ model.brand_name
- Model.name ↔ model.name - Model.name ↔ model.name
- OTA.id ↔ ota.id - OTA.ID ↔ ota.id
- OTA.verCode ↔ ota.verCode - OTA.VerCode ↔ ota.verCode
- OTA.verName ↔ ota.verName - OTA.VerName ↔ ota.verName
- OTA.url ↔ ota.url - OTA.URL ↔ ota.url
- OTA.md5 ↔ ota.md5 - OTA.MD5 ↔ ota.md5
- OTA.force ↔ ota.force - OTA.Force ↔ ota.force
- OTA.desc ↔ ota.desc - OTA.Desc ↔ ota.desc
- OTA.model ↔ ota.model - OTA.Model ↔ ota.model
- OTA.hw ↔ ota.hw - OTA.HW ↔ ota.hw
- OTA.target ↔ ota.target - OTA.Target ↔ ota.target
- OTA.beta ↔ ota.beta - OTA.Beta ↔ ota.beta
- OTA.pawVerCode ↔ ota.pawVerCode - OTA.StartTime ↔ ota.startTime
- OTA.pawVerName ↔ ota.pawVerName - OTA.EndTime ↔ ota.endTime
- OTA.pawUrl ↔ ota.pawUrl - OTA.Status ↔ ota.status
- OTA.pawMD5 ↔ ota.pawMD5 - BlackList.ID ↔ black_list.id
- OTA.startTime ↔ ota.startTime - BlackList.OTAID ↔ black_list.ota_id
- OTA.endTime ↔ ota.endTime - BlackList.Mac ↔ black_list.mac
- OTA.status ↔ ota.status - BlackList.CreateAt ↔ black_list.create_at
- BlackList.id ↔ black_list.id - OTATargetDevice.ID ↔ ota_target_device.id
- BlackList.ota_id ↔ black_list.ota_id - OTATargetDevice.OTAID ↔ ota_target_device.ota_id
- BlackList.mac ↔ black_list.mac - OTATargetDevice.MacAddr ↔ ota_target_device.mac_addr
- BlackList.create_at ↔ black_list.create_at - OTATargetDevice.Type ↔ ota_target_device.type
- OTATargetDevice.id ↔ ota_target_device.id - OTATargetDevice.CreateAt ↔ ota_target_device.create_at
- OTATargetDevice.ota_id ↔ ota_target_device.ota_id
- OTATargetDevice.mac_addr ↔ ota_target_device.mac_addr
- OTATargetDevice.type ↔ ota_target_device.type
- OTATargetDevice.create_at ↔ ota_target_device.create_at
- UserDevice.id ↔ user_device.id - UserDevice.id ↔ user_device.id
- UserDevice.mac_addr ↔ user_device.mac_addr - UserDevice.mac_addr ↔ user_device.mac_addr
- UserDevice.model ↔ user_device.model - UserDevice.model ↔ user_device.model
@@ -1059,14 +1060,15 @@ Task_Share --> Redis
**章节来源** **章节来源**
- [sql/model.sql:24-35](file://sql/model.sql#L24-L35) - [sql/model.sql:24-35](file://sql/model.sql#L24-L35)
- [sql/ota.sql:24-44](file://sql/ota.sql#L24-L44) - [sql/ota.sql:24-40](file://sql/ota.sql#L24-L40)
- [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31) - [sql/ota_target_device.sql:24-31](file://sql/ota_target_device.sql#L24-L31)
- [sql/black_list.sql:24-30](file://sql/black_list.sql#L24-L30)
- [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32) - [sql/user_device.sql:24-32](file://sql/user_device.sql#L24-L32)
- [sql/user_active.sql:24-32](file://sql/user_active.sql#L24-L32) - [sql/user_active.sql:24-32](file://sql/user_active.sql#L24-L32)
- [sql/share_code_log.sql:9-23](file://sql/share_code_log.sql#L9-L23) - [sql/share_code_log.sql:9-23](file://sql/share_code_log.sql#L9-L23)
- [sql/target.sql:24-31](file://sql/target.sql#L24-L31) - [sql/target.sql:24-31](file://sql/target.sql#L24-L31)
- [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15) - [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15)
- [internal/model/ota.go:29-67](file://internal/model/ota.go#L29-L67) - [internal/model/ota.go:29-63](file://internal/model/ota.go#L29-L63)
- [internal/model/user_device.go:5-12](file://internal/model/user_device.go#L5-L12) - [internal/model/user_device.go:5-12](file://internal/model/user_device.go#L5-L12)
- [internal/model/user_active.go:5-13](file://internal/model/user_active.go#L5-L13) - [internal/model/user_active.go:5-13](file://internal/model/user_active.go#L5-L13)
- [internal/model/share_code.go:14-25](file://internal/model/share_code.go#L14-L25) - [internal/model/share_code.go:14-25](file://internal/model/share_code.go#L14-L25)
@@ -1096,7 +1098,8 @@ Task_Share --> Redis
- 方法:GET - 方法:GET
- 参数:model(必需)、hw(必需)、mac(可选)、beta(可选)、base64Resp(可选) - 参数:model(必需)、hw(必需)、mac(可选)、beta(可选)、base64Resp(可选)
- 返回:OTA对象或 Base64 编码后的 JSON - 返回:OTA对象或 Base64 编码后的 JSON
- 参考路径:[internal/handler/ota.go:23-133](file://internal/handler/ota.go#L23-L133) - **更新**:返回的OTA对象现在包含简化的字段结构
- 参考路径:[internal/handler/ota.go:23-145](file://internal/handler/ota.go#L23-L145)
- **设备信息上报** - **设备信息上报**
- 路由:/audio/reportDevInfo - 路由:/audio/reportDevInfo
- 方法:GET - 方法:GET
@@ -1133,7 +1136,7 @@ Task_Share --> Redis
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50) - [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51) - [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
- [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57) - [internal/handler/model_list.go:26-57](file://internal/handler/model_list.go#L26-L57)
- [internal/handler/ota.go:23-133](file://internal/handler/ota.go#L23-L133) - [internal/handler/ota.go:23-145](file://internal/handler/ota.go#L23-L145)
- [internal/handler/device.go:27-83](file://internal/handler/device.go#L27-L83) - [internal/handler/device.go:27-83](file://internal/handler/device.go#L27-L83)
- [internal/handler/share_code.go:40-125](file://internal/handler/share_code.go#L40-L125) - [internal/handler/share_code.go:40-125](file://internal/handler/share_code.go#L40-L125)
- [internal/handler/share_code.go:192-211](file://internal/handler/share_code.go#L192-L211) - [internal/handler/share_code.go:192-211](file://internal/handler/share_code.go#L192-L211)
@@ -1146,11 +1149,13 @@ Task_Share --> Redis
- 对可空字段提供默认值策略,避免前端空值判断复杂化。 - 对可空字段提供默认值策略,避免前端空值判断复杂化。
- OTA模型支持复杂的升级策略,建议在业务层添加更多的参数验证。 - OTA模型支持复杂的升级策略,建议在业务层添加更多的参数验证。
- 分享码模型支持多种设备型号,建议添加设备型号验证和限制。 - 分享码模型支持多种设备型号,建议添加设备型号验证和限制。
- **更新**:OTA模型简化后,减少了字段验证的复杂度,但仍需确保核心字段的完整性。
- **版本管理与向后兼容** - **版本管理与向后兼容**
- 通过 API 版本号(如 /api/v1)隔离变更;新增字段采用可选策略,保持旧字段必填。 - 通过 API 版本号(如 /api/v1)隔离变更;新增字段采用可选策略,保持旧字段必填。
- 对于破坏性变更,提供迁移脚本与双写策略。 - 对于破坏性变更,提供迁移脚本与双写策略。
- OTA升级策略的变更需要谨慎处理,确保向后兼容性。 - OTA升级策略的变更需要谨慎处理,确保向后兼容性。
- 分享码功能的新增不影响现有API,保持向前兼容。 - 分享码功能的新增不影响现有API,保持向前兼容。
- **更新**:OTA模型的简化属于向后兼容的重构,不会影响现有API调用。
- **性能优化** - **性能优化**
- 为高频查询字段建立索引;避免 SELECT *,仅选择必要字段。 - 为高频查询字段建立索引;避免 SELECT *,仅选择必要字段。
- 对大列表启用可选 Base64 编码;结合分页与缓存策略。 - 对大列表启用可选 Base64 编码;结合分页与缓存策略。
@@ -1158,6 +1163,7 @@ Task_Share --> Redis
- OTA查询使用复合索引,支持快速定位最新OTA记录。 - OTA查询使用复合索引,支持快速定位最新OTA记录。
- 分享码使用Redis缓存,支持TTL自动过期和分布式锁。 - 分享码使用Redis缓存,支持TTL自动过期和分布式锁。
- 目标曲线使用Redis缓存,优化fr数据的独立存储。 - 目标曲线使用Redis缓存,优化fr数据的独立存储。
- **更新**:OTA查询现在使用简化的字段列表,减少了查询开销。
- **错误处理与可观测性** - **错误处理与可观测性**
- 统一错误码与消息格式;记录关键链路日志;对数据库与外部服务增加超时与重试。 - 统一错误码与消息格式;记录关键链路日志;对数据库与外部服务增加超时与重试。
- OTA查询失败需要详细的日志记录,包括参数、查询结果等。 - OTA查询失败需要详细的日志记录,包括参数、查询结果等。
@@ -1177,3 +1183,4 @@ Task_Share --> Redis
- 添加任务调度监控,确保持久化任务正常执行。 - 添加任务调度监控,确保持久化任务正常执行。
- 添加分布式锁监控,防止死锁和资源竞争。 - 添加分布式锁监控,防止死锁和资源竞争。
- 添加S3访问监控,确保CSV文件读取正常。 - 添加S3访问监控,确保CSV文件读取正常。
- **更新**:监控OTA表结构变化,确保简化的字段结构得到正确应用。
@@ -46,13 +46,10 @@
## 更新摘要 ## 更新摘要
**变更内容** **变更内容**
- 新增分享代码仓储层(ShareCodeRepository),支持分享码日志管理与数据库操作 - OTA仓库层实现已移除pawVerCode、pawVerName、pawUrl、pawMd5字段,简化了查询逻辑
- 增强曲线仓储层(CurveRepository),支持频响曲线数据查询与缓存合并 - OTA模型结构已精简,移除了不必要的字段,提高了数据传输效率
- 新增分享码缓存层(ShareCodeCache),提供高级Redis缓存功能与Lua原子操作 - OTA查询方法的SQL语句已优化,减少了字段选择和扫描操作
- 新增分享码持久化任务(ShareCodePersistTask),实现异步数据同步 - OTA表结构已更新,移除了相关字段定义
- 新增分享码处理器(ShareCodeHandler),支持完整的分享码生命周期管理
- 扩展Handler层以支持分享码创建、查询、导入、导出和删除操作
- 增强缓存策略,支持fr数据分离存储和分布式锁机制
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
@@ -246,7 +243,7 @@ SHARE_LOG_TBL --> DB_SQL
- **BrandRepository**:负责品牌列表查询,支持缓存感知的全量查询和按名称模糊过滤,返回 Brand 领域对象切片。 - **BrandRepository**:负责品牌列表查询,支持缓存感知的全量查询和按名称模糊过滤,返回 Brand 领域对象切片。
- **ModelRepository**:负责型号列表查询,支持缓存感知的按品牌精确匹配、按型号名模糊匹配和全量查询,返回 Model 领域对象切片,并对可空字段进行 NullString 到指针字符串的安全转换。 - **ModelRepository**:负责型号列表查询,支持缓存感知的按品牌精确匹配、按型号名模糊匹配和全量查询,返回 Model 领域对象切片,并对可空字段进行 NullString 到指针字符串的安全转换。
- **DeviceRepository**:负责设备信息管理,支持按MAC地址查询设备、插入新设备、更新设备版本信息,以及用户活跃信息的查询和更新。 - **DeviceRepository**:负责设备信息管理,支持按MAC地址查询设备、插入新设备、更新设备版本信息,以及用户活跃信息的查询和更新。
- **OTARepository**:负责固件升级信息查询,支持按型号、硬件版本、灰度标识查询最新OTA记录,黑名单检查、定向设备筛选等功能。 - **OTARepository**:负责固件升级信息查询,支持按型号、硬件版本、灰度标识查询最新OTA记录,黑名单检查、定向设备筛选等功能。**已精简**:移除了pawVerCode、pawVerName、pawUrl、pawMd5字段,简化了查询逻辑和数据处理流程。
- **CurveRepository**:负责频响曲线数据查询,支持按品牌+型号查询Model信息和按标签查询Target信息,为曲线缓存提供数据支撑。 - **CurveRepository**:负责频响曲线数据查询,支持按品牌+型号查询Model信息和按标签查询Target信息,为曲线缓存提供数据支撑。
- **ShareCodeRepository**:负责分享码日志管理,支持插入分享码操作日志、查询导出日志等数据库操作,提供完整的分享码数据持久化能力。 - **ShareCodeRepository**:负责分享码日志管理,支持插入分享码操作日志、查询导出日志等数据库操作,提供完整的分享码数据持久化能力。
- **CurveCache**:新增的曲线缓存层,支持fr数据分离存储、分布式锁机制、缓存合并逻辑,优化曲线数据访问性能。 - **CurveCache**:新增的曲线缓存层,支持fr数据分离存储、分布式锁机制、缓存合并逻辑,优化曲线数据访问性能。
@@ -526,6 +523,7 @@ DeviceRepository --> UserActive : "活跃信息"
- 定向设备检查:检查设备是否在指定OTA的定向设备列表中 - 定向设备检查:检查设备是否在指定OTA的定向设备列表中
- 可空字段处理:使用 sql.NullString 和 sql.NullTime 安全处理数据库可空字段 - 可空字段处理:使用 sql.NullString 和 sql.NullTime 安全处理数据库可空字段
- 复杂查询:支持子查询、条件筛选、时间范围检查等复杂业务逻辑 - 复杂查询:支持子查询、条件筛选、时间范围检查等复杂业务逻辑
- **已精简**:移除了pawVerCode、pawVerName、pawUrl、pawMd5字段,简化了查询逻辑和数据处理流程
- **业务逻辑** - **业务逻辑**
- 支持灰度发布(beta=1)和正式发布(beta=0)两种模式 - 支持灰度发布(beta=1)和正式发布(beta=0)两种模式
- 支持强制升级(force=1)和普通升级(force=0 - 支持强制升级(force=1)和普通升级(force=0
@@ -550,16 +548,12 @@ class OTA {
+string VerName +string VerName
+string URL +string URL
+string MD5 +string MD5
+int Force +BoolInt Force
+*string Desc +*string Desc
+*string Model +*string Model
+int HW +int HW
+int Target +BoolInt Target
+int Beta +BoolInt Beta
+int PawVerCode
+string PawVerName
+string PawURL
+string PawMD5
+*time StartTime +*time StartTime
+*time EndTime +*time EndTime
+int Status +int Status
@@ -1120,7 +1114,7 @@ MD_CACHE --> REDIS_CLIENT
- BrandRepository:按名称模糊匹配,建议在 name 上建立合适索引;对大结果集引入分页。 - BrandRepository:按名称模糊匹配,建议在 name 上建立合适索引;对大结果集引入分页。
- ModelRepository:按品牌名精确匹配或按型号名模糊匹配,建议为 brand_name 与 name 建立索引;对大结果集引入分页。 - ModelRepository:按品牌名精确匹配或按型号名模糊匹配,建议为 brand_name 与 name 建立索引;对大结果集引入分页。
- DeviceRepositoryuser_device 表的 MAC 地址建立唯一索引,user_active 表建立复合索引(mac_addr, active_date)。 - DeviceRepositoryuser_device 表的 MAC 地址建立唯一索引,user_active 表建立复合索引(mac_addr, active_date)。
- OTARepositoryota 表建立复合索引(model, hw, beta, status),black_list 表建立索引(ota_id, mac),ota_target_device 表建立索引(ota_id, mac_addr)。 - OTARepositoryota 表建立复合索引(model, hw, beta, status),black_list 表建立索引(ota_id, mac),ota_target_device 表建立索引(ota_id, mac_addr)。**已优化**:移除了pawVerCode、pawVerName、pawUrl、pawMd5字段,减少了查询字段数量,提升了查询性能。
- CurveRepositorymodel 表建立复合索引(brand_name, name),target 表建立索引(label)。 - CurveRepositorymodel 表建立复合索引(brand_name, name),target 表建立索引(label)。
- ShareCodeRepositoryshare_code_log 表建立索引(mac_addr, share_code, create_at)。 - ShareCodeRepositoryshare_code_log 表建立索引(mac_addr, share_code, create_at)。
- 应用层过滤:在缓存命中时进行过滤,减少数据库压力。 - 应用层过滤:在缓存命中时进行过滤,减少数据库压力。
@@ -1175,7 +1169,7 @@ MD_CACHE --> REDIS_CLIENT
- 排查:检查设备持久化任务日志,确认Redis连接正常;验证user_device和user_active表结构;检查JSON数据格式;确认定时任务正常运行。 - 排查:检查设备持久化任务日志,确认Redis连接正常;验证user_device和user_active表结构;检查JSON数据格式;确认定时任务正常运行。
- **OTA查询错误** - **OTA查询错误**
- 现象:OTA升级查询返回错误或结果不符合预期。 - 现象:OTA升级查询返回错误或结果不符合预期。
- 排查:检查OTA表数据完整性,确认status=1且有效时间范围内;验证黑名单和定向设备表数据;检查参数传递(model、hw、beta、mac)。 - 排查:检查OTA表数据完整性,确认status=1且有效时间范围内;验证黑名单和定向设备表数据;检查参数传递(model、hw、beta、mac**注意**OTA查询已移除pawVerCode、pawVerName、pawUrl、pawMd5字段,确保查询逻辑正确
- **曲线查询错误** - **曲线查询错误**
- 现象:曲线查询返回错误或结果不符合预期。 - 现象:曲线查询返回错误或结果不符合预期。
- 排查:检查CurveRepository查询的Model和Target数据;确认EQ API可访问;验证Redis缓存键格式;检查分布式锁状态;确认fr数据分离存储正确。 - 排查:检查CurveRepository查询的Model和Target数据;确认EQ API可访问;验证Redis缓存键格式;检查分布式锁状态;确认fr数据分离存储正确。
@@ -1225,7 +1219,11 @@ MD_CACHE --> REDIS_CLIENT
- [internal/repository/share_code.go:20-58](file://internal/repository/share_code.go#L20-L58) - [internal/repository/share_code.go:20-58](file://internal/repository/share_code.go#L20-L58)
## 结论 ## 结论
Luxsin 的数据访问层经过重构后,采用了更加完善的缓存感知查询逻辑,实现了多级缓存策略和智能数据刷新机制。新增的设备持久化仓库、OTA仓库、曲线仓库和分享码仓库进一步完善了数据访问层的功能,支持设备信息上报、固件升级查询、频响曲线计算和分享码管理等核心业务场景。新增的CurveCache和ShareCodeCache提供了更高级的缓存策略,包括fr数据分离存储、分布式锁机制、Lua原子操作等,显著提升了系统的响应性能和数据一致性。通过集成 Redis 缓存层和异步持久化任务,系统在高并发场景下表现出色。建议后续继续优化缓存策略,增加缓存监控指标,完善缓存失效和更新机制,并持续改进监控与日志体系。 Luxsin 的数据访问层经过重构后,采用了更加完善的缓存感知查询逻辑,实现了多级缓存策略和智能数据刷新机制。新增的设备持久化仓库、OTA仓库、曲线仓库和分享码仓库进一步完善了数据访问层的功能,支持设备信息上报、固件升级查询、频响曲线计算和分享码管理等核心业务场景。新增的CurveCache和ShareCodeCache提供了更高级的缓存策略,包括fr数据分离存储、分布式锁机制、Lua原子操作等,显著提升了系统的响应性能和数据一致性。通过集成 Redis 缓存层和异步持久化任务,系统在高并发场景下表现出色。
**重要更新**:OTA仓库层已成功移除了pawVerCode、pawVerName、pawUrl、pawMd5等冗余字段,简化了查询逻辑和数据处理流程,提升了系统性能和维护性。OTA模型结构已精简,移除了不必要的字段,提高了数据传输效率。
建议后续继续优化缓存策略,增加缓存监控指标,完善缓存失效和更新机制,并持续改进监控与日志体系。
## 附录:扩展新 Repository 指南 ## 附录:扩展新 Repository 指南
- **设计原则** - **设计原则**
File diff suppressed because one or more lines are too long
+1 -13
View File
@@ -1,15 +1,3 @@
FROM golang:1.24-alpine AS builder
RUN apk add --no-cache git
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server
FROM alpine:3.20 FROM alpine:3.20
RUN apk add --no-cache ca-certificates tzdata \ RUN apk add --no-cache ca-certificates tzdata \
@@ -18,7 +6,7 @@ RUN apk add --no-cache ca-certificates tzdata \
WORKDIR /app WORKDIR /app
COPY --from=builder /server . COPY server .
EXPOSE 8080 EXPOSE 8080
+25
View File
@@ -0,0 +1,25 @@
FROM golang:1.24-alpine AS builder
RUN apk add --no-cache git
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server
FROM alpine:3.20
RUN apk add --no-cache ca-certificates tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
WORKDIR /app
COPY --from=builder /server .
EXPOSE 8080
CMD ["./server"]
+4 -1
View File
@@ -1,6 +1,6 @@
SWAG := $(shell go env GOPATH)/bin/swag SWAG := $(shell go env GOPATH)/bin/swag
.PHONY: run build test tidy swag .PHONY: run build build-linux test tidy swag
run: run:
go run ./cmd/server go run ./cmd/server
@@ -8,6 +8,9 @@ run:
build: swag build: swag
go build -o bin/server ./cmd/server go build -o bin/server ./cmd/server
build-linux: swag
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/server-linux ./cmd/server
test: test:
go test ./... go test ./...
+133
View File
@@ -0,0 +1,133 @@
#!/usr/bin/env bash
set -euo pipefail
REMOTE_DIR="/data/project/app-api"
show_help() {
cat <<'EOF'
用法: deploy.sh [选项] [服务器]
本地交叉编译后上传二进制到服务器。
选项:
-a 同时上传 Dockerfile 和 docker-compose.yml
-r 上传后 SSH 到服务器执行 docker compose up -d --build 重启容器
-s 跳过编译,直接使用已编译好的 bin/server-linux
-n 虚拟执行,不实际传输文件
-h, --help 显示此帮助信息
服务器:
api1 仅部署到 api1 (luxsin-api1)
api2 仅部署到 api2 (luxsin-api2)
(省略) 同时部署到 api1 和 api2
默认行为:
1. 本地执行 make build-linux 交叉编译
2. 上传编译好的二进制到服务器
示例:
deploy.sh 编译并上传二进制到 api1 和 api2
deploy.sh api1 编译并上传二进制到 api1
deploy.sh -s api1 跳过编译,直接上传已有二进制到 api1
deploy.sh -a api1 同时上传 Dockerfile + docker-compose.yml 到 api1
deploy.sh -r 编译、上传二进制并重启容器
deploy.sh -s -r api1 跳过编译,上传已有二进制并重启
deploy.sh -a -r api1 全量部署到 api1(含 Docker 文件 + 重启)
deploy.sh -n api1 虚拟执行,预览部署到 api1
EOF
}
remote_host_for() {
case "$1" in
api1) echo "luxsin-api1" ;;
api2) echo "luxsin-api2" ;;
*)
echo "未知服务器: $1(可选: api1, api2" >&2
exit 1
;;
esac
}
UPLOAD_ALL=false
RESTART=false
SKIP_BUILD=false
DRY_RUN=false
ARGS=()
for arg in "$@"; do
case "$arg" in
-a) UPLOAD_ALL=true ;;
-r) RESTART=true ;;
-s) SKIP_BUILD=true ;;
-n) DRY_RUN=true ;;
-h|--help)
show_help
exit 0
;;
*)
ARGS+=("$arg")
;;
esac
done
SERVERS=()
if [ ${#ARGS[@]} -gt 0 ] && { [ "${ARGS[0]}" = "api1" ] || [ "${ARGS[0]}" = "api2" ]; }; then
SERVERS=("${ARGS[0]}")
else
SERVERS=(api1 api2)
fi
if [ "$SKIP_BUILD" = true ]; then
echo "=== 跳过编译,使用已有二进制 ==="
if [ ! -f bin/server-linux ]; then
echo "错误: bin/server-linux 不存在,请先编译" >&2
exit 1
fi
echo " 文件: bin/server-linux ($(du -h bin/server-linux | cut -f1))"
else
echo "=== 本地编译 ==="
if [ "$DRY_RUN" = true ]; then
echo "(虚拟) make build-linux"
else
make build-linux
fi
fi
echo
rsync_opts=(-avz --progress)
if [ "$DRY_RUN" = true ]; then
rsync_opts+=(-n)
fi
for server in "${SERVERS[@]}"; do
remote_host="$(remote_host_for "$server")"
if [ "$DRY_RUN" = true ]; then
echo "=== 虚拟部署到 ${server} (${remote_host}) ==="
else
echo "=== 部署到 ${server} (${remote_host}) ==="
fi
echo " 上传二进制: bin/server-linux -> ${remote_host}:${REMOTE_DIR}/server"
rsync "${rsync_opts[@]}" bin/server-linux "${remote_host}:${REMOTE_DIR}/server"
if [ "$UPLOAD_ALL" = true ]; then
echo " 上传 Dockerfile -> ${remote_host}:${REMOTE_DIR}/Dockerfile"
rsync "${rsync_opts[@]}" Dockerfile "${remote_host}:${REMOTE_DIR}/Dockerfile"
echo " 上传 docker-compose.yml -> ${remote_host}:${REMOTE_DIR}/docker-compose.yml"
rsync "${rsync_opts[@]}" docker-compose.yml "${remote_host}:${REMOTE_DIR}/docker-compose.yml"
fi
if [ "$RESTART" = true ]; then
if [ "$DRY_RUN" = true ]; then
echo " (虚拟) SSH 重启容器: docker compose up -d --build"
else
echo " SSH 重启容器 ..."
ssh "$remote_host" "cd ${REMOTE_DIR} && docker compose up -d --build"
fi
fi
echo
done
echo "完成。"