Перейти к содержанию

C. Financial Transaction Pipeline

Walkthrough · Раздел03

Тип материала: учебный архитектурный сценарий. Не описывает систему конкретной компании.

Границы и версии

PostgreSQL17 intake/outbox → Kafka4.1 → command consumer → authoritative ledger transaction → posted-event outbox → reporting. Intake success, ledger posted и report visible — разные состояния. Учебная архитектура HYPOTHETICAL, не готовая банковская платформа.

Data contracts

PaymentRequested содержит request_id,tenant,accounts,currency,exact amount,payload fingerprint и aggregate routing key. LedgerPosted имеет отдельный event_id,ledger transaction identity и link к request. Report consumer принимает committed posted facts, а не считает всякий PaymentRequested проведённым платежом.

State ownership и transaction boundaries

Владелец State / scope
Intake DB Accepted request и atomic publication intent
Ledger service / PG Authoritative journal/balance constraints/idempotency
Kafka Delivery/replay command и posted topics, разные contracts
Reporting DB Inbox+projection transaction; не financial authority

Архитектура — HYPOTHETICAL

flowchart TB
  Intake[PostgreSQL request plus outbox] --> Kafka[Kafka commands]
  Kafka --> Consumer[Idempotent command consumer]
  Consumer --> Ledger[Authoritative ledger transaction]
  Ledger --> Outbox[LedgerPosted outbox]
  Outbox --> Posted[Kafka posted facts]
  Posted --> Reporting[Atomic inbox and report projection]

Нормальная обработка по шагам

  1. Intake проверяет auth/schema и атомарно фиксирует request+outbox. Повтор с тем же request ID проверяет неизменность payload.

  2. Relay/CDC публикует Kafka message, допускающий повторы. Key задаёт partition order только в выбранном scope; cross-account serialization обеспечивается ledger transaction, не global topic order.

  3. Command consumer вызывает ledger protocol с тем же request_id. Locks/constraints, zero-sum postings и idempotency работают в одной authoritative DB transaction.

  4. Успешный ledger commit также пишет LedgerPosted outbox. При lost response consumer выясняет outcome по прежнему ID; не создаёт новый перевод.

  5. Posted relay публикует факт, reporting consumer выполняет inbox+projection atomic transaction, затем отдельно commit Kafka offset.

  6. Reconciliation сравнивает accepted/posted/report states и выявляет pending requests, duplicate/conflicting identities и расхождения totals. Отсутствие report не отменяет проведённую ledger transaction.

sequenceDiagram
  participant Source as Source or caller
  participant Kafka as Kafka retained log
  participant Sink as Processing worker
  participant Target as Target state
  Source->>Kafka: Relay publishes committed PaymentRequested
  Kafka->>Sink: Command consumer receives stable request ID
  Sink->>Target: Authoritative ledger transaction with outbox
  Target-->>Sink: Posted or previous matching result
  Sink->>Kafka: Commit command progress separately
  Target->>Kafka: Relay LedgerPosted for reporting

Failure / recovery sequence — HYPOTHETICAL

sequenceDiagram
  participant Source as Source or caller
  participant Kafka as Kafka retained log
  participant Sink as Processing worker
  participant Target as Target state
  Kafka->>Sink: Deliver request R
  Sink->>Target: Post transfer with idempotency R
  Target-->>Sink: COMMIT succeeds, response lost
  Note over Sink,Kafka: Consumer stops before offset commit
  Kafka->>Sink: Replay request R
  Sink->>Target: Same R and payload returns previous outcome
  Sink->>Kafka: Commit progress, reporting still deduplicates posted fact

Replay / backfill protocol

Replay command никогда не меняет request identity и не обходит ledger auth/invariants. Reporting backfill идёт из committed facts в отдельную projection generation. Inbox retention покрывает replay; marker и business effect нельзя размещать в разных stores без протокола.

Monitoring и alerting

Outbox age/retained WAL, Kafka lag/partition skew, ledger pending/idempotency conflicts/deadlocks/ambiguous commits, reporting inbox conflicts и currency reconciliation. Alert на долгое accepted-not-posted состояние отличается от report lag.

Trade-offs и альтернативы

Outbox добавляет storage/relay operations, но закрывает local publication-intent gap. Kafka EOS не заменяет ledger protocol. Альтернатива synchronous ledger command + posted outbox уменьшает intake steps, сохраняя idempotency. [Ledger SQL02] — минимальный учебный protocol, не production security hardening.

Типичные ошибки проектирования

Считать всю цепочку одной transaction; терять stable identity/versions; скрывать late/rejected scope; смешивать backfill и live generations; делать external financial effect во время технического replay.

Вопросы на собеседовании

Какая E2E guarantee доказана этой схемой? Сама схема ничего не доказывает. Нужны реализованные source/state/sink protocols и experiments для указанных failure points; фактически выполненные проверки перечислены в отчёте.

Практические упражнения

Воспроизведите failure sequence в изолированном runtime и сохраните source positions, target state, count/key/amount reconciliation и recovery evidence. До этого distributed guarantee остаётся документированной моделью.

Дополнительные источники и примеры

Протокол проверок (архив рабочего проекта) · Журнал ограничений (архив рабочего проекта).