4.2 KiB
Брейншторм: Микросервисные паттерны
Дата: 2026-02-21
Контекст
Team Board = микросервисная архитектура: Tracker (ядро), Picogent (агенты), Bridges (Telegram, OpenClaw), Web Client, BFF.
Принятые паттерны
✅ Event Bus (Redis Streams) — КЛЮЧЕВОЕ
Redis Streams как шина событий между Tracker и потребителями.
Проблема: WS-событие теряется если клиент offline. При reconnect — пропущенные сообщения потеряны.
Решение: Tracker пишет события в Redis Stream → потребители (agents, bridges) читают из stream. Если потребитель был offline → при reconnect читает с последнего обработанного offset.
Плюсы:
- Persistent queue — события не теряются
- Consumer groups — несколько потребителей одного потока
- Replay — можно перечитать историю
- Redis у нас уже есть (порт 6380)
Статус: нужно продумать детали (формат событий, consumer groups, retention policy).
✅ Saga Pattern (компенсации)
Каждый шаг агента имеет компенсацию при сбое.
Пример:
take_task(42)→ задача in_progress- Агент работает...
- Агент упал (heartbeat timeout)
- Компенсация: задача → todo, комментарий "Агент упал, задача возвращена"
✅ Idempotency
Каждое сообщение/событие имеет уникальный ID. Повторная доставка с тем же ID → игнорируется. Критично для reliable delivery через Event Bus.
✅ Centralized Logging
Все сервисы: structured JSON logging (Pino для Node.js, structlog для Python). Единый формат → возможность агрегации.
✅ Circuit Breaker
Exponential backoff при недоступности Tracker. Picogent уже реализует (1s → 2s → 4s → ... → 30s cap). Event Bus частично решает: если Tracker упал, события копятся в Redis.
Отклонённые
❌ Service Discovery
Один Tracker — overkill.
❌ API Gateway (BFF для всех)
Бессмысленно отдельный BFF если все через него. BFF остаётся только для Web Client.
❌ Health Check / Readiness Probe
Агенты должны быть доступны по IP:port — слишком сложно. Heartbeat через WS достаточен.
На подумать
✅ Event Bus: Redis Streams (решение)
Выбор: Redis Streams (не RabbitMQ — тот не хранит историю).
Роль: real-time доставка + буфер при reconnect. НЕ хранилище истории (это PostgreSQL).
Retention: ~24ч. Старые события — из PostgreSQL через REST API.
✅ Lazy Loading контекста (ключевое решение)
Агент при подключении НЕ грузит историю. Как человек — зашёл и видит только новое.
1. Subscribe на Redis Stream (real-time, с текущего момента)
2. GET /tasks?assignee=me # мои задачи
3. GET /project/{id}/docs # документация
4. Работает. Историю НЕ грузит.
5. Если нужен контекст → read_messages(limit=10) — пагинация назад
Почему: не засоряет контекст LLM, агент сам решает когда подгружать. Prompt guideline: "Если не хватает контекста — используй read_messages()"
Reconnect
1. XREAD STREAMS events {last_event_id} # пропущенные
2. Если last_event_id > 24ч — начинаем с текущего момента