- chat.Router: ограниченный пул chatWorkers=4 воркеров + FIFO-очереди per-user (userState/workerLoop/runUser). Порядок сообщений одного UserID сохраняется; разные пользователи обрабатываются параллельно (до 4 одновременных LLM-вызовов), long-poll Telegram не блокируется чужим аналитиком. Backpressure по jobs — только на перегруженного пользователя. - app.FreeChat: sessions под sync.Mutex (защита от data race при параллельных воркерах роутера). - update: ResolveLatest проверяет наличие бинаря HEAD-пробой без скачивания тела (fallback GET Range 0-0 при 405/501), сортировка версий по id убыв.; один общий http.Client (keep-alive) вместо нового на каждый запрос. - тесты: порядок/параллелизм per-user в router, HEAD-без-тела и фоллбэк на версию без бинаря в update. - память Serena: инварианты Router/update, примечания по форматированию на Windows.
4.3 KiB
4.3 KiB
conventions
Стиль / кодстайл
- Стандартный Go-стиль;
gofmt/go fmt ./.... Документация-комментарии и package-doc на русском языке. - Типизация: строгие типы, интерфейсы для абстракций (Decider, ui.Store, events.Event, chat.Channel).
- Свой тип
config.Durationдля времени (YAML-строки "5s"/"10m"), метод.Duration(). - UI: uni-directional data flow — UI читает снапшоты (копии,
ui.Store), не мутирует storage/core. Ядро публикует события вevents.Bus, UI подписываетсяevents.Hub→ колбэки в UI-поток черезfyne.Do.
Обработка ошибок
- Ошибки классифицируются по идентификаторам классов в исходниках (см. ниже).
- Ошибка-обёртка:
fmt.Errorf("%w: %v", ErrXxx, err). errors.Joinдля склейки нескольких ошибок валидации (config.Validate).
Классы ошибок (маркируются в коде, документированы в README)
| Блок | Коды | Где |
|---|---|---|
| C | C1–C4 | internal/config |
| A | A1–A4 | internal/analyst; A (app): A1–A4 в internal/app |
| M | M1–M5 | internal/chat |
| D | D1–D5 | internal/core (ErrDecideFailed, ErrMaxTurns, ErrCommandUnknown…) |
| O | O1–O5 | internal/opencode |
| S | S1–S5 | internal/storage |
| W | W1–W5 | internal/worker |
| E | E1–E4 | internal/worker (репозитории) |
| R | R1–R6 | internal/worker/review_errors.go |
| U | U1–U6 | internal/update |
Архитектурные конвенции
- Composition root — internal/app; подсистемы собираются там. UI-окно создаётся через
newUIWindow(store)(build-tag: cgo → desktop.New, !cgo → nil/headless). Флаг--nouiвыключает окно. - Слои: model (домен) ← storage/events/UI зависят только от model; core не знает про UI.
- Агенты (analyst.md/dev.md/reviewer.md) — markdown-промпты, go:embed, распаковка в config_dir. Вердикт — строгий JSON.
- Репо-клонирование/воркеры — через gitops; ветки задач
feat/<taskTag>(см. mem:core). - Обратная совместимость: поле
Repo(одиночный) иRepos(список); EffectiveRepos/ SetReposFromDB/ReposJoined в storage/models.go.
Версии
app.Version— семантическая major.minor.patch (ручной инкремент: patch=фиксы, minor=новая обратно-совместимая функциональность, major=несовместимые изменения). Сейчас 0.2.2.main.version(ldflag) — build-идентификаторcommit-<sha7>, отдельно от app.Version.
Форматирование (важно на Windows)
- Репо на Windows-чекауте:
core.autocrlf=true→ файлы в рабочей копии с CRLF;gofmt -lна CRLF-копии шумит (глобально ~60 файлов). Проверять формат только на LF-версии (напр.git -c core.autocrlf=false cloneво временный каталог) — так дифы видны корректно. - gofmt 1.26 форматирует doc-comments (
//передgo build ...в// go build→ пустая строка//) и выравнивание структур; не все файлы отформатированы по новой версии (предсуществующе). - CI (
go vet+go test) формат не проверяет → gofmt-дифы не ломают сборку. - Known race в тест-харнессе app:
e2eChannel.Send(internal/app/e2e_test.go:213) пишетc.sentбез лока, тест читает с главной горутины →-raceловит вTestE2ENotificationsOnTransitions. Путьworker→Notify→Send; предсуществует, ещё не чинили (fix — мьютекс вe2eChannel).