# 部署流程与回滚方案

## 部署拓扑

```
                    ┌──────────┐
                    │  NGINX   │  :80/:443
                    └────┬─────┘
                         │
              ┌──────────┴──────────┐
              │                     │
        ┌─────▼─────┐         ┌─────▼─────┐
        │ zhixi-api │         │zhixi-worker│
        │  :3000    │         │ (no port)  │
        │ main.js   │         │worker.main │
        └─────┬─────┘         └─────┬─────┘
              │                     │
              │    ┌──────────┐     │
              └────┤  Redis   ├─────┘
                   │ (BullMQ) │
                   └────┬─────┘
                        │
                   ┌────▼────┐
                   │  MySQL  │
                   └─────────┘

  zhixi-heavy-runtime  (独立服务, 本批不修改)
```

## API 与 Worker 职责边界

| 职责 | API | Worker |
|------|:---:|:------:|
| HTTP Controller | ✅ | — |
| Queue Producer (add) | ✅ | — |
| BullMQ @Processor | — | ✅ |
| Prisma migration | ✅ (启动时) | — |
| 监听端口 | :3000 | 无 |
| systemd unit | `zhixi-nest-api` | `zhixi-nest-worker` |
| Docker CMD | `node dist/src/main.js` | `node dist/worker.main.js` |

## Docker 部署

```bash
# 构建
docker compose build api worker

# 启动（含 MySQL/Redis 依赖）
docker compose up -d

# 验证
docker compose exec api wget -qO- http://localhost:3000/health      # API health
docker compose logs worker | grep "Worker version"                   # Worker startup
# Heartbeat 验证见 M-AI-01-07
```

Docker 环境中 API 进程 Processor 数量为 0（`AppModule` 不含任何 `@Processor()` 注册，仅 `WorkerModule` 注册全部 5 个 Processor）。

## 生产 systemd 部署

```bash
# 1. 复制 unit 文件
sudo cp deploy/zhixi-nest-api.service /etc/systemd/system/
sudo cp deploy/zhixi-nest-worker.service /etc/systemd/system/
sudo systemctl daemon-reload

# 2. 启用自启动
sudo systemctl enable zhixi-nest-api zhixi-nest-worker

# 3. 启动
sudo systemctl start zhixi-nest-api
sudo systemctl start zhixi-nest-worker

# 4. 验证
sudo systemctl status zhixi-nest-api zhixi-nest-worker
curl -s http://localhost:3000/health
sudo journalctl -u zhixi-nest-worker -n 20 | grep "Worker version"
```

## 标准部署流程

无 DB 变更时（回滚同样适用）：

```
1. npm run build                              # 构建
2. sudo systemctl restart zhixi-nest-worker   # 先重启 Worker
3. sleep 5 && journalctl -u zhixi-nest-worker # 验证 Worker heartbeat
4. sudo systemctl restart zhixi-nest-api      # 再重启 API
5. curl http://localhost:3000/health          # 验证 API health
6. smoke test                                  # 业务验证
```

**原则**：Worker 先于 API 重启。API 重启期间 Worker 继续消费队列。Worker 重启期间 API 继续响应请求（jobs 变为 waiting）。

## 独立重启验证

- **API 重启不停止 Worker**：`systemctl restart zhixi-nest-api` 后 `systemctl status zhixi-nest-worker` 仍为 active
- **Worker 重启不停止 API**：`systemctl restart zhixi-nest-worker` 后 `curl localhost:3000/health` 返回 200

## 回滚方案

### 代码回滚

```bash
git revert <commit>           # 回滚代码
npm run build                 # 重新构建
sudo systemctl restart zhixi-nest-worker
sudo systemctl restart zhixi-nest-api
```

### Processor 恢复（回滚 M-AI-01-03）

如果拆分导致问题，恢复全部 5 个 Processor 到拆分前位置即可回退为 API 进程内消费模式：

1. 在 `app.module.ts` providers 中恢复 `AiAnalysisWorker`、`DocumentImportWorker`、`NotificationWorker`
2. 在 `admin-audit-log.module.ts` providers 中恢复 `AuditLogProcessor` 及 `BullModule.registerQueue({ name: QUEUE_AUDIT_LOG })`
3. 在 `files.module.ts` providers 中恢复 `FileCleanupProcessor` 及 `BullModule.registerQueue({ name: QUEUE_FILE_CLEANUP })`
4. 从 `worker.module.ts` providers 移除 `AuditLogProcessor`、`FileCleanupProcessor`
5. 停止 `zhixi-nest-worker` service：`sudo systemctl stop zhixi-nest-worker`
6. 重启 API：`sudo systemctl restart zhixi-nest-api`

此时全部 5 个 Processor 回到拆分前位置，API 进程同时担任 Producer 和 Consumer。

> 推荐使用 `git revert` 作为主回滚方案，可一步覆盖上述所有文件。

### 数据回滚

本批不涉及 Prisma Schema 变更，无需数据回滚。

### 队列安全

回滚前后验证 BullMQ 无双重消费：

```bash
# 检查 Bull Board 或 Redis 中的 active/waiting 计数
redis-cli LLEN bull:ai-analysis:waiting
redis-cli LLEN bull:ai-analysis:active
```
