Перейти к основному содержимому

Правила Runtime-Поведения Операций

Назначение

Документ фиксирует обязательные требования к observability, transaction boundaries, side effects и state transitions для API methods, background jobs, event consumers, provider callbacks и admin actions.

CQRS Runtime

Каждая runtime-операция исполняется как command или query.

  • Command handler владеет изменением состояния внутри одного микросервиса, открывает локальную transaction boundary, сохраняет aggregate changes, audit, idempotency result и MassTransit outbox publish/send атомарно.
  • Query handler читает owned source of truth или documented projection/read model, не меняет operational state и описывает projection freshness.
  • Event consumer получает событие через MassTransit Inbox, выполняет локальный command/projection update и публикует новые события через локальный outbox, если они нужны.
  • Cross-service distributed transaction запрещена: взаимодействие между микросервисами идет через Kafka events, saga/compensation, reconciliation или явно описанный internal API lookup до/после локальной транзакции.
  • Любой sync internal API вызов в command должен иметь timeout, retry/circuit breaker, fallback и правило, что делать при частичном успехе.

Observability Requirements

Каждая операция описывает логи, метрики и tracing.

Логи

В постановке нужно указать:

  • вход операции: operation name, actor, tenantId, brandId, correlationId, request id, masked identifiers;
  • ключевые шаги: загружены aggregates, пройдены проверки, создана external session, событие добавлено в MassTransit outbox;
  • ошибки: validation failure, permission denied, provider rejected, concurrency conflict, idempotent duplicate, unexpected exception.

Логи не содержат secrets, raw PII, access/refresh tokens, payment credentials, KYC files и provider credentials.

Метрики

Для каждой операции указываются:

МетрикаОбязательностьПример
latencyвсегдаaccounting_deposit_create_duration_ms
error rateвсегдаaccounting_deposit_create_errors_total
throughputвсегдаaccounting_deposit_create_requests_total
business counterдля критичных flowsaccounting_withdrawal_approved_total
backlog/lagдля очередей и jobsmasstransit_outbox_pending_count, kyc_queue_size

Tracing

Trace должен переносить:

  • correlationId;
  • traceId;
  • causationId, если операция вызвана событием;
  • tenantId и brandId, если это безопасно;
  • external dependency span для provider, Redis, Kafka, PostgreSQL, file storage и Elasticsearch вызовов.

Transaction Boundary

Для каждой mutation операции явно указывается:

  • где начинается транзакция;
  • где заканчивается транзакция;
  • какие сущности участвуют;
  • какие MassTransit outbox publish/send, audit и idempotency records участвуют в той же транзакции;
  • используется ли distributed transaction, saga или компенсация;
  • что происходит при ошибке до commit и после commit.

Distributed transaction между сервисами запрещена по умолчанию. Cross-service consistency достигается через MassTransit Inbox/Outbox, idempotency, saga state и reconciliation jobs.

Side Effects

Каждая операция перечисляет побочные эффекты:

ТипЧто Описывать
Eventsevent name, topic, key, payload source, MassTransit outbox transaction
External Callsprovider/client, endpoint/capability, timeout, retry, idempotency key
Cachekeys, invalidation или refresh policy
Read Modelsprojection/index/materialized view, sync/async update
Notificationsкому отправляется, шаблон, канал, suppression rules
Auditaudit action, actor, entity id, before/after fields

Если side effects отсутствуют, пишется Побочные эффекты отсутствуют.

State Transitions

Запрещены неявные переходы состояния. Для каждой state machine создается таблица:

FromToУсловиеИнициаторПроверкиПобочные Эффекты
RequestedApprovedВсе проверки выплат пройдены.Adminpermission, MFA, expectedVersionaudit, MassTransit outbox, provider payout call

Правила:

  • статус нельзя менять без проверки текущего состояния;
  • illegal transition возвращает typed error и не меняет aggregate;
  • каждый переход указывает actor/system инициатора;
  • transition method находится в aggregate или domain service, а не в controller;
  • событие публикуется после успешного перехода через MassTransit outbox;
  • для платежей, accounting, KYC, бонусов и provider callbacks state transition table обязательна.

Идемпотентность И Concurrency

  • Внешний ввод, callbacks, admin decisions и money mutations имеют idempotency key или deterministic external reference.
  • Уникальный constraint защищает idempotency на уровне БД.
  • Mutable aggregates с ручными действиями используют ExpectedVersion.
  • Повторная операция возвращает ранее сохраненный результат или controlled duplicate response.
  • Out-of-order events/callbacks не должны откатывать более новое состояние.

Reconciliation

Если операция вызывает внешний provider до локального commit или получает callback после provider-side изменения, постановка должна описывать reconciliation:

  • источник правды;
  • ключ сопоставления;
  • периодичность job;
  • допустимые статусы для исправления;
  • audit trail исправления;
  • событие, публикуемое после reconciliation.

Обратные ссылки

Автоссылки: где используется этот документ.