forked from erp-dev/erp
feat: big version, added tasks for backup_database and stock change, added health check api, approve sse (support channel via merchant)
This commit is contained in:
108
docs/celery_testing.md
Normal file
108
docs/celery_testing.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Celery 任务测试指南
|
||||
|
||||
## 1. 自动化测试(单元测试/CI)
|
||||
|
||||
项目新增了三个演示型任务(`api_v1/tasks.py`):
|
||||
|
||||
| 任务 | 功能 |
|
||||
|------|------|
|
||||
| `ping_task(message='ping')` | 打印并返回时间戳,用于快速验证 worker 是否可接收/返回结果 |
|
||||
| `merchant_product_count(merchant_id)` | 统计某商户下产品数量,示范如何在任务中访问数据库 |
|
||||
| `backup_database(output_dir=None, filename_prefix='db-backup')` | 将当前数据库导出为 `.sql` 文件(数据备份),默认保存到 `BASE_DIR/data-bak/` |
|
||||
|
||||
对应的单元测试位于 `api_v1/tests.py`(类 `CeleryTasksTestCase`),通过
|
||||
`@override_settings(CELERY_TASK_ALWAYS_EAGER=True)` 让任务在测试进程内同步执行。
|
||||
|
||||
运行方式:
|
||||
|
||||
```bash
|
||||
uv run manage.py test api_v1.tests.CeleryTasksTestCase
|
||||
```
|
||||
|
||||
若要在其他测试中调用任务,只需在测试类上使用同样的 `override_settings`
|
||||
即可保证 Celery 在没有 worker 的情况下仍能同步执行。
|
||||
|
||||
---
|
||||
|
||||
## 2. 本地验证真实 worker(RabbitMQ + Celery)
|
||||
|
||||
### 2.1 启动依赖服务
|
||||
|
||||
```bash
|
||||
# 启动基础设施(Postgres/Redis/Rabbit/Celery worker/web)
|
||||
docker compose up -d postgres redis rabbitmq
|
||||
|
||||
# 启动 web(Django)
|
||||
docker compose up -d web
|
||||
|
||||
# 启动 Celery worker(如已运行,可跳过)
|
||||
docker compose up -d celery_worker
|
||||
# 或者手动:uv run celery -A flower worker -l info
|
||||
```
|
||||
|
||||
> 若 worker 容器异常,可通过 `docker compose restart celery_worker` 重启。
|
||||
|
||||
### 2.2 发送测试任务
|
||||
|
||||
在另一个终端进入容器或宿主项目目录执行:
|
||||
|
||||
```bash
|
||||
uv run python manage.py shell
|
||||
```
|
||||
|
||||
```python
|
||||
from api_v1.tasks import ping_task, merchant_product_count, backup_database
|
||||
from basic_info.models import Merchant
|
||||
|
||||
# 发送心跳任务
|
||||
async_result = ping_task.delay('hello celery')
|
||||
print(async_result.get(timeout=10))
|
||||
|
||||
# 发送统计任务(示例:使用 ID=1 的商户)
|
||||
merchant = Merchant.objects.first()
|
||||
result = merchant_product_count.delay(merchant.id)
|
||||
print(result.get(timeout=10))
|
||||
|
||||
# 触发数据库备份(输出到默认 data-bak)
|
||||
backup = backup_database.delay(filename_prefix='manual-backup')
|
||||
print(backup.get(timeout=30)) # payload 中包含 backup_path,文件为 .sql
|
||||
```
|
||||
|
||||
### 2.3 观察执行结果
|
||||
|
||||
1. **Worker 日志**:`docker compose logs -f celery_worker` \
|
||||
可查看任务被消费、日志输出等信息。
|
||||
2. **RabbitMQ 控制台**:访问 `http://localhost:15672`(默认账号 guest/guest),
|
||||
观察队列长度是否回落到 0。
|
||||
3. **Task Result**:上面的 `result.get()` 会在任务完成时返回 payload,
|
||||
若超时或无法连接则会抛出异常,帮助定位问题。
|
||||
|
||||
---
|
||||
|
||||
## 3. 失败排查 Checklist
|
||||
|
||||
1. **环境变量**:`CELERY_BROKER_URL` 和 `CELERY_RESULT_BACKEND` 是否指向
|
||||
正在运行的 RabbitMQ/Redis?
|
||||
2. **Worker 进程**:`docker compose ps` 确认 `celery_worker` 状态为 Up。
|
||||
3. **队列阻塞**:RabbitMQ 控制台查看是否有大量消息处于 `Unacked`。
|
||||
4. **日志级别**:测试中需要捕获日志时,可使用
|
||||
`with self.assertLogs('api_v1.tasks', level='INFO')`.
|
||||
5. **自动化测试**:若任务在测试里需要真实队列,请去掉
|
||||
`CELERY_TASK_ALWAYS_EAGER` 覆盖;否则保持默认值即可同步执行。
|
||||
6. **数据库备份依赖**:`backup_database` 在 PostgreSQL 场景下需要系统可执行 `pg_dump`,
|
||||
请确保容器/宿主机已安装 PostgreSQL 客户端工具;SQLite 则会使用内置 `iterdump` 生成 `.sql`。
|
||||
|
||||
---
|
||||
|
||||
## 4. 常用命令速查
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
| 启动 worker | `docker compose up -d celery_worker` |
|
||||
| 查看 worker 日志 | `docker compose logs -f celery_worker` |
|
||||
| 重启 worker | `docker compose restart celery_worker` |
|
||||
| 清空 RabbitMQ 队列 | `docker compose exec rabbitmq rabbitmqctl purge_queue flower`(示例) |
|
||||
| 运行单个任务测试 | `uv run python manage.py shell` -> `ping_task.delay()` |
|
||||
|
||||
通过以上步骤,即可确认 Celery + RabbitMQ 在本地能够成功执行任务,并在自动化测试里保持覆盖。若需要新增业务任务,可参考 `api_v1/tasks.py` 的写法:使用 `@shared_task`,在任务内进行必要的日志记录,便于问题排查。***
|
||||
|
||||
Reference in New Issue
Block a user