8a2f72d366
Co-authored-by: zzhyyyyy <2685922758@qq.com> Reviewed-on: #63 Co-authored-by: zhuzihao <zhuzihao@wonderable.ai> Co-committed-by: zhuzihao <zhuzihao@wonderable.ai>
70 lines
3.8 KiB
Markdown
70 lines
3.8 KiB
Markdown
# 0 点自动兑金币 定时任务 — 运维手册
|
||
|
||
> 对象:维护「每天 0 点把用户金币自动兑成现金」这套定时任务的同事。
|
||
> 🔒 服务器登录信息见**私密交接清单**,不入库。
|
||
|
||
## 现状(2026-06 起):已改为 App 进程内任务,不再需要 systemd timer
|
||
「0 点自动兑换」现由 **App 进程内后台任务** `app.core.daily_exchange_worker` 负责:App 一起来就
|
||
每 10 分钟检查、跨过北京 0 点自动跑一轮(逐用户幂等、文件锁互斥、重启补跑当天遗漏)。**无需再装 / 启用
|
||
`daily-exchange.timer`**。
|
||
|
||
- 开关仍是 `.env` 的 `AUTO_EXCHANGE_ENABLED`(false → worker 不启动);间隔由 `AUTO_EXCHANGE_CHECK_INTERVAL_SEC`(默认 600s=10min)控。
|
||
- 下方 systemd timer / 脚本属**遗留 + 手动应急**:逻辑同一套且幂等,可手动 `--once` 补跑;
|
||
但**不要再 `enable` timer 与进程内 worker 并存**(虽幂等不会双兑,纯属多余)。
|
||
|
||
## 它是什么
|
||
客户端已删手动「兑金币」入口、改为「0 点自动兑现金(可能存在延迟)」,故服务端每天 0 点跑一轮:
|
||
把每个用户的金币按汇率 **100 金币 = 1 分** 兑成现金。
|
||
|
||
- **到分全额**:`coin_amount = floor(余额 / 100) × 100`,不足 1 分(<100 金币)的零头留到下次。
|
||
- **复用 `exchange_in` 流水类型**(手动兑入口已下线,不会混淆),用户在「现金明细」看到「金币兑换现金」。
|
||
- **幂等**:同一用户当天已有 `exchange_in` 流水则跳过 → timer 重触发 / 手动重跑当天不会重复兑。
|
||
- 逻辑见 `app/repositories/wallet.py::daily_auto_exchange`,入口 `scripts/daily_auto_exchange.py`。
|
||
|
||
## 文件
|
||
| 项 | 路径 |
|
||
|---|---|
|
||
| 脚本入口 | `scripts/daily_auto_exchange.py` |
|
||
| 核心逻辑 | `app/repositories/wallet.py::daily_auto_exchange` |
|
||
| 开关 | `.env` 的 `AUTO_EXCHANGE_ENABLED`(默认 true;false=脚本 no-op) |
|
||
| systemd 单元 | `deploy/daily-exchange.{service,timer}` |
|
||
| 运行锁 | `/tmp/daily_auto_exchange.lock`(可用环境变量 `DAILY_EXCHANGE_LOCK` 覆盖) |
|
||
|
||
## (遗留 / 可选)systemd timer 部署 — 现已被进程内 worker 取代,正常无需执行
|
||
```bash
|
||
# ⚠️ 仅在你明确想用外部 timer 而非进程内 worker 时才做(并把 worker 关掉),否则跳过。
|
||
sudo cp deploy/daily-exchange.{service,timer} /etc/systemd/system/
|
||
sudo systemctl daemon-reload && sudo systemctl enable --now daily-exchange.timer
|
||
systemctl list-timers daily-exchange.timer # 确认下次触发时间
|
||
```
|
||
|
||
## 本机 Windows 开发(无 systemd)
|
||
直接手动跑:
|
||
```
|
||
.venv\Scripts\python -m scripts.daily_auto_exchange --once
|
||
# 本地循环调试(每小时一轮,幂等空跑无害):
|
||
.venv\Scripts\python -m scripts.daily_auto_exchange --loop --interval 3600
|
||
```
|
||
|
||
## 怎么看健康 / 手动跑一次
|
||
```bash
|
||
sudo systemctl start daily-exchange.service # 立即手动跑一轮(不等 0 点)
|
||
journalctl -u daily-exchange -n 30 --no-pager # 看日志:扫描/兑换/跳过/失败/累计兑入分
|
||
```
|
||
日志一行形如:`自动兑完成 用时1.2s 扫描120 兑换88 已兑过跳过30 零头跳过2 失败0 累计兑入15600分`。
|
||
|
||
## 怎么关 / 临时停
|
||
- **临时停(推荐)**:`.env` 置 `AUTO_EXCHANGE_ENABLED=false` → 脚本 no-op,无需动 timer。
|
||
- **停 timer**:`sudo systemctl disable --now daily-exchange.timer`。
|
||
|
||
## 脚本参数
|
||
- `--once`:跑一轮(timer 用这个,默认)
|
||
- `--loop --interval N`:常驻循环,每 N 秒一轮(默认 3600,调试用)
|
||
- 锁位置可用环境变量 `DAILY_EXCHANGE_LOCK=/path/to.lock` 覆盖
|
||
|
||
## 注意事项
|
||
- **触发时间**:`OnCalendar=*-*-* 00:00:00`。客户端文案已注明「可能存在延迟」,要错开整点扎堆可改 `00:05:00`。
|
||
- **catch-up**:`Persistent=true`,服务器宕机错过当天会在重启后补跑一轮。
|
||
- **DB 无关**:sqlite / postgres 均可(不像美团 ETL 需要 PG)。
|
||
- **改脚本 / 改部署**:走 git + PR,由有 root 的人部署。
|