Kamixitong/docs/license_expiration_fix.md
2025-12-12 11:35:14 +08:00

223 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 卡密过期状态自动更新方案
## 问题描述
之前卡密系统存在一个严重问题:**卡密激活后即使到期,状态也不会自动更新为"已过期"**,导致用户可以一直使用已过期的卡密。
### 问题根源
1. 只有在用户主动调用 `verify()` 方法验证时,才会检查过期状态
2. 如果用户不验证(离线使用、关闭验证等),卡密状态不会更新
3. 缺少定期检查过期卡密的后台任务
## 解决方案
### 1. 新增功能
#### 后台定时任务
- **每小时检查一次**自动将已激活但已过期的卡密状态更新为2已过期
- **每天凌晨2点**:执行全面的卡密健康检查和统计
- **每周清理**:清理过期的审计日志
#### 手动触发接口
管理员可以通过API手动触发检查立即更新过期卡密状态。
### 2. 文件变更
#### 新增文件
1. **`app/utils/background_tasks.py`** - 后台任务模块
- `update_expired_licenses()` - 更新过期卡密状态
- `check_licenses_batch()` - 批量检查所有卡密状态
- `cleanup_old_license_logs()` - 清理旧日志
2. **`app/utils/scheduler.py`** - 定时任务调度器
- 管理所有后台定时任务
- 提供任务状态查询功能
#### 修改文件
1. **`requirements.txt`** - 添加 APScheduler 依赖
2. **`app/__init__.py`** - 应用启动时初始化调度器
3. **`app/api/license.py`** - 新增4个API接口
### 3. 新增API接口
#### 3.1 手动检查过期卡密
```
POST /api/v1/licenses/check-expired
```
权限:管理员
响应示例:
```json
{
"success": true,
"message": "成功更新 5 个过期卡密状态",
"data": {
"updated_count": 5
}
}
```
#### 3.2 批量检查所有卡密状态
```
POST /api/v1/licenses/batch-check
```
权限:管理员
响应示例:
```json
{
"success": true,
"message": "批量检查完成",
"data": {
"active_but_expired": 5,
"expired_and_marked": 12,
"active_and_valid": 158,
"inactive": 45,
"disabled": 3
}
}
```
#### 3.3 获取定时任务状态
```
GET /api/v1/scheduler/status
```
权限:管理员
响应示例:
```json
{
"success": true,
"data": {
"running": true,
"jobs": [
{
"id": "update_expired_licenses_hourly",
"name": "每小时更新过期卡密状态",
"next_run_time": "2024-01-15T10:00:00",
"trigger": "interval[1:00:00]"
},
{
"id": "daily_license_health_check",
"name": "每日卡密健康检查",
"next_run_time": "2024-01-16T02:00:00",
"trigger": "cron[hour:2]"
}
]
}
}
```
#### 3.4 手动触发定时任务检查
```
POST /api/v1/scheduler/trigger-check
```
权限:管理员
响应示例:
```json
{
"success": true,
"message": "成功更新 5 个过期卡密状态"
}
```
## 部署步骤
### 1. 安装依赖
```bash
pip install APScheduler==3.10.4
```
### 2. 重启应用
重启Flask应用调度器会自动启动。
### 3. 验证部署
- 查看应用日志,确认调度器启动成功
- 调用 `/api/v1/scheduler/status` 查看任务状态
- 调用 `/api/v1/licenses/batch-check` 进行一次全面检查
## 配置选项
### 禁用调度器
如果需要禁用定时任务,可以设置环境变量:
```bash
export DISABLE_SCHEDULER=true
```
### 修改检查频率
如需修改定时任务的执行频率,编辑 `app/utils/scheduler.py` 文件中的调度器配置:
```python
# 每30分钟检查一次
scheduler.add_job(
func=check_and_update_expired_licenses,
trigger=IntervalTrigger(minutes=30),
id='update_expired_licenses_half_hourly',
name='每30分钟更新过期卡密状态',
replace_existing=True,
max_instances=1
)
```
## 日志监控
所有定时任务的执行都会记录到应用日志中:
```
INFO - 开始检查过期卡密...
INFO - 成功更新 5 个过期卡密状态
INFO - 定时任务调度器已启动
```
## 测试验证
### 手动测试步骤
1. **创建测试卡密**
- 生成一个短期卡密如1天有效期
- 记录卡密ID
2. **激活卡密**
- 通过客户端激活卡密
- 确认状态为1已激活
3. **模拟过期**
- 修改数据库中的 `expire_time` 为过去时间
- 或等待卡密自然过期
4. **触发检查**
- 调用 `POST /api/v1/licenses/check-expired`
- 确认返回更新的卡密数量
5. **验证状态**
- 查询卡密详情确认状态变为2已过期
### 自动化测试
可以编写自动化测试脚本,定期调用检查接口并验证结果。
## 注意事项
1. **数据库事务**:所有状态更新都在事务中执行,确保数据一致性
2. **错误处理**:定时任务失败不会影响应用正常运行
3. **并发安全**:使用 `max_instances=1` 防止并发执行
4. **日志记录**:所有操作都有审计日志,便于追踪
5. **性能考虑**:大批量更新时,建议分批处理以避免锁表
## 监控建议
1. **设置告警**:当定时任务连续失败时发送告警
2. **定期检查**:每周查看一次定时任务执行日志
3. **统计报告**:每月统计过期卡密数量和趋势
## 总结
通过添加后台定时任务和手动触发接口,彻底解决了卡密过期状态不更新的问题。系统现在可以:
✅ 自动检测过期卡密并更新状态
✅ 提供管理员手动检查接口
✅ 记录详细的执行日志
✅ 支持灵活的配置和监控
确保用户无法继续使用已过期的卡密,提升了系统的安全性和可靠性。