[2026-09-26] eagle: personal/projects/balda/balda-mattermost-connector.md personal/projects/balda/balda-mm-delegation-plan.md personal/projects/balda/mattermost-kraken-deploy.md personal/tech/balda-go-fx-pitfalls.md
This commit is contained in:
1 parent
06950241dd
commit
e7091dd819
4 files changed
+286
-52
No files matched your search
@@ -1,6 +1,7 @@
|
||||
# Balda — Go/fx pitfalls и метод правок (зеркало скилла)
|
||||
|
||||
> Создано 2026-09-26. Зеркало секции скилла `devops/docker-balda-service`, добавленной 2026-09-26.
|
||||
> Создано 2026-09-26. Обновлено 2026-09-26 (ночь) — добавлены lint/arch-lint и закрытие Фазы 2.
|
||||
> Зеркало секции скилла `devops/docker-balda-service`, добавленной 2026-09-26.
|
||||
> Источник: работа над Mattermost-адаптером Балды (Фаза 2).
|
||||
> Проектные доки: [[personal/projects/balda/balda-mattermost-connector]],
|
||||
> [[personal/projects/balda/balda-mm-delegation-plan]].
|
||||
@@ -121,6 +122,117 @@ fx.Provide(
|
||||
4. `validate<X>Config` + вызов рядом с `validateSlackConfig`
|
||||
5. включить в `validateBaldaChannelConfiguration` (`cmd/balda/command.go`) —
|
||||
иначе деплой только на этом транспорте отбивается «at least one channel is required»
|
||||
6. `.go-arch-lint.yml` — компоненты `<x>_transport`/`<x>_wiring` + права у
|
||||
`composition_root` и `ingress_wiring` (см. §go-arch-lint выше)
|
||||
7. тест на `validateBaldaApplication` с `<x>.enabled=true` (см. §«go build ≠ …» выше)
|
||||
8. тест env-override в `cmd/balda/command_test.go` (по образцу
|
||||
`TestLoadConfigDocument_AppliesZulipEnvOverrides`)
|
||||
9. если добавлял маршрут в `BuiltinRoutes()` — обновить `TestBuiltinRoutes`
|
||||
10. доки: `docs/reference/configuration.md` (ключи), `docs/commands.md` (колонка транспорта)
|
||||
|
||||
**Финальные quality gates (все обязательны, из `AGENTS.md`):**
|
||||
```bash
|
||||
go build ./... # 0
|
||||
go vet ./... # 0
|
||||
go tool golangci-lint run # 0 issues
|
||||
go tool go-arch-lint check --project-path . # OK
|
||||
go test -race ./...
|
||||
```
|
||||
⚠️ `go-arch-lint` **не входит** в `golangci-lint` — запускать отдельно, иначе ошибка
|
||||
архитектуры всплывёт только на CI/ревью.
|
||||
|
||||
---
|
||||
|
||||
## 🔴 `go-arch-lint` — обязательный шаг для нового транспорта
|
||||
|
||||
⚠️ **Это не «опциональная придирка»: `AGENTS.md` прямо требует обновлять
|
||||
`.go-arch-lint.yml` в том же изменении, что и архитектуру.** Без правки линтер падает
|
||||
с двумя классами ошибок:
|
||||
|
||||
```
|
||||
Component composition_root shouldn't depend on .../channel/mattermost
|
||||
File /internal/apps/balda/channel/mattermost/adapter.go not attached to any component in archfile
|
||||
```
|
||||
|
||||
**Что добавить в `.go-arch-lint.yml` (4 правки) — по образцу `zulip`:**
|
||||
|
||||
1. **Секция `components:`** — пары `in:`-компонентов:
|
||||
```yaml
|
||||
# Provider-owned Mattermost transport. It may depend only on
|
||||
# transport-neutral contracts; application/runtime adapters live in wiring.
|
||||
mattermost_transport:
|
||||
in:
|
||||
- internal/apps/balda/channel/mattermost
|
||||
- internal/apps/balda/channel/mattermost/presentation
|
||||
|
||||
# Composition-root adapters for Mattermost delivery, prompt, and structured renderers.
|
||||
mattermost_wiring:
|
||||
in:
|
||||
- internal/apps/balda/channel/mattermost/mattermostfx
|
||||
```
|
||||
⚠️ Root-пакет и `presentation/` идут в **один** компонент `_transport`, а `_fx`-пакет —
|
||||
отдельно в `_wiring`. Именно так у `zulip`/`telegram`/`slackagent`.
|
||||
|
||||
2. **Правила `mayDependOn`:**
|
||||
- `mattermost_transport` → `foundation, contracts, neutral_registry, mattermost_transport`
|
||||
- `mattermost_wiring` → `foundation, contracts, neutral_registry, application, delivery,
|
||||
storage, mattermost_transport, mattermost_wiring`
|
||||
|
||||
3. **`composition_root`** → добавить `mattermost_transport`, `mattermost_wiring`
|
||||
(иначе «composition_root shouldn't depend on …» — это ожидаемый отказ, там
|
||||
перечислены все транспорты).
|
||||
|
||||
4. **`ingress_wiring`** → добавить `mattermost_transport` (соседствует с `telegram_transport`,
|
||||
`zulip_transport`).
|
||||
|
||||
Проверка: `go tool go-arch-lint check --project-path .` → должно быть `OK - No warnings found`.
|
||||
|
||||
---
|
||||
|
||||
## 🔴 `golangci-lint` на новом транспорте: мёртвый typing-throttle
|
||||
|
||||
Первый прогон дал 4 замечания — все в новом коде. Важный урок: **не гейтить линтер
|
||||
nolint-комментарием, а удалять мёртвый код.**
|
||||
|
||||
| Замечание | Что было | Фикс |
|
||||
|---|---|---|
|
||||
| `inamedparam` ×2 | `Start(context.Context) error` в interface-assertion | `Start(ctx context.Context) error` |
|
||||
| `unused` | `shouldSendTyping()` — недостижим, т.к. `SendTyping` всегда no-op | удалён |
|
||||
| `unused` | `websocketReceiveTimeout` — константа без использования | удалена |
|
||||
| `unlambda` | `func(client, logger) *Adapter { return NewAdapter(...) }` | заменено на `mattermost.NewAdapter` |
|
||||
|
||||
**Корневая причина `unused`:** механизм typing-throttle (`shouldSendTyping`, поля
|
||||
`typingThrottleInterval`/`typingLastSentAt`, `typingMu sync.Mutex`,
|
||||
`SetTypingThrottleInterval`) был скопирован из Zulip по аналогии. Но у Mattermost
|
||||
**ботов нет typing API** (`SendTyping` осознанно возвращает `nil`), поэтому весь механизм
|
||||
недостижим. Удалён целиком — не заглушён.
|
||||
|
||||
**Правило: при копировании транспорта с Zulip проверять каждую фичу на применимость.**
|
||||
Zulip-специфичное, что НЕ переносится в транспорт без поддержки:
|
||||
- typing-throttle (нужен интерактивный typing API)
|
||||
- логика `sendWithPlainFallback` — переносится, но только на content-rejection
|
||||
|
||||
⚠️ **Каскад после удаления полей:** удаление `typingThrottleInterval` потянуло `SetTypingThrottleInterval`
|
||||
→ `sync` (импорт) → `zerolog` (импорт в `module.go`). Удалять надо **всей группой**,
|
||||
иначе серия `undefined`/`imported and not used`.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Тест-регрессия: `BuiltinRoutes` и длина списка
|
||||
|
||||
Добавление маршрута в `BuiltinRoutes()` (`deliveryfmt/routes.go`) **ломает** `TestBuiltinRoutes`
|
||||
в `deliveryfmt/registry_test.go`, если не обновить ожидание:
|
||||
|
||||
```
|
||||
len(BuiltinRoutes()) = 5, want 4
|
||||
```
|
||||
|
||||
Фикс — добавить строку в map `want`:
|
||||
```go
|
||||
{transport: TransportMattermost, deliveryFormat: DeliveryFormatNone}: NamePlainText,
|
||||
```
|
||||
📌 Нашлось только сравнением «с правками / без правок» через `git stash` — в списке
|
||||
предсуществующих падений апстрима этого теста **не было**, значит это наша регрессия.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user