Event Bus (Apache Kafka)

Событийная модель пока пуста

Topics и события будут добавляться по мере реализации сервисов. Текущий скоуп (TASK-001: авторизация) не требует Kafka.

Конвенции

  • Topic naming: {service_domain}.{entity}.{action} (e.g. catalog.stoplist.updated)
  • Consumer group: {consumer_service}-group (e.g. warehouse-group)
  • Формат: JSON, обязательные поля: event_id, timestamp, version, payload
  • Идемпотентность: консьюмеры должны обрабатывать дубли (по event_id)
  • Partitioning: по entity_id для гарантии порядка в рамках одной сущности

SSE-мост admin → POS

Kafka — серверная инфра, до Tauri-приложения POS Desktop её не дотащить. Решение — мост через pos-bff: Fastify держит Server-Sent Events канал на каждый POS-терминал, Kafka consumer получает события каталога/стора/агрегатора и пушит их подключённым клиентам.

admin (PATCH price/stoplist/table)
        │
        ▼
catalog/store/aggregator-service ──outbox──► Kafka topics
                                                │
                                          consume│  group: pos-bff-sse-${HOSTNAME}
                                                ▼
                                      pos-bff (kafkajs)
                                                │ filter by franchise_id/store_id
                                                │ debounce 300ms на batch-update
                                                ▼
                                      SSE-hub → POS Desktop (EventSource)
                                                │
                                                ▼
                              menuStore.checkForUpdates / tablesStore.reload / aggregatorStore.reload

Топики на SSE: catalog.product.{upserted,deleted}, catalog.category.{upserted,deleted}, catalog.modifier_group.{upserted,deleted}, catalog.stoplist.updated, store.table.upserted, aggregator.order.received.

SSE-events для клиента: menu.invalidate, table.invalidate, aggregator.invalidate. POS на каждое событие дёргает соответствующий store, дальше сравнение snapshot решает показывать ли «обновите меню».

Per-pod Kafka group. Каждый инстанс pos-bff — отдельная consumer group (с HOSTNAME-суффиксом), чтобы все pod’ы получали все события — иначе SSE-клиенты на pod B не увидели бы события, обработанные pod A.

Auth для EventSource. EventSource в браузере не поддерживает Authorization header — JWT передаём через ?token=. Nginx с access_log off для /pos/api/v1/pos/notifications/stream чтобы токен не оседал в логах.

Nginx настройки. proxy_buffering off (иначе chunked не доезжает до клиента), proxy_read_timeout 3600s (default 30с обрывает idle-канал), Connection "" (keep-alive вместо close). Heartbeat : ping\n\n каждые 30с от pos-bff страхует от idle-kill промежуточных прокси.

Fallback на polling. Polling в POS Desktop (60с/10с/15с) НЕ удалён — работает как страховка при разрыве SSE. EventSource auto-reconnect ≈3с, при работающем SSE snapshot всегда совпадёт и доп. нагрузка минимальна.

Ссылки