# 2026-07-13: 内部调度器停摆事件

## 告警

"异常告警：文章抓取系统已 19 天未获取新文章，请检查原因"

## 根因

2026-06-24 服务重启后 SQLite DB 短暂损坏（`no such table: users/articles`），导致内部调度器 TaskQueueManager 加载失败。服务在 17:37~23:07 陷入崩溃循环（每 13 秒重启一次，持续 5 小时）。虽然最终在 23:07 稳定启动（pid=1121980），但内部文章采集队列**永久停止**——最后一条 `werss:queue:history` 记录停在 2026-06-25 09:01。

## 时间线

| 时间 (CST) | 事件 |
|-------------|------|
| 06-24 17:37:25 | we-mp-rss 重启（pid=1029361），日志出现 `no such table: users` |
| 06-24 17:37:26 | `加载定时任务失败: no such table: message_tasks` |
| 06-24 17:57:14 | 服务停止 |
| 06-24 17:59:08 ~ 23:07:29 | 崩溃循环：每 ~13 秒重启一次，约 70+ 次重启 |
| 06-24 23:07:29 | 最终稳定启动（pid=1121980） |
| 06-25 09:00~09:01 | 内部调度器最后一次采集任务（中职生 + 广东中职菌） |
| 06-25 ~ 07-12 | 内部调度器停止，但 Hermes cron 94d230f73e7f 持续通过 fetch_and_push.py 触发抓取，DB 每日有文章入库 |
| 07-13 09:05 | 用户收到告警 |
| 07-13 09:09 | `sudo systemctl restart we-mp-rss` — 重启后调度器正常初始化，无 DB 错误 |

## 排查用到的关键命令

### 1. 验证三个数据源

```bash
# 源①：DB 文章时间线
cd ~/project/we-mp-rss-main && source venv/bin/activate && python3 -c "
import sqlite3
db = sqlite3.connect('/home/ubuntu/project/we-mp-rss-data/db.db')
rows = db.execute('''
    SELECT f.mp_name, datetime(MAX(a.publish_time), 'unixepoch', 'localtime') as last_pub
    FROM articles a JOIN feeds f ON a.mp_id = f.id
    GROUP BY f.mp_name
''').fetchall()
for r in rows: print(f'{r[1]} | {r[0]}')
"

# 源②：fetch_and_push.py
cd ~/project && source ~/project/we-mp-rss-main/venv/bin/activate && python3 scripts/fetch_and_push.py

# 源③：内部调度器队列历史
cd ~/project/we-mp-rss-main && source venv/bin/activate && python3 -c "
from core.redis_client import redis_client
import json
hist = redis_client._client.lrange('werss:queue:history', 0, -1)
for h in hist[-5:]:
    d = json.loads(h)
    print(f\"{d.get('start_time','?')} | {d.get('task_name','?')}: {d.get('duration','?')}s\")
"
```

### 2. 查看服务重启历史

```bash
journalctl -u we-mp-rss --no-pager | grep -E "Started we-mp-rss|Stopped we-mp-rss" 
```

### 3. 查看 DB 表是否存在

```bash
journalctl -u we-mp-rss --no-pager | grep -i "no such table"
```

### 4. 按天统计文章入库量

```bash
cd ~/project/we-mp-rss-main && source venv/bin/activate && python3 -c "
import sqlite3
db = sqlite3.connect('/home/ubuntu/project/we-mp-rss-data/db.db')
rows = db.execute(\"\"\"
    SELECT date(publish_time, 'unixepoch', 'localtime') as day, COUNT(*) as cnt
    FROM articles
    WHERE publish_time > CAST(strftime('%s','now','-30 days') AS INTEGER)
    GROUP BY day ORDER BY day DESC
\"\"\").fetchall()
for r in rows: print(f'{r[0]}: {r[1]}篇')
"
```

### 5. Redis 队列状态（注意 key 类型）

```bash
# werss:queue:status 是 hash 类型
cd ~/project/we-mp-rss-main && source venv/bin/activate && python3 -c "
from core.redis_client import redis_client
r = redis_client._client
# hash keys
for key in ['werss:queue:status', 'werss:content_queue:status']:
    print(f'=== {key} ===')
    for k, v in r.hgetall(key).items():
        print(f'  {k.decode()}: {v.decode()}')
# login check
print(f'login: {r.get(\"werss:login:status\")}')
"
```

## 修复

```bash
sudo systemctl restart we-mp-rss
# 验证：无 no such table 错误，Scheduler started 正常，API 返回 200
```

## 教训

1. 告警源（内部调度器队列历史）≠ 实际文章入库情况
2. 必须交叉验证三个数据源才能判断真实影响
3. 重启时检查日志是否有 `no such table` / `加载定时任务失败`
4. 重启后 `history_count`（hash）会被重置为 0，不影响功能
