51 KiB
资产服务(Asset Service)设计文档
📊 文档状态总结
✅ 已完成
- ✅ 数据库模型设计(
pkg/models/asset.go已实现) - ✅ 核心功能设计确认(Q1-Q17, Q23-Q25 已确认)
- ✅ 数据库表结构设计(assets、mint_orders、asset_likes 表结构已确定)
- ✅ 服务职责边界定义
- ✅ 配置设计(参考 socialService 的配置模式)
⚠️ 需要补充和确认
🔴 高优先级(阻塞开发)
-
User Service 接口补充
- ❌
UpdateCrystalBalanceRPC 接口(需要在proto/user.proto中添加) - ⚠️
UpdateAssetsCountRPC 接口(Repository 层已实现,需要添加 RPC 接口)
- ❌
-
Asset Service Proto 定义
- ❌ 需要创建
proto/asset.proto文件 - ❌ 定义资产服务的所有 RPC 接口
- ❌ 需要创建
-
Social Service 接口补充
- ❌ 资产点赞相关的 RPC 接口(需要在
proto/social.proto中添加)
- ❌ 资产点赞相关的 RPC 接口(需要在
🟡 中优先级(建议确认)
-
事件驱动机制 ✅ 已确认:不使用消息队列
- ✅ 不使用消息队列(RocketMQ/Kafka/RabbitMQ),直接通过 RPC 调用或数据库记录
- ⚠️ 事件格式规范(如需事件记录,可在数据库中记录)
- ⚠️ 事件重试机制(如需重试,可在应用层实现)
-
缓存策略 ✅ 已确认:不使用 Redis 缓存
- ✅ 不使用 Redis 缓存,直接查询数据库
- ✅ 所有数据查询都直接访问数据库
🟢 低优先级(可后续优化)
- 错误处理国际化
- ⚠️ 是否需要多语言支持
📝 待实现内容
1. 服务实现(未开始)
- 创建
services/assetService/目录结构 - 实现 Repository 层(asset_repository.go、mint_order_repository.go、asset_like_repository.go)
- 实现 Service 层(asset_service.go、mint_service.go)
- 实现 Provider 层(asset_provider.go)
- 实现 RPC Client(user_rpc_client.go)
2. Gateway 集成(未开始)
- 创建
gateway/controller/asset_controller.go - 创建
gateway/dto/asset_converter.go - 在
gateway/router/router.go中添加路由
3. 数据库迁移(未开始)
- 创建表结构迁移脚本
- 创建索引
4. 测试(未开始)
- 单元测试
- 集成测试
- HTTP 完整测试流程
📋 快速参考
数据库表设计(基于提供设计 + 服务交互字段)
assets 表
- 基础字段(来自提供设计):
id,owner_uid,star_id,name,cover_url,status,tx_hash,block_number,like_count - 新增字段(需求确认):
material_url(用户上传素材),description,rarity,tags,visibility(预留) - 新增字段(服务交互):
created_at,updated_at,minted_at,deleted_at,is_active
mint_orders 表
- 基础字段(来自提供设计):
order_id(UUID),user_id,asset_id,star_id,status,created_at - 新增字段(服务交互):
updated_at,minted_at,cost_crystal,error_message,retry_count
服务间交互字段映射
| 交互服务 | 使用的字段 | 用途 |
|---|---|---|
| User Service | mint_orders.cost_crystal |
扣除/退款水晶 |
| User Service | assets.owner_uid, assets.star_id |
更新资产数量 |
| Social Service | assets.like_count |
更新点赞数 |
| Gallery Service | - | 暂不考虑,后续再实现 |
| Task Service | assets.created_at, assets.minted_at |
事件发布 |
需要确认的关键问题
🔴 高优先级(必须确认):
- 铸造费用和支付方式(Q1)
- 区块链集成方式(Q11, Q23)
- User Service 接口可用性(Q18)
🟡 中优先级(建议确认): 4. 资产属性字段(Q13) 5. 订单表设计细节(Q14)
🟢 低优先级(可后续优化): 6. 其他功能细节(Q5-Q10, Q15-Q17, Q19-Q30)
一、服务概述
1.1 服务定位
Asset Service(资产服务) 是负责数字藏品(NFT)全生命周期管理的核心微服务,包括:
- 数字藏品的铸造(链下记录 + 链上确权)
- 资产查询与列表管理
- 资产详情展示
- 素材管理(平台素材库)
- 图片上传与审核
1.2 服务职责边界
Asset Service 负责:
- ✅ 资产的创建、查询、更新
- ✅ 铸造订单的管理
- ✅ 素材库管理
- ✅ 图片上传处理
- ✅ 资产上链状态跟踪
Asset Service 不负责:
- ❌ 用户余额管理(CoinBalance, CrystalBalance)- 由 User Service 管理
- ❌ 资产数量统计(AssetsCount)- 由 User Service 管理(通过 RPC 调用更新)
- ❌ 资产展示(展馆)- 由 Gallery Service 管理
- ❌ 资产点赞 - 由 Social Service 管理
二、核心功能设计
2.1 资产铸造流程
2.1.1 铸造流程概述
用户发起铸造请求
↓
1. 验证用户权限和余额
↓
2. 创建资产记录(链下)
↓
3. 创建铸造订单(异步)
↓
4. 调用区块链服务上链
↓
5. 更新资产状态和链上信息
↓
6. 更新用户资产数量(调用 User Service)
↓
7. 发布事件(asset.mint_complete)
2.1.2 ✅ 已确认
Q1: 铸造费用和支付方式 ✅
- ✅ 铸造需要消耗水晶(CrystalBalance)
- ✅ 费用后续同样会引入规则表进行定义,现在直接和 socialService 一致,统一定义在
config/asset_config.go文件中(CostCrystal) - ✅ 支付是在创建订单的时候扣除
- ✅ 上链失败会进行退款
Q2: 铸造材料来源 ✅
- ✅ 目前可以暂不考虑,随机生成一个图片的 URL 即可
- ✅ 后续再进行拓展
Q3: 铸造限制 ✅
- ✅ 次数限制同样和 Q1 一致,后续同样会引入规则表进行定义
- ✅ 现在直接和 socialService 一致,统一定义在
config/asset_config.go文件中(MaxMintCountPerDay,MaxMintCountPerUser)
Q4: 异步处理机制 ✅
- ✅ 上链为异步机制
- ✅ 但是目前不引入上链功能,所以只需要做简单的模拟
- ✅ 后续引入后再进行优化
2.2 资产查询功能
2.2.1 我的藏品列表
接口设计:
GET /api/v1/assets/me
Query Parameters:
- page: 页码(默认1)
- page_size: 每页数量(默认20,最大100)
- status: 状态筛选(all, pending, minted, failed)
- keyword: 关键词搜索(资产名称)
- sort: 排序方式(created_at_desc, created_at_asc, name_asc)
响应结构:
{
"code": 200,
"message": "ok",
"data": {
"items": [
{
"asset_id": 123,
"name": "藏品名称",
"cover_url": "https://...",
"status": "minted", // pending, minting, minted, failed
"token_id": "0x123...",
"tx_hash": "0xabc...",
"created_at": 1704067200000,
"minted_at": 1704067300000
}
],
"total": 100,
"page": 1,
"page_size": 20,
"has_more": true
}
}
2.2.2 资产详情
接口设计:
GET /api/v1/assets/{asset_id}
响应结构:
{
"code": 200,
"message": "ok",
"data": {
"asset_id": 123,
"name": "藏品名称",
"description": "藏品描述",
"cover_url": "https://...",
"owner": {
"user_id": 1,
"nickname": "张三"
},
"star_id": 1,
"status": "minted",
"token_id": "0x123...",
"tx_hash": "0xabc...",
"materials": [
{
"material_id": 1,
"type": "platform",
"url": "https://..."
}
],
"created_at": 1704067200000,
"minted_at": 1704067300000,
"like_count": 10,
"is_liked": false // 当前用户是否点赞
}
}
2.2.3 ✅ 已确认
Q5: 资产可见性 ✅
- ✅ 用户不能看到别人的资产
- ✅ 目前不需要考虑分享等功能
- ✅ 但是在表格设计的时候可以留一个权限控制的字段接口出来(
visibility字段)
Q6: 资产属性 ✅
- ✅ 名称(name)和封面图(cover_url)是目前设计的必须字段
- ✅ 同样可以预留描述(description)、稀有度(rarity)、标签(tags)的字段接口以便后续功能添加
2.3 素材管理功能
2.3.1 平台素材列表
接口设计:
GET /api/v1/materials/platform
Query Parameters:
- page: 页码
- page_size: 每页数量
- category: 分类筛选(可选)
响应结构:
{
"code": 200,
"message": "ok",
"data": {
"items": [
{
"material_id": 1,
"name": "素材名称",
"url": "https://...",
"category": "背景",
"star_id": 1
}
],
"total": 50,
"page": 1,
"page_size": 20
}
}
2.3.2 ✅ 已确认
Q7: 素材分类和管理 ✅
- ✅ 素材需要根据
star_id进行隔离
Q8: 用户上传素材 ✅
- ✅ 用户可以上传自己的素材
- ✅ 目前暂不需要审核功能
- ✅ 不需要
materials表,直接在assets表里面加入一个material_url字段代表素材的 URL 即可 - ✅ 后续会定期清理这个字段
2.4 图片上传功能
2.4.1 上传接口设计
接口设计:
POST /api/v1/assets/upload
Content-Type: multipart/form-data
Form Data:
- file: 图片文件
- type: 上传类型(cover, material)
响应结构:
{
"code": 200,
"message": "ok",
"data": {
"url": "https://minio.example.com/bucket/path/to/image.jpg",
"upload_id": "upload_123"
}
}
2.4.2 ✅ 已确认
Q9: 图片存储和审核 ✅
- ✅ 暂不考虑图片存储的细节问题,存一个 URL 即可
Q10: 上传任务管理 ✅
- ✅ 不需要上传任务表
- ✅ 直接阻塞上传,上传成功返回后才会允许前端用户进行下一步操作
2.5 上链状态查询
2.5.1 状态查询接口
接口设计:
GET /api/v1/assets/{asset_id}/status
响应结构:
{
"code": 200,
"message": "ok",
"data": {
"asset_id": 123,
"status": "minting", // pending, minting, minted, failed
"tx_hash": "0xabc...",
"token_id": "0x123...",
"block_number": 12345,
"minted_at": 1704067300000,
"error_message": "" // 如果失败,错误信息
}
}
2.5.2 ✅ 已确认
Q11: 区块链集成 ✅
- ✅ 区块链暂不考虑,后续才会引入相应的函数功能
- ✅ 目前只需要模拟已经上链成功结束即可
Q12: 上链信息存储 ✅
- ✅ 只需要存储
tx_hash和block_number即可 - ✅ 不需要
token_id
三、数据库设计
3.1 核心表结构
3.1.1 assets 表(资产表)
基于提供的数据库设计,完善后的表结构:
CREATE TABLE assets (
-- 主键和基础字段
id BIGSERIAL PRIMARY KEY, -- asset_id (Asset ID)
owner_uid BIGINT NOT NULL, -- 当前持有者 (Current Owner)
star_id BIGINT NOT NULL, -- 所属星球 (Belonging Planet)
name VARCHAR(100) NOT NULL, -- 藏品名称 (Collection Name)
cover_url VARCHAR(500) NOT NULL, -- 封面图URL (Cover Image URL)
-- 用户上传的素材URL(后续会定期清理)
material_url VARCHAR(500), -- 用户上传的素材URL(可选)
-- 预留字段(后续功能扩展)
description TEXT, -- 藏品描述(预留)
rarity INT, -- 稀有度(预留)
tags JSONB, -- 标签(预留,JSON数组)
-- 权限控制字段(预留)
visibility VARCHAR(20) DEFAULT 'private', -- 可见性:private, friends, public(预留)
-- 状态字段
status INT NOT NULL DEFAULT 0, -- 0:Pending, 1:Active (状态枚举)
-- 链上信息(目前模拟,后续引入区块链功能)
tx_hash VARCHAR(100), -- Web3:交易哈希
block_number BIGINT, -- 区块号
-- 社交相关(与 Social Service 交互)
like_count INT NOT NULL DEFAULT 0, -- 点赞数 (Like Count)
-- 时间戳字段(用于排序、查询、事件追踪)
created_at BIGINT NOT NULL, -- 创建时间(毫秒时间戳)
updated_at BIGINT NOT NULL, -- 更新时间(毫秒时间戳)
minted_at BIGINT, -- 上链成功时间(毫秒时间戳,用于 Task Service 事件)
-- 软删除(与现有服务保持一致)
deleted_at BIGINT, -- 软删除时间戳(NULL 表示未删除)
is_active BOOLEAN NOT NULL DEFAULT true, -- 是否激活(用于快速查询过滤)
-- 索引
INDEX idx_assets_owner_star (owner_uid, star_id),
INDEX idx_assets_status (status),
INDEX idx_assets_created_at (created_at DESC),
INDEX idx_assets_tx_hash (tx_hash),
INDEX idx_assets_star_active (star_id, is_active),
INDEX idx_assets_deleted_at (deleted_at)
);
完整字段列表(基于提供的设计 + 服务交互所需字段):
| 字段名 | 类型 | 约束 | 默认值 | 说明 | 来源 |
|---|---|---|---|---|---|
id |
BIGINT | PK, AUTO_INCREMENT | - | 资产ID | 提供设计 |
owner_uid |
BIGINT | NOT NULL, FK | - | 当前持有者 | 提供设计 |
star_id |
BIGINT | NOT NULL, FK | - | 所属星球 | 提供设计 |
name |
VARCHAR(100) | NOT NULL | - | 藏品名称 | 提供设计 |
cover_url |
VARCHAR(500) | NOT NULL | - | MinIO地址 | 提供设计 |
status |
INT | NOT NULL | 0 | 状态(0:Pending, 1:Active) | 提供设计 |
tx_hash |
VARCHAR(100) | NULL | NULL | Web3交易哈希 | 提供设计 |
token_id |
VARCHAR(100) | NULL | NULL | Web3链上ID | 提供设计 |
like_count |
INT | NOT NULL | 0 | 点赞数 | 提供设计 |
created_at |
BIGINT | NOT NULL | - | 创建时间(毫秒时间戳) | 新增 |
updated_at |
BIGINT | NOT NULL | - | 更新时间(毫秒时间戳) | 新增 |
minted_at |
BIGINT | NULL | NULL | 上链成功时间(毫秒时间戳) | 新增 |
deleted_at |
BIGINT | NULL | NULL | 软删除时间戳 | 新增 |
is_active |
BOOLEAN | NOT NULL | true | 是否激活 | 新增 |
字段说明:
| 字段 | 类型 | 说明 | 用途 |
|---|---|---|---|
id |
bigint | 资产ID(主键) | 唯一标识 |
owner_uid |
bigint | 当前持有者 | 资产归属,与 User Service 交互 |
star_id |
bigint | 所属星球 | 数据隔离,与现有服务保持一致 |
name |
varchar | 藏品名称 | 显示和搜索 |
cover_url |
varchar | 封面图URL | 图片展示 |
material_url |
varchar | 用户上传的素材URL | 用户自定义素材(后续会清理) |
status |
int | 状态(0:Pending, 1:Active) | 状态管理 |
tx_hash |
varchar | 交易哈希 | 链上查询(目前模拟) |
block_number |
bigint | 区块号 | 链上查询(目前模拟) |
like_count |
int | 点赞数 | 与 Social Service 交互 |
created_at |
bigint | 创建时间 | 排序、查询、Task Service 事件 |
updated_at |
bigint | 更新时间 | 追踪变更 |
minted_at |
bigint | 上链成功时间 | 事件发布、统计 |
deleted_at |
bigint | 软删除时间 | 数据恢复、审计 |
is_active |
boolean | 是否激活 | 快速查询过滤 |
description |
text | 藏品描述 | 🔵 预留字段 |
rarity |
int | 稀有度 | 🔵 预留字段 |
tags |
jsonb | 标签(JSON数组) | 🔵 预留字段 |
visibility |
varchar | 可见性(private/friends/public) | 🔵 预留字段 |
状态枚举值:
const (
AssetStatusPending = 0 // 待处理(创建中)
AssetStatusActive = 1 // 已激活(上链成功)
// 预留:AssetStatusMinting = 2 // 上链中
// 预留:AssetStatusFailed = 3 // 上链失败
)
索引设计说明:
| 索引名 | 字段 | 用途 |
|---|---|---|
idx_assets_owner_star |
(owner_uid, star_id) |
查询用户的资产列表 |
idx_assets_status |
(status) |
按状态筛选资产 |
idx_assets_created_at |
(created_at DESC) |
按创建时间排序 |
idx_assets_tx_hash |
(tx_hash) |
通过交易哈希查询 |
idx_assets_star_active |
(star_id, is_active) |
按明星和激活状态查询 |
idx_assets_deleted_at |
(deleted_at) |
软删除查询过滤 |
Q13: 资产表字段补充 ✅
- ✅
description(描述)字段:已添加为预留字段 - ✅
block_number(区块号)字段:已添加 - ✅
token_id(链上ID)字段:不需要,已移除 - ✅
contract_address(合约地址)字段:不需要 - ✅
chain_id(链ID)字段:不需要 - ✅
material_url(用户上传素材URL)字段:已添加,后续会定期清理 - ✅ 不需要合约地址和链ID,其他都需要(description, block_number等)
3.1.2 mint_orders 表(铸造订单表)
基于提供的数据库设计,完善后的表结构:
CREATE TABLE mint_orders (
-- 主键
order_id VARCHAR(100) PRIMARY KEY, -- 铸造订单号 (Mint Order Number)
-- 关联字段
user_id BIGINT NOT NULL, -- 用户ID
asset_id BIGINT, -- 关联资产(生成后回填) (Associated Asset)
star_id BIGINT NOT NULL, -- 明星ID(用于数据隔离)
-- 状态字段
status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING/PROCESSING/SUCCESS/FAILED
-- 费用相关(与 User Service 交互)
cost_crystal BIGINT DEFAULT 0, -- 消耗的水晶数量(用于记录和审计)
-- 错误处理
error_message TEXT, -- 错误信息(如果失败)
retry_count INT DEFAULT 0, -- 重试次数(用于上链失败重试)
-- 时间戳字段
created_at BIGINT NOT NULL, -- 创建时间(毫秒时间戳)
updated_at BIGINT NOT NULL, -- 更新时间(毫秒时间戳)
minted_at BIGINT, -- 上链成功时间(用于 Task Service 事件)
-- 外键约束
FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE SET NULL,
-- 索引
INDEX idx_mint_orders_user_star (user_id, star_id),
INDEX idx_mint_orders_asset (asset_id),
INDEX idx_mint_orders_status (status),
INDEX idx_mint_orders_created_at (created_at DESC)
);
字段说明:
| 字段 | 类型 | 说明 | 用途 |
|---|---|---|---|
order_id |
varchar | 铸造订单号(主键) | 唯一标识,使用 UUID 生成 |
user_id |
bigint | 用户ID | 与 User Service 交互 |
asset_id |
bigint | 关联资产ID | 关联 assets 表(创建资产后回填) |
star_id |
bigint | 明星ID | 数据隔离 |
status |
varchar | 订单状态 | PENDING/PROCESSING/SUCCESS/FAILED |
cost_crystal |
bigint | 消耗的水晶数量 | 记录费用,用于审计和退款 |
error_message |
text | 错误信息 | 失败原因记录 |
retry_count |
int | 重试次数 | 上链失败重试机制 |
created_at |
bigint | 创建时间 | 排序、查询 |
updated_at |
bigint | 更新时间 | 追踪变更 |
minted_at |
bigint | 上链成功时间 | Task Service 事件发布 |
状态枚举值:
const (
MintOrderStatusPending = "PENDING" // 待处理
MintOrderStatusProcessing = "PROCESSING" // 处理中(上链中,目前模拟)
MintOrderStatusSuccess = "SUCCESS" // 成功
MintOrderStatusFailed = "FAILED" // 失败
// 注意:不需要 CANCELLED 状态,不支持订单取消功能
)
字段说明:
| 字段 | 类型 | 说明 | 状态 |
|---|---|---|---|
order_id |
varchar | 铸造订单号(UUID) | ✅ 必需 |
user_id |
bigint | 用户ID | ✅ 必需 |
asset_id |
bigint | 关联资产ID | ✅ 必需 |
star_id |
bigint | 明星ID | ✅ 必需 |
status |
varchar | 订单状态 | ✅ 必需 |
cost_crystal |
bigint | 消耗的水晶数量 | ✅ 必需 |
error_message |
text | 错误信息 | ✅ 必需 |
retry_count |
int | 重试次数 | ✅ 必需 |
created_at |
bigint | 创建时间 | ✅ 必需 |
updated_at |
bigint | 更新时间 | ✅ 必需 |
minted_at |
bigint | 上链成功时间 | ✅ 必需 |
3.2 与现有服务交互所需的额外字段
3.2.1 与 User Service 交互
需要添加的字段:
-
assets.created_at/mint_orders.created_at- 用途:记录创建时间,用于:
- 资产列表排序(按创建时间)
- Task Service 事件发布(
asset.mint事件需要时间戳) - 统计和报表(每日/每月新增资产数)
- 用途:记录创建时间,用于:
-
assets.minted_at/mint_orders.minted_at- 用途:记录上链成功时间,用于:
- Task Service 事件发布(
asset.mint_complete事件) - 统计上链成功率
- 计算上链耗时
- Task Service 事件发布(
- 用途:记录上链成功时间,用于:
-
mint_orders.cost_crystal- 用途:记录消耗的水晶数量,用于:
- 调用 User Service 扣除余额时的参数
- 上链失败时的退款计算
- 费用审计和统计
- 用途:记录消耗的水晶数量,用于:
-
assets.updated_at/mint_orders.updated_at- 用途:追踪数据变更,用于:
- 数据同步和缓存更新
- 审计日志
- 用途:追踪数据变更,用于:
3.2.2 与 Social Service 交互
已包含的字段:
assets.like_count- 用途:存储点赞数,避免每次查询都 JOIN
asset_likes表 - 更新方式:Social Service 点赞/取消点赞时,通过 RPC 调用更新
- 用途:存储点赞数,避免每次查询都 JOIN
✅ 已确认:
- ✅ 暂不考虑 Gallery Service,不需要
is_exhibited字段
3.2.3 与 Gallery Service 交互(暂不考虑)
✅ 已确认:
- ✅ 目前不考虑 Gallery Service 的实现
- ✅ 后续引入 Gallery Service 时,再添加相应的字段和接口
- ✅ 可能的字段:
assets.is_exhibited或通过关联表实现
3.2.4 与 Task Service 交互
需要添加的字段:
-
assets.created_at- 用途:发布
asset.mint事件时的时间戳
- 用途:发布
-
assets.minted_at- 用途:发布
asset.mint_complete事件时的时间戳
- 用途:发布
事件发布格式:
{
"event_type": "asset.mint_complete",
"user_id": 1,
"star_id": 1,
"asset_id": 123,
"minted_at": 1704067300000,
"timestamp": 1704067300000
}
3.2.5 数据隔离和软删除
需要添加的字段:
-
assets.deleted_at/mint_orders.deleted_at- 类型:BIGINT NULL
- 用途:软删除,与现有服务(User Service)保持一致
- 查询过滤:
WHERE deleted_at IS NULL
-
assets.is_active- 类型:BOOLEAN DEFAULT true
- 用途:快速查询过滤,避免每次都检查
deleted_at - 索引:
(star_id, is_active)复合索引
3.2.6 字段添加总结
assets 表需要添加的字段:
| 字段名 | 类型 | 默认值 | 说明 | 交互服务 |
|---|---|---|---|---|
created_at |
BIGINT | NOT NULL | 创建时间(毫秒时间戳) | Task Service |
updated_at |
BIGINT | NOT NULL | 更新时间(毫秒时间戳) | 通用 |
minted_at |
BIGINT | NULL | 上链成功时间(毫秒时间戳) | Task Service |
deleted_at |
BIGINT | NULL | 软删除时间戳 | 通用 |
is_active |
BOOLEAN | true | 是否激活 | 通用 |
mint_orders 表需要添加的字段:
| 字段名 | 类型 | 默认值 | 说明 | 交互服务 |
|---|---|---|---|---|
updated_at |
BIGINT | NOT NULL | 更新时间(毫秒时间戳) | 通用 |
minted_at |
BIGINT | NULL | 上链成功时间(毫秒时间戳) | Task Service |
cost_crystal |
BIGINT | 0 | 消耗的水晶数量 | User Service |
error_message |
TEXT | NULL | 错误信息 | 错误处理 |
retry_count |
INT | 0 | 重试次数 | 错误处理 |
✅ 已确认:
- ✅ 不需要
materials表:用户上传的素材直接存储在assets.material_url字段中 - ✅ 不需要
asset_materials表:资产和素材的关联关系不需要单独维护 - ✅ 不需要
upload_tasks表:上传采用阻塞式,上传成功返回后才会允许前端用户进行下一步操作 - ✅ 素材隔离:根据
star_id进行隔离(在assets表中已有star_id字段)
3.1.3 asset_likes 表(点赞记录表)
用于存储用户对资产的点赞记录,支持高并发场景:
CREATE TABLE asset_likes (
id BIGSERIAL PRIMARY KEY,
asset_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
star_id BIGINT NOT NULL, -- 用于数据隔离和查询优化
created_at BIGINT NOT NULL,
-- 唯一索引:防止重复点赞(数据库层面保护)
UNIQUE KEY uk_asset_likes_user_asset (asset_id, user_id),
-- 索引:用于查询用户点赞列表
INDEX idx_asset_likes_user_star (user_id, star_id, created_at DESC),
-- 索引:用于查询资产点赞用户列表(可选功能)
INDEX idx_asset_likes_asset (asset_id, created_at DESC),
-- 外键约束
FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE CASCADE
);
字段说明:
| 字段 | 类型 | 说明 | 用途 |
|---|---|---|---|
id |
bigint | 主键 | 唯一标识 |
asset_id |
bigint | 资产ID | 关联 assets 表 |
user_id |
bigint | 用户ID | 点赞用户 |
star_id |
bigint | 明星ID | 数据隔离,查询优化 |
created_at |
bigint | 创建时间 | 排序、统计 |
设计要点:
- ✅ 唯一索引:
uk_asset_likes_user_asset防止重复点赞 - ✅ 复合索引:
idx_asset_likes_user_star支持查询用户点赞列表 - ✅ 外键约束:资产删除时自动删除点赞记录
- ✅ 第一阶段设计:直接数据库查询,不使用 Redis 缓存(后续可根据性能需求再引入)
详细设计文档: 资产点赞功能高性能设计.md
四、服务间交互设计
4.1 与 User Service 的交互
4.1.1 需要调用的接口
验证用户和粉丝档案:
RPC: ValidateUser(user_id) -> bool
RPC: ValidateFanProfile(user_id, star_id) -> bool
- 使用场景:创建铸造订单前验证用户有效性
- 使用字段:
mint_orders.user_id,mint_orders.star_id
扣除/增加余额:
RPC: UpdateCrystalBalance(user_id, star_id, delta) -> new_balance
RPC: UpdateCoinBalance(user_id, star_id, delta) -> new_balance
- 使用场景:
- 创建铸造订单时扣除水晶(
mint_orders.cost_crystal) - 上链失败时退款
- 创建铸造订单时扣除水晶(
- 使用字段:
mint_orders.cost_crystal,mint_orders.user_id,mint_orders.star_id
更新资产数量:
RPC: UpdateAssetsCount(user_id, star_id, delta) -> new_count
- 使用场景:资产上链成功后,更新用户的资产数量
- 使用字段:
assets.owner_uid,assets.star_id - 触发时机:
assets.status从0(Pending) 变为1(Active) 时
4.1.2 需要提供的接口
查询用户信息(用于资产详情展示):
RPC: GetUserInfo(user_id) -> UserInfo
- 使用场景:资产详情中显示持有者信息
- 使用字段:
assets.owner_uid
需要确认的问题 ⚠️
Q18: User Service 接口
- ✅
ValidateUser(user_id) -> bool- 已实现(通过GetUserRPC 接口实现,Social Service 中已有使用) - ✅
ValidateFanProfile(user_id, star_id) -> bool- 已实现(通过GetFanProfileRPC 接口实现,Social Service 中已有使用) - ❌
UpdateCrystalBalance(user_id, star_id, delta) -> new_balance- 未实现,需要在 User Service 中添加 RPC 接口 - ⚠️
UpdateAssetsCount(user_id, star_id, delta) -> new_count- Repository 层已实现(IncrementAssetsCount/DecrementAssetsCount),但缺少 RPC 接口,需要在 User Service 中添加
补充说明:
ValidateUser和ValidateFanProfile可以通过现有的GetUser和GetFanProfile接口实现,返回错误即表示不存在UpdateCrystalBalance需要新增 RPC 接口,用于扣除/增加水晶余额UpdateAssetsCount需要在 User Service 的 Proto 中新增 RPC 接口,调用现有的 Repository 方法
Q19: 接口提供
- ✅ Asset Service 需要提供 RPC 接口给其他服务
- ✅ 需要调用的服务:
- Social Service:需要
GetAsset(asset_id)接口用于验证资产是否存在(点赞功能) - Gallery Service(后续):需要
ValidateAsset和GetAsset接口 - Task Service(后续):可能需要查询资产信息用于事件处理
- Social Service:需要
4.2 与 Social Service 的交互
4.2.1 点赞功能交互
Social Service 需要提供的接口:
更新点赞数:
RPC: UpdateAssetLikeCount(asset_id, delta) -> new_count
- 使用场景:用户点赞/取消点赞时,更新
assets.like_count - 使用字段:
assets.like_count - delta 值:+1(点赞)或 -1(取消点赞)
查询用户是否点赞:
RPC: CheckAssetLike(user_id, star_id, asset_id) -> bool
- 使用场景:资产详情中显示
is_liked状态 - 使用字段:
assets.id
Asset Service 需要提供的接口:
获取资产信息:
RPC: GetAsset(asset_id) -> AssetInfo
- 使用场景:Social Service 点赞时验证资产是否存在
- 使用字段:
assets.id,assets.status,assets.is_active
✅ 简化设计方案(第一阶段,直接数据库交互):
核心设计要点:
-
数据库直接交互
- 点赞操作直接写入数据库
- 使用数据库原子更新保证一致性
- 使用唯一索引防止重复点赞
-
原子操作
- 使用
UPDATE assets SET like_count = like_count + 1原子更新 - 使用数据库唯一索引
uk_asset_likes_user_asset防止重复
- 使用
-
防重复点赞
- 数据库唯一索引
uk_asset_likes_user_asset保护 - 应用层先查询再插入(双重保护)
- 数据库唯一索引
-
性能优化
- 数据库索引优化(
uk_asset_likes_user_asset,idx_asset_likes_user_star) - 原子更新减少锁竞争
- 不使用 Redis 缓存,直接查询数据库(后续可根据性能需求再引入)
- 数据库索引优化(
实现方式:
// 点赞操作(直接数据库)
1. 检查是否已点赞:SELECT COUNT(*) FROM asset_likes WHERE asset_id = ? AND user_id = ?
2. 如果未点赞:
- INSERT INTO asset_likes (asset_id, user_id, star_id, created_at)
- UPDATE assets SET like_count = like_count + 1 WHERE id = ?
3. 返回成功
后续优化(第二阶段,暂不实现):
- 如需提升性能,可后续引入 Redis 缓存
- 可考虑异步写入数据库
- 详细设计参考:资产点赞功能高性能设计.md
需要确认的问题 ⚠️
Q20: 点赞功能实现
- ✅ 资产点赞功能在 Social Service 中实现(参考:资产点赞功能高性能设计.md)
- ✅ Asset Service 不需要提供资产列表,Social Service 直接查询 assets 表
- ✅ 资产详情中的 like_count 和 is_liked 获取方式:
- 当前实现:直接查询数据库(
assets.like_count和asset_likes表) - 后续优化:如需提升性能,可后续引入 Redis 缓存(暂不实现)
- 当前实现:直接查询数据库(
- ⚠️ 需要补充:Social Service 的 Proto 中需要添加资产点赞相关的 RPC 接口定义(
LikeAsset,UnlikeAsset,CheckAssetLike等)
4.3 与 Gallery Service 的交互
4.3.1 资产验证
Asset Service 需要提供的接口:
验证资产是否存在:
RPC: ValidateAsset(asset_id, user_id, star_id) -> bool
- 使用场景:Gallery Service 放置资产前验证资产是否存在且属于当前用户
- 使用字段:
assets.id,assets.owner_uid,assets.star_id,assets.status,assets.is_active
获取资产信息:
RPC: GetAsset(asset_id) -> AssetInfo
- 使用场景:Gallery Service 获取资产信息用于展示
- 使用字段:
assets.*
4.3.2 展馆状态同步
Gallery Service 需要提供的接口:
更新资产展馆状态:
RPC: UpdateAssetExhibitionStatus(asset_id, is_exhibited) -> void
- 使用场景:资产放置/下架时,更新
assets.is_exhibited - 使用字段:
assets.is_exhibited - 触发时机:
- 放置资产:
is_exhibited = true - 下架资产:
is_exhibited = false
- 放置资产:
需要确认的问题 ⚠️
Q21: 展馆集成
- Gallery Service 是否需要验证资产是否存在?
- Asset Service 是否需要提供资产列表接口给 Gallery Service?
- 资产下架时,是否需要通知 Gallery Service?
- 是否需要
assets.is_exhibited字段,还是通过关联表查询?
4.4 与 Task Service 的交互
4.4.1 事件发布 ✅ 已确认:不使用消息队列
实现方式:
- ✅ 不使用消息队列(RocketMQ/Kafka/RabbitMQ)
- ✅ 如需事件通知,直接通过 RPC 调用 Task Service
- ✅ 如需事件记录,可在数据库中创建事件表进行记录
事件类型(如需实现):
-
asset.mint- 资产创建事件- 触发时机:创建资产记录时(
assets.status = 0) - 使用字段:
assets.created_at,assets.owner_uid,assets.star_id,assets.id - 实现方式:直接 RPC 调用 Task Service 或数据库记录
- 触发时机:创建资产记录时(
-
asset.mint_complete- 资产上链成功事件- 触发时机:资产上链成功,
assets.status从0变为1时 - 使用字段:
assets.minted_at,assets.owner_uid,assets.star_id,assets.id - 实现方式:直接 RPC 调用 Task Service 或数据库记录
- 触发时机:资产上链成功,
-
asset.mint_failed- 资产上链失败事件(可选)- 触发时机:资产上链失败时
- 实现方式:直接 RPC 调用 Task Service 或数据库记录
✅ 已确认:
- ✅ 不使用消息队列,直接通过 RPC 调用或数据库记录
- ⚠️ 事件格式是否需要统一规范?待确认(如需事件记录,可在数据库中创建事件表)
- ⚠️ 是否需要事件重试机制?待确认(如需重试,可在应用层实现)
- ⚠️ 是否需要
asset.mint_failed事件(上链失败时)?待确认(如需记录,可在数据库中记录)
五、配置设计
5.1 配置结构
参考 socialService 的配置设计,在 assetService/config/asset_config.go 中定义配置:
package config
// AssetConfig 资产服务配置
type AssetConfig struct {
// MintConfig 铸造相关配置
MintConfig MintConfig
// RetryConfig 重试相关配置
RetryConfig RetryConfig
}
// MintConfig 铸造配置
type MintConfig struct {
// CostCrystal 铸造费用(水晶数量)
// 后续会引入规则表进行定义,现在统一定义在config文件中
CostCrystal int64
// MaxMintCountPerDay 每日最大铸造次数
// 后续会引入规则表进行定义,现在统一定义在config文件中
MaxMintCountPerDay int
// MaxMintCountPerUser 用户最大铸造次数(总次数)
// 后续会引入规则表进行定义,现在统一定义在config文件中
MaxMintCountPerUser int
}
// RetryConfig 重试配置
type RetryConfig struct {
// MaxRetryCount 上链失败最大重试次数
MaxRetryCount int
// RetryIntervalSeconds 重试间隔(秒)
RetryIntervalSeconds int
}
// GlobalAssetConfig 全局资产配置实例
var GlobalAssetConfig = &AssetConfig{
MintConfig: MintConfig{
CostCrystal: 100, // 默认100水晶
MaxMintCountPerDay: 10, // 默认每日10次
MaxMintCountPerUser: 100, // 默认总次数100次
},
RetryConfig: RetryConfig{
MaxRetryCount: 3, // 默认重试3次
RetryIntervalSeconds: 5, // 默认间隔5秒
},
}
5.2 配置使用场景
5.2.1 铸造费用(CostCrystal)
使用场景:
- 创建铸造订单时,从用户账户扣除
CostCrystal数量的水晶 - 上链失败时,退还
CostCrystal数量的水晶
实现位置:
service/mint_service.go-CreateMintOrder方法
5.2.2 次数限制(MaxMintCountPerDay / MaxMintCountPerUser)
使用场景:
- 创建铸造订单前,检查用户是否超过每日/总次数限制
实现位置:
service/mint_service.go-CreateMintOrder方法- 需要查询
mint_orders表统计用户今日/总铸造次数
5.2.3 重试配置(MaxRetryCount / RetryIntervalSeconds)
使用场景:
- 上链失败时,根据
MaxRetryCount决定是否重试 - 重试间隔由
RetryIntervalSeconds控制
实现位置:
service/mint_service.go- 上链失败处理逻辑(目前模拟)
5.3 配置更新方法(预留)
// UpdateMintConfig 更新铸造配置
// 注意:后续可以从规则表或配置中心读取配置并调用此方法更新
func (c *AssetConfig) UpdateMintConfig(costCrystal int64, maxPerDay, maxPerUser int) {
c.MintConfig.CostCrystal = costCrystal
c.MintConfig.MaxMintCountPerDay = maxPerDay
c.MintConfig.MaxMintCountPerUser = maxPerUser
}
// UpdateRetryConfig 更新重试配置
func (c *AssetConfig) UpdateRetryConfig(maxRetryCount, retryIntervalSeconds int) {
c.RetryConfig.MaxRetryCount = maxRetryCount
c.RetryConfig.RetryIntervalSeconds = retryIntervalSeconds
}
✅ 已确认:
- ✅ 铸造费用:配置在
config/asset_config.go中,创建订单时扣除,上链失败退款 - ✅ 次数限制:配置在
config/asset_config.go中,后续会引入规则表 - ✅ 重试次数:配置在
config/asset_config.go中,默认3次
六、技术架构设计
5.1 服务结构
assetService/
├── main.go # 服务入口
├── config/ # 配置管理
│ └── asset_config.go
├── repository/ # 数据访问层
│ ├── asset_repository.go
│ ├── mint_order_repository.go
│ └── asset_like_repository.go # 点赞记录(第一阶段:直接数据库)
├── service/ # 业务逻辑层
│ ├── asset_service.go
│ └── mint_service.go
├── provider/ # RPC 提供者
│ └── asset_provider.go
├── client/ # RPC 客户端(调用其他服务)
│ └── user_rpc_client.go
├── proto/ # Proto 定义(可选,如果单独定义)
└── start.sh # 启动脚本
5.2 外部依赖
6.2.1 区块链服务
✅ 已确认:
- ✅ 区块链暂不考虑,后续才会引入相应的功能
- ✅ 目前只需要模拟已经上链成功结束即可
- ✅ 上链为异步机制,但目前不引入上链功能,只做简单模拟
实现方式:
- 创建资产时,随机生成
tx_hash和block_number - 模拟异步上链:延迟几秒后更新
assets.status = 1(Active) - 后续引入区块链功能后再进行优化
6.2.2 对象存储服务
✅ 已确认:
- ✅ 暂不考虑图片存储的细节问题,存一个URL即可
- ✅ 封面图URL直接存储在
assets.cover_url字段中 - ✅ 用户上传的素材URL存储在
assets.material_url字段中(后续会定期清理)
实现方式:
- 前端上传图片后,返回图片URL
- 后端直接存储URL,不进行图片处理
七、API 接口设计
7.1 接口列表
| 功能 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 创建铸造订单 | POST | /api/v1/assets/mints |
创建资产并发起铸造(包含上传封面图) |
| 获取我的藏品列表 | GET | /api/v1/assets/me |
获取当前用户的藏品列表 |
| 获取资产详情 | GET | /api/v1/assets/{asset_id} |
获取资产详细信息(仅限自己的资产) |
| 查询上链状态 | GET | /api/v1/assets/{asset_id}/status |
查询资产上链状态(仅限自己的资产) |
✅ 已确认:
- ✅ 不需要单独的上传接口:上传采用阻塞式,在创建铸造订单时一起处理
- ✅ 不需要素材管理接口:用户上传的素材直接存储在
assets.material_url字段中 - ✅ 不需要订单取消接口:不支持订单取消功能
- ✅ 用户不能看到别人的资产:所有查询接口都只返回当前用户的资产
6.2 需要确认的问题 ⚠️
Q26: API 路径规范
- ✅ API 路径前缀使用
/api/v1/assets(与其他服务保持一致) - ✅ 需要版本控制(v1)
Q27: 权限控制
- ✅ 所有接口都需要登录(通过 Gateway 的 auth middleware)
- ✅ 资产查询接口需要验证资产所有权(只能查询自己的资产)
- ✅ 创建铸造订单接口需要验证用户权限和余额
七、数据隔离设计
7.1 隔离方案
所有表都包含 star_id 字段,实现数据隔离:
-- 所有查询都基于 user_id + star_id
SELECT * FROM assets
WHERE user_id = ? AND star_id = ?;
7.2 需要确认的问题 ⚠️
Q28: 跨明星资产
- ✅ 资产不能跨明星使用(通过
star_id字段隔离) - ✅ 用户切换明星身份后,只能看到当前明星下的资产(通过
star_id过滤)
八、性能优化设计
8.1 缓存策略
需要确认的问题 ⚠️
Q29: 缓存需求 ✅ 已确认:不使用 Redis 缓存
- ✅ 不使用 Redis 缓存,所有数据查询都直接访问数据库
- ✅ 所有接口都直接查询数据库,保证数据实时性
- ⚠️ 后续优化:如需提升性能,可后续引入 Redis 缓存(暂不实现)
8.2 分页和索引
- ✅ 所有列表接口都支持分页(默认 page=1, page_size=20,最大 page_size=100)
- ✅ 关键字段建立索引(user_id, star_id, status, created_at)
九、错误处理设计
9.1 错误码定义
需要确认的问题 ⚠️
Q30: 错误处理
- ✅ 使用统一的错误码体系(参考
pkg/errors/errors.go) - ⚠️ 待确认:错误信息是否需要国际化?(建议第一阶段仅支持中文,后续再扩展)
十、数据库设计总结
10.1 完整表结构(基于提供设计 + 服务交互字段)
assets 表(最终设计)
CREATE TABLE assets (
-- 主键和基础字段(来自提供设计)
id BIGSERIAL PRIMARY KEY,
owner_uid BIGINT NOT NULL,
star_id BIGINT NOT NULL,
name VARCHAR(100) NOT NULL,
cover_url VARCHAR(500) NOT NULL,
material_url VARCHAR(500), -- 用户上传的素材URL(后续会定期清理)
description TEXT, -- 藏品描述(预留)
rarity INT, -- 稀有度(预留)
tags JSONB, -- 标签(预留,JSON数组)
visibility VARCHAR(20) DEFAULT 'private', -- 可见性(预留)
status INT NOT NULL DEFAULT 0, -- 0:Pending, 1:Active
tx_hash VARCHAR(100), -- 交易哈希(目前模拟)
block_number BIGINT, -- 区块号(目前模拟)
like_count INT NOT NULL DEFAULT 0,
-- 服务交互所需字段(新增)
created_at BIGINT NOT NULL, -- Task Service 事件
updated_at BIGINT NOT NULL, -- 通用
minted_at BIGINT, -- Task Service 事件
deleted_at BIGINT, -- 软删除
is_active BOOLEAN NOT NULL DEFAULT true, -- 快速查询
-- 索引
INDEX idx_assets_owner_star (owner_uid, star_id),
INDEX idx_assets_status (status),
INDEX idx_assets_created_at (created_at DESC),
INDEX idx_assets_tx_hash (tx_hash),
INDEX idx_assets_star_active (star_id, is_active),
INDEX idx_assets_deleted_at (deleted_at)
);
mint_orders 表(最终设计)
CREATE TABLE mint_orders (
-- 主键和基础字段(来自提供设计)
order_id VARCHAR(100) PRIMARY KEY,
user_id BIGINT NOT NULL,
asset_id BIGINT,
star_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
created_at BIGINT NOT NULL,
-- 服务交互所需字段(新增)
updated_at BIGINT NOT NULL, -- 通用
minted_at BIGINT, -- Task Service 事件
cost_crystal BIGINT DEFAULT 0, -- User Service 交互
error_message TEXT, -- 错误处理
retry_count INT DEFAULT 0, -- 重试机制
-- 外键和索引
FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE SET NULL,
INDEX idx_mint_orders_user_star (user_id, star_id),
INDEX idx_mint_orders_asset (asset_id),
INDEX idx_mint_orders_status (status),
INDEX idx_mint_orders_created_at (created_at DESC)
);
10.2 字段分类总结
来自提供设计的字段:
- ✅
assets.id,assets.owner_uid,assets.star_id,assets.name,assets.cover_url - ✅
assets.status,assets.tx_hash,assets.like_count - ✅
mint_orders.order_id,mint_orders.user_id,mint_orders.asset_id,mint_orders.status,mint_orders.created_at
根据需求新增的字段:
- ✅
assets.material_url- 用户上传的素材URL(后续会定期清理) - ✅
assets.description,assets.rarity,assets.tags,assets.visibility- 预留字段 - ✅
assets.block_number- 区块号(目前模拟) - ✅
assets.created_at,assets.updated_at,assets.minted_at- 时间戳(Task Service 事件) - ✅
assets.deleted_at,assets.is_active- 软删除(与现有服务一致) - ✅
mint_orders.updated_at,mint_orders.minted_at- 时间戳 - ✅
mint_orders.cost_crystal- 费用记录(User Service 交互) - ✅
mint_orders.error_message,mint_orders.retry_count- 错误处理
已移除的字段:
- ❌
assets.token_id- 不需要(根据Q12确认) - ❌
assets.is_exhibited- 暂不需要(Gallery Service集成后续再考虑)
十一、待确认问题汇总
✅ 已确认的问题
Q1-Q4: 铸造流程相关 ✅
- ✅ Q1: 铸造费用在config文件中定义,创建订单时扣除,上链失败退款
- ✅ Q2: 暂不考虑,随机生成图片URL即可
- ✅ Q3: 次数限制在config文件中定义
- ✅ Q4: 上链为异步机制,但目前只做简单模拟
Q5-Q6: 资产可见性和属性 ✅
- ✅ Q5: 用户不能看到别人的资产,预留权限控制字段
- ✅ Q6: 名称和封面图必须,预留描述、稀有度、标签字段
Q7-Q10: 素材和上传 ✅
- ✅ Q7: 素材需要根据star_id隔离
- ✅ Q8: 用户可以上传素材,不需要审核,不需要materials表,在assets表加material_url字段
- ✅ Q9: 暂不考虑图片存储细节,存URL即可
- ✅ Q10: 不需要上传任务表,直接阻塞上传
Q11-Q12: 区块链集成 ✅
- ✅ Q11: 区块链暂不考虑,模拟上链成功
- ✅ Q12: 只需要tx_hash和block_number,不需要token_id
Q13-Q14: 数据库表字段 ✅
- ✅ Q13: 不需要合约地址和链ID,其他都需要(description, block_number等)
- ✅ Q14: UUID生成,不需要支付状态,不需要取消功能,重试次数在config中
Q15-Q17: 其他表设计 ✅
- ✅ Q15-Q17: 不需要materials表、asset_materials表、upload_tasks表
Q23-Q25: 技术选型 ✅
- ✅ Q23: 区块链暂不考虑,后续引入
- ✅ Q24: 暂不考虑图片存储细节
- ✅ Q25: 暂不考虑AI生成功能
⚠️ 仍需确认的问题
Q18: User Service 接口可用性 ⚠️ 部分已实现,部分待补充
- ✅
ValidateUser- 已实现(通过GetUser接口) - ✅
ValidateFanProfile- 已实现(通过GetFanProfile接口) - ❌
UpdateCrystalBalance- 需要在 User Service 中新增 RPC 接口 - ⚠️
UpdateAssetsCount- Repository 层已实现,需要在 User Service 中新增 RPC 接口
Q19-Q22: 服务间交互细节
- ✅ Q19: Asset Service 需要提供 RPC 接口给 Social Service 和 Gallery Service
- ✅ Q20: 资产点赞功能在 Social Service 中实现,直接查询数据库(不使用 Redis)
- ✅ Q21: Gallery Service 集成暂不考虑,后续再实现
- ✅ Q22: 事件驱动已确认不使用消息队列,直接通过 RPC 调用或数据库记录
Q26-Q30: 其他技术细节
- ✅ Q26-Q27: API 路径规范和权限控制已确认
- ✅ Q28: 跨明星资产隔离已确认
- ✅ Q29: 缓存需求已确认(不使用 Redis 缓存,直接查询数据库)
- ⚠️ Q30: 错误处理国际化待确认
📝 需要补充的内容
1. Proto 接口定义
- Asset Service Proto:需要创建
proto/asset.proto文件,定义资产服务的 RPC 接口 - User Service Proto 补充:需要在
proto/user.proto中添加:UpdateCrystalBalanceRPC 接口UpdateAssetsCountRPC 接口
- Social Service Proto 补充:需要在
proto/social.proto中添加资产点赞相关的 RPC 接口
2. 服务实现状态
- Asset Service 服务目录:需要创建
services/assetService/目录结构 - 配置管理:需要创建
services/assetService/config/asset_config.go(参考socialService/config/social_config.go) - Repository 层:需要实现
asset_repository.go、mint_order_repository.go、asset_like_repository.go - Service 层:需要实现
asset_service.go、mint_service.go - Provider 层:需要实现
asset_provider.go - RPC Client:需要实现
user_rpc_client.go(调用 User Service)
3. Gateway 集成
- 路由配置:需要在
gateway/router/router.go中添加资产服务的路由 - Controller:需要创建
gateway/controller/asset_controller.go - DTO 转换:需要创建
gateway/dto/asset_converter.go
4. 数据库迁移
- 表结构创建:需要创建
assets、mint_orders、asset_likes表的迁移脚本 - 索引创建:确保所有索引都已创建
5. 测试
- 单元测试:Repository 层、Service 层的单元测试
- 集成测试:服务间交互的集成测试
- HTTP 测试:Gateway 接口的完整测试流程(参考
用户服务HTTP完整测试流程.md)
十一、下一步行动
阶段 1: 需求确认(当前阶段)✅ 进行中
- 与产品/业务确认上述 30 个问题(大部分已确认)
- 确定核心功能范围(已确定)
- 确定技术选型(已确定)
- 待补充:确认 User Service 接口补充需求
- 待补充:确认 Social Service 资产点赞接口定义
阶段 2: 详细设计 ⚠️ 部分完成
- 完善数据库表结构(已完成,见
pkg/models/asset.go) - 待补充:设计 Asset Service Proto 接口定义
- 待补充:设计 User Service Proto 接口补充(
UpdateCrystalBalance、UpdateAssetsCount) - 待补充:设计 Social Service Proto 接口补充(资产点赞相关)
- 设计服务间交互协议(已设计)
- 设计错误处理机制(参考现有服务)
阶段 3: 开发实现 ❌ 未开始
- Repository 层实现
- Service 层实现
- Provider 层实现
- Gateway 集成
- 单元测试
阶段 4: 测试和上线 ❌ 未开始
- 集成测试
- 性能测试
- 上线部署