docs(mm-transport): дефект #2 — heartbeat/status улетали в корень канала (b738a3dea3)
This commit is contained in:
1 parent
913282b667
commit
9d54f0dcba
1 file changed
+84
-1
@@ -4,7 +4,7 @@ created: '2026-09-29'
|
||||
updated: '2026-09-30'
|
||||
type: tech
|
||||
namespace: personal
|
||||
status: "транспорт+telegram+pairing+toolsets+рестарт ✅; \U0001F534 фикс root-post thread_id 2026-09-30 (916f2c7e4f) — ЖДЁТ РЕСТАРТА gateway; \U0001F534 открыт инцидент — бот не в канале hermes-maintenance"
|
||||
status: "транспорт+telegram+pairing+toolsets+фиксы тредов (916f2c7e4f, b738a3dea3) — ЖДУТ РЕСТАРТА gateway; \U0001F534 открыт инцидент — бот не в канале hermes-maintenance"
|
||||
tags:
|
||||
- hermes
|
||||
- mattermost
|
||||
@@ -16,6 +16,7 @@ tags:
|
||||
- hermes-maintenance
|
||||
- incident
|
||||
- thread-session-split
|
||||
- heartbeat-thread-nesting
|
||||
related:
|
||||
- '[[personal/projects/balda/mattermost-kraken-deploy.md]]'
|
||||
- '[[personal/tech/kraken-host-resource-limits.md]]'
|
||||
@@ -401,6 +402,88 @@ thread_id = post.get("root_id") or post_id or None
|
||||
456+ ошибок на чистом дереве — конфликт фикстур/состояния при параллельном
|
||||
сборе. Гонять **только целевые файлы**, иначе результат нечитаем.
|
||||
|
||||
## 🔴 Дефект #2 2026-09-30 (ЗАКРЫТ): heartbeat/status улетали в корень канала
|
||||
|
||||
**Симптом Alex:** «из треда все равно ушло пара сообщений в общий канал».
|
||||
|
||||
**Факты из MM API** (`GET /api/v4/channels/{id}/posts`) — 4 поста с `root=ROOT`:
|
||||
|
||||
```
|
||||
13:26:04 ⏳ Working — 6 min — iteration 45/90, terminal
|
||||
13:28:05 is fine, docker active, 27 containers. Bridge exited (2) 3 days ago. L
|
||||
13:30:25 is valid. Let me start the bridge and watch what happens.
|
||||
13:30:44 request for udp:reverse:0` at 15:30:32. Let me immediately re-test kr
|
||||
```
|
||||
|
||||
Первый — heartbeat, остальные — status-callback. Все — **синтетические отправки**.
|
||||
|
||||
### Причина
|
||||
|
||||
`gateway/run.py` (`_run_agent`), было:
|
||||
|
||||
```python
|
||||
_progress_thread_id = source.thread_id or (
|
||||
event_message_id if source.platform == Platform.SLACK else None
|
||||
)
|
||||
...
|
||||
_status_thread_metadata = self._thread_metadata_for_source(source, event_message_id) if _progress_thread_id else None
|
||||
```
|
||||
|
||||
**Mattermost не был в fallback** → `_progress_thread_id = None` → гейт
|
||||
`if _progress_thread_id` **не вызывал** `_thread_metadata_for_source`.
|
||||
|
||||
⚠️ **Ключевое:** ветка Mattermost-fallback **уже была
|
||||
написана** в `_thread_metadata_for_target`, но была **недостижима**:
|
||||
|
||||
```python
|
||||
if thread_id is None:
|
||||
if platform == Platform.MATTERMOST and reply_to_message_id:
|
||||
return {"thread_id": str(reply_to_message_id)} # <-- не доходило
|
||||
return None
|
||||
```
|
||||
|
||||
Аналогичный питфолл был уже починен для тред-постов (коммит `f7dbceae8e`
|
||||
— «nest tool progress, status and heartbeat posts in thread»), но остался **корневой случай**.
|
||||
|
||||
### Фикс (коммит `b738a3dea3`)
|
||||
|
||||
Выражение вынесено в именованную функцию уровня модуля
|
||||
`gateway.run._progress_thread_id_for` + Mattermost добавлен в fallback, зеркально Slack:
|
||||
|
||||
```python
|
||||
def _progress_thread_id_for(platform, thread_id, event_message_id):
|
||||
if thread_id:
|
||||
return thread_id
|
||||
if platform in (Platform.SLACK, Platform.MATTERMOST):
|
||||
return event_message_id
|
||||
return None
|
||||
```
|
||||
|
||||
Telegram и Discord остаются `None` — они роутятся по реальным id топиков.
|
||||
|
||||
### 📌 Питфолл: тест-копия выражения — фальшивое покрытие
|
||||
|
||||
Первая версия тестов дублировала выражение своей копией —
|
||||
**11 passed на НЕФИКШЕНОМ коде**. Не ловили баг вообще.
|
||||
Правильно: вынести логику в функцию и **импортировать её в тест**.
|
||||
Тест, который переписывает прод-логику своими словами, **ничего не гарантирует**.
|
||||
|
||||
После рефактора — **проверено откатом**: на нефикшеном helper падает
|
||||
`assert None == {'thread_id': 'root_post_abc'}` — ровно наш баг.
|
||||
|
||||
### Тесты
|
||||
|
||||
`tests/gateway/test_mattermost_synthetic_thread_metadata.py` — 12 тестов.
|
||||
|
||||
| Прогон | Результат |
|
||||
|---|---|
|
||||
| На нефикшеном коде | 2 failed — баг воспроизведён |
|
||||
| Целевой срез (6 файлов) | 215 passed |
|
||||
|
||||
⚠️ `edit_message` тут **ни при чём** — он патчит уже существующий пост и `root_id`
|
||||
не задаёт. Обрывки текста в списке — это ОТДЕЛЬНЫЕ посты
|
||||
`status_callback`, а не части одного сообщения.
|
||||
|
||||
## 🔴 Питфоллы, найденные на месте
|
||||
|
||||
1. **`mmctl user convert --bot` требует ШЕСТЬ флагов, не один.**
|
||||
|
||||
Reference in new issue
Block a user