Financial correctness¶
Тип материала — инженерная модель. HYPOTHETICAL — значения, состояния и схемы.
Инварианты и границы¶
Финансовый эффект определяется сохранённой операцией, которая связана с экономическим основанием. Exactly-once delivery описывает доставку в определённом протоколе. Повтор с новым business ID способен создать второй сбалансированный journal. Unique constraint по области операции, сравнение параметров и атомарный commit журнала защищают эффект в пределах одной БД.
Проводки должны балансироваться внутри journal и currency. Нулевой итог по всей таблице не обнаружит ошибочное направление, пропуск пары или дубликат пары. Кредитный и дебетовый знак выбираются по типу счёта. Денежные значения хранятся в точных единицах с явно заданной валютой и scale. FX требует отдельных балансирующих счетов по каждой валюте. Остаток может участвовать в авторитетном guard, если его изменение атомарно с posting, он имеет определённого владельца и регулярно сверяется с журналом. UI projection используется для чтения.
flowchart LR
C[Stable business command] --> T[Atomic operation and journal commit]
T --> P[Balance projection]
T --> O[Outbox]
T --> R[Independent reconciliation]
E[External statement] --> R
Нормальная проводка¶
sequenceDiagram
participant C as Client
participant L as Ledger transaction
participant D as Ledger DB
C->>L: Submit operation ID and amount
L->>D: Check identity and lock position
L->>D: Write balanced legs and result
D-->>C: Return committed journal reference
Lost ACK и ambiguous commit¶
sequenceDiagram
participant C as Client
participant D as Ledger DB
C->>D: Submit operation K
Note over D: Journal J committed
D--xC: ACK lost
C->>D: Retry K with identical parameters
D-->>C: Return stored reference J
- Принять перевод 30 EUR с ID K.
- Зафиксировать ID, параметры и журнал J одним commit.
- При timeout открыть проверку исхода. На авторитетном writer повторить ту же операцию или прочитать сохранённый результат. Отсутствие записи на отстающей реплике недостаточно для нового запроса.
- Если исход относится к PSP, разрешить его по PSP lookup, подписанному callback и settlement evidence. Истечение окна дедупликации переводит операцию в review.
| Срез | Durable state | Наблюдение |
|---|---|---|
| До commit | K отсутствует | Клиент ожидает |
| После отказа | K → J, legs −30 и +30 | ACK неизвестен |
| После retry | Тот же J | Второй эффект отсутствует |
Конкурентный расход¶
- При available 100 одновременно поступают два расхода по 70 с разными ID.
- Оба читают предварительное значение. Под lock или serializable transaction первая операция фиксирует legs и уменьшает available до 30.
- Вторая заново проверяет состояние либо повторяет всю aborted transaction после serialization error. При 30 расход отклоняется.
- Заблокировать счета в устойчивом порядке для переводов между ними. Guard и legs держать в одном commit.
| Срез | Available | Durable postings |
|---|---|---|
| До гонки | 100 | Исходное состояние |
| После первого commit | 30 | Один расход 70 |
| После retry второго | 30 | Один расход 70 |
Исправление после закрытия¶
- Проводка J на 60 зафиксирована и вошла в отчёт V1. Независимый statement подтверждает 50.
- Сверить identity и исключить ожидаемую задержку, комиссию или частичный расчёт.
- Approver создаёт корректирующий journal на разницу либо reversal и replacement согласно утверждённой policy. Сохранить ссылку на J и evidence.
- Выпустить V2 с собственным cut и lineage. Retry correction по тому же ID возвращает прежний результат.
| Срез | Учёт | Evidence |
|---|---|---|
| До обнаружения | J = 60 | Отчёт V1 |
| После расхождения | J = 60 | Statement 50 и exception |
| После исправления | J и adjustment −10 | V1 и V2 со связью |
Compensation совершает новый эффект. Rollback отменяет незавершённую транзакцию. Сверка сравнивает независимые IDs, multiplicity, валюты и суммы на явном cut. Audit trail связывает инициатора, policy version, исходное событие, journal, correction и выпуск отчёта.