Архитектура верхнего уровня
NOTE
Статус: Target design. Документ описывает целевую архитектуру. Сервисы, модули и контракты, упомянутые ниже, могут ещё не существовать в
backend/. Правила маркировки — в50-processes/documentation-standard.md.
Компоненты системы и потоки данных.
Компонентная схема
┌────────────────────────────────────────────────────────────────────┐
│ ВНЕШНИЕ ИСТОЧНИКИ │
│ [ETM API] [Supplier B] [Supplier C] ... │
└────────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌────────────────────────────────────────────────────────────────────┐
│ CONNECTORS (целевые модули в backend/internal/connectors/*) │
│ • Плагины к ядру, реализующие connector.Connector │
│ • Rate Limiter (Redis), Session Manager, Async Job Poller │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────┐
│ KAFKA │
│ raw.* │
└──────────────────┘
│
┌───────────────┼──────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐
│ S3 / MinIO │ │ NORMALIZE │ │ CLICKHOUSE PIPELINE│
│ raw.payload │ │ service │ │ history (price/stk)│
└──────────────┘ └──────────────┘ └─────────────────────┘
│
▼
┌──────────────────┐
│ KAFKA │
│ offer.* │
└──────────────────┘
│
▼
┌──────────────────┐
│ MATCHING │
│ rules + ML/LLM │
└──────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ KAFKA │
│ canonical.events.v1 │
│ supplier.graph.events.v1 │
│ enrichment.job.events.v1 │
│ estimate.events.v1 │
└─────────────────────────────────────────┘
│
┌───────────────┼──────────────────┐
▼ ▼ ▼
┌────────────────┐ ┌──────────────┐ ┌──────────────────┐
│ POSTGRESQL │ │ ENRICHMENT │ │ ELASTICSEARCH │
│ primary store │ │ service │ │ search index │
│ event_store │ └──────────────┘ └──────────────────┘
│ outbox │ ┌──────────────────────────────┐
└────────────────┘ │ SUPPLY-CHAIN RECALCULATOR │
│ (consumer of supplier.graph) │
└──────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ CORE APPLICATION SERVICES (Go) │
│ • catalog-core • search • pricing • meta-search │
│ • visibility • normalization │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ PUBLIC-API SERVICE (multi-protocol) │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────────┐ │
│ │ REST (ServeMux)│ │ RPC (Connect) │ │ WS (coder/websocket)│ │
│ └────────────────┘ └────────────────┘ └────────────────────┘ │
│ Применяет Visibility Policy, freshness markers, EnrichmentJob │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ CLIENTS │
│ • Customer Web/Mobile UI — REST + WS │
│ • B2B integrations — gRPC │
│ • Admin UI (Next.js + Hero UI) — REST к admin-api (отдельно) │
└────────────────────────────────────────────────────────────────────┘
Ключевые потоки
Поток 1: Ingestion от поставщика
Scheduler tick
→ RateLimiter.acquire(supplier_id)
→ Connector.fetch()
→ produce(raw.supplier.<name>.payload)
↓
Parser/Normalizer consume
→ save raw to S3
→ parse → SupplierOffer (pre-match)
→ persist in PG (offers table)
→ produce(offer.normalized.v1)
↓
Matching Engine consume
→ lookup candidate canonical products (ES + PG)
→ apply rules + ML verification for low confidence
→ update offer.canonical_product_ref, match_confidence
→ produce(matching.decided.v1)
↓
If new canonical needed:
Canonical Service
→ apply CanonicalCreated / CharacteristicAdded events
→ event_store + outbox → canonical.events.v1
↓
Projection workers:
- PG projections (readmodels)
- ES canonical index update
- CH history
Поток 2: Мета-поиск / сборка сметы
User uploads estimate
→ parse lines (rule + LLM)
→ for each line:
- search candidates (ES)
- score & rank
- fetch offers of top-N canonical
- pricing engine(offer, context)
→ optimize (ILP / greedy)
→ produce breakdown + alternatives
→ persist estimate + version
→ response with explanation
Межсервисное взаимодействие внутри одного окружения
- Все контейнеры и сервисы среды входят в общий
docker-composenetworktracium. - Синхронные вызовы между сервисами идут по internal HTTP/Connect endpoint’ам через DNS-имена контейнеров (
catalog-core,pricing,search,postgres,kafka). - Host ports публикуются только для внешнего доступа разработчика, reverse proxy и операционной диагностики.
- Асинхронная межсервисная коммуникация остаётся на Kafka topics.
Модули ядра (краткий перечень)
catalog-core— canonical products, characteristics, manufacturers, identity profiles.offers— supplier offers, stock.pricing— Price Rules, Pricing Engine.search— абстракция поиска + ES connector.matching— движок матчинга.enrichment— AI-обогащение.meta-search— сборка смет.admin-api/public-api— HTTP endpoints.
Каждый модуль в ../30-services/<n>/ имеет свой README.
Внешние зависимости
- PostgreSQL 15+ — primary store, event store, outbox.
- Kafka — event bus + event sourcing distribution.
- Elasticsearch 8+ — search.
- ClickHouse — аналитика, история.
- Redis — cache, rate limiter, locks.
- S3 / MinIO — raw payloads, media.
- Secret backend / KMS — backend для master key и локальных/production secret flows (Vault Transit допустим, но не обязателен).
- OTel collector + backend (Grafana / Tempo / Loki).
Инструменты доставки
- GitLab CI/CD — lint, docs build, compose validation, release jobs.
- Quartz + GitLab Pages — web-публикация актуальной документации.
- SemVer + Keep a Changelog + git-cliff — версия продукта и release notes.