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'
|
updated: '2026-09-30'
|
||||||
type: tech
|
type: tech
|
||||||
namespace: personal
|
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:
|
tags:
|
||||||
- hermes
|
- hermes
|
||||||
- mattermost
|
- mattermost
|
||||||
@@ -16,6 +16,7 @@ tags:
|
|||||||
- hermes-maintenance
|
- hermes-maintenance
|
||||||
- incident
|
- incident
|
||||||
- thread-session-split
|
- thread-session-split
|
||||||
|
- heartbeat-thread-nesting
|
||||||
related:
|
related:
|
||||||
- '[[personal/projects/balda/mattermost-kraken-deploy.md]]'
|
- '[[personal/projects/balda/mattermost-kraken-deploy.md]]'
|
||||||
- '[[personal/tech/kraken-host-resource-limits.md]]'
|
- '[[personal/tech/kraken-host-resource-limits.md]]'
|
||||||
@@ -401,6 +402,88 @@ thread_id = post.get("root_id") or post_id or None
|
|||||||
456+ ошибок на чистом дереве — конфликт фикстур/состояния при параллельном
|
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` требует ШЕСТЬ флагов, не один.**
|
1. **`mmctl user convert --bot` требует ШЕСТЬ флагов, не один.**
|
||||||
|
|||||||
Reference in new issue
Block a user