You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

7.3 KiB

变更日志: 积分过期机制与动态定价集成

日期: 2026-01-27
版本: v1.3.0
类型: 功能增强


概述

本次更新为 Credit Service 添加了两个重要功能:

  1. 积分过期机制: 自动处理赠送积分的过期逻辑
  2. 动态定价集成: 与 AI Service 集成,优先使用 ai_models 表的定价

变更内容

新增功能

1. 积分过期机制

  • 添加查询即将过期积分的方法
  • 实现自动过期处理逻辑
  • 创建 Celery 定时任务(每天凌晨 3 点执行)
  • 添加过期通知任务(每天上午 10 点执行)
  • 新增 API 端点 GET /api/v1/credits/expiring

2. 动态定价集成

  • 集成 AI Model Repository
  • 实现 Redis 缓存机制(TTL 1 小时)
  • 添加降级策略(AI Service 不可用时使用 credit_pricing 表)
  • 重构 calculate_credits() 方法

Breaking Changes

无破坏性变更,所有改动向后兼容。

技术细节

后端变更

1. Repository 层

文件: server/app/repositories/credit_repository.py

新增方法:

  • get_expiring_gifts(days: int) - 获取即将过期的赠送积分
  • get_expired_gifts() - 获取已过期的赠送积分
  • get_user_expiring_gifts(user_id, days) - 获取用户即将过期的积分

2. Service 层

文件: server/app/services/credit_service.py

新增方法:

  • get_expiring_credits(user_id, days) - 查询用户即将过期的积分
  • expire_gift_credits() - 过期赠送积分(定时任务调用)
  • _get_model_pricing_from_ai_service(feature_type, model_name) - 从 AI Service 获取定价

修改方法:

  • calculate_credits(feature_type, params) - 优先使用 AI Service 定价

3. Celery 任务

文件: server/app/tasks/credit_tasks.py (新建)

新增任务:

  • expire_gift_credits_task() - 过期积分定时任务
  • notify_expiring_credits_task(days) - 过期通知任务
  • collect_credit_statistics_task() - 积分统计任务

4. Celery 配置

文件: server/app/core/celery_app.py

新增定时调度:

beat_schedule={
    "expire-gift-credits": {
        "task": "app.tasks.credit_tasks.expire_gift_credits_task",
        "schedule": crontab(hour=3, minute=0),
    },
    "notify-expiring-credits": {
        "task": "app.tasks.credit_tasks.notify_expiring_credits_task",
        "schedule": crontab(hour=10, minute=0),
        "kwargs": {"days": 7},
    },
}

5. API 路由

文件: server/app/api/v1/credits.py

新增端点:

  • GET /api/v1/credits/expiring - 查询即将过期的积分

请求参数:

{
  "user_id": "uuid",
  "days": 7
}

响应示例:

{
  "code": 200,
  "message": "查询到 100 积分即将在 7 天内过期",
  "data": {
    "total_expiring": 100,
    "days": 7,
    "items": [
      {
        "gift_id": "uuid",
        "credits": 50,
        "gift_type": "register",
        "description": "注册赠送",
        "expires_at": "2026-02-03T00:00:00Z",
        "days_until_expiry": 7
      }
    ]
  }
}

数据库变更

无数据库结构变更,使用现有的 credit_gifts 表的 expires_at 字段。

缓存策略

Redis 缓存键格式:

ai_model:pricing:{model_name}
ai_model:pricing:default_{model_type}

TTL: 3600 秒(1 小时)

测试

单元测试

# 测试积分过期逻辑
pytest tests/unit/services/test_credit_service.py::test_expire_gift_credits

# 测试动态定价
pytest tests/unit/services/test_credit_service.py::test_calculate_credits_with_ai_service

# 测试降级策略
pytest tests/unit/services/test_credit_service.py::test_calculate_credits_fallback

集成测试

# 测试定时任务
pytest tests/integration/tasks/test_credit_tasks.py

# 测试 API 端点
pytest tests/integration/api/test_credits.py::test_get_expiring_credits

部署说明

1. 重启 Celery Beat

定时任务配置已更新,需要重启 Celery Beat:

# 重启 Celery Beat 容器
docker restart jointo-server-celery-beat

# 验证定时任务已加载
docker exec jointo-server-celery-beat celery -A app.core.celery_app inspect scheduled

2. 验证 Redis 连接

确保 Redis 服务正常运行:

# 检查 Redis 容器状态
docker ps | grep redis

# 测试 Redis 连接
docker exec jointo-server-redis redis-cli ping

3. 监控定时任务

查看定时任务执行日志:

# 查看 Celery Beat 日志
docker logs -f jointo-server-celery-beat

# 查看 Celery Worker 日志
docker logs -f jointo-server-celery-ai

4. 手动触发测试

可以手动触发定时任务进行测试:

# 进入容器
docker exec -it jointo-server-app bash

# 手动触发过期任务
python -c "from app.tasks.credit_tasks import expire_gift_credits_task; expire_gift_credits_task.delay()"

性能影响

积分过期机制

  • 定时任务执行时间: 预计 < 5 秒(处理 1000 条记录)
  • 数据库查询: 每天 1 次(凌晨 3 点)
  • 对用户影响: 无,后台异步处理

动态定价集成

  • 首次查询: 与原方案持平(1 次 DB 查询)
  • 缓存命中: 性能提升 100%(0 次 DB 查询)
  • 预期缓存命中率: >90%
  • 平均响应时间: 从 50ms 降至 5ms

监控指标

积分过期

  • credit.expiration.processed_count - 每天处理的过期记录数
  • credit.expiration.failed_count - 处理失败的记录数
  • credit.expiration.task_duration - 任务执行时长

动态定价

  • credit.pricing.cache_hit_rate - 缓存命中率
  • credit.pricing.fallback_count - 降级次数
  • credit.pricing.query_duration - 查询耗时

回滚方案

如果出现问题,可以快速回滚:

1. 禁用定时任务

编辑 server/app/core/celery_app.py,注释掉新增的定时任务:

beat_schedule={
    # "expire-gift-credits": {...},  # 注释掉
    # "notify-expiring-credits": {...},  # 注释掉
}

重启 Celery Beat:

docker restart jointo-server-celery-beat

2. 回滚定价逻辑

修改 calculate_credits() 方法,直接使用 credit_pricing 表:

async def calculate_credits(self, feature_type: int, params: Dict[str, Any]) -> int:
    # 跳过 AI Service 查询,直接使用 credit_pricing 表
    pricing = await self.repository.get_pricing(feature_type)
    # ... 原有逻辑

已知问题

  1. 过期通知功能: 当前仅记录日志,未实现实际通知(邮件、站内信)
  2. 批量处理: 大量过期记录时可能需要分批处理
  3. 缓存预热: 首次启动时缓存为空,需要预热

后续优化

  1. 实现过期通知功能(邮件、站内信、推送)
  2. 添加批量处理逻辑(每次处理 100 条)
  3. 实现缓存预热机制
  4. 添加更详细的监控和告警
  5. 优化定价计算性能

相关文档

贡献者

  • System

注意: 本次更新已在开发环境测试通过,建议在生产环境部署前进行充分测试。