Правила 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 | для критичных flows | accounting_withdrawal_approved_total |
| backlog/lag | для очередей и jobs | masstransit_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
Каждая операция перечисляет побочные эффекты:
| Тип | Что Описывать |
|---|---|
| Events | event name, topic, key, payload source, MassTransit outbox transaction |
| External Calls | provider/client, endpoint/capability, timeout, retry, idempotency key |
| Cache | keys, invalidation или refresh policy |
| Read Models | projection/index/materialized view, sync/async update |
| Notifications | кому отправляется, шаблон, канал, suppression rules |
| Audit | audit action, actor, entity id, before/after fields |
Если side effects отсутствуют, пишется Побочные эффекты отсутствуют.
State Transitions
Запрещены неявные переходы состояния. Для каждой state machine создается таблица:
| From | To | Условие | Инициатор | Проверки | Побочные Эффекты |
|---|---|---|---|---|---|
Requested | Approved | Все проверки выплат пройдены. | Admin | permission, MFA, expectedVersion | audit, 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.
Обратные ссылки
Автоссылки: где используется этот документ.
- adr (1): ADR-0047: Structured Logging И Observability Standards
- backend-rules.md (1): Правила Backend Разработки
- backend-shared-standards-index.md (1): Backend Shared Standards Index