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

Digital wallet и balance management

Раздел 05 · Редакционный стандарт

Тип материала — референсная архитектура. HYPOTHETICAL — схемы и операции. INFERENCE — инженерные рекомендации и критерии выбора. Внешние контракты ограничены источниками ниже.

Бизнес-задача

Разрешать конкурентный расход только в пределах доступных средств.

Требования

Отдельно учитывать booked, active holds и available. Чтение UI допускает явный stale marker. Spend требует текущей проверки.

Поток данных и владение состоянием

flowchart LR
 A["Wallet API"] --> B["Spend service"]
 B --> C["Ledger and holds DB"]
 C --> D["Balance projection"]
 D --> E["Reporting"]

Posted legs определяют booked. Holds уменьшают available. UI projection служит чтению.

Транзакционные границы

Под общей блокировкой позиции проверить лимит и создать hold. Capture атомарно уменьшает hold и пишет legs.

Порядок и идемпотентность

Capture и expiry конкурируют в одной области. Replay требует source revision и projection generation.

Нормальная последовательность

sequenceDiagram
 participant A as Wallet API
 participant B as Spend service
 participant C as Ledger and holds DB
 participant D as Balance projection
 A->>B: Request debit against available funds
 B->>C: Lock position and commit hold
 C-->>B: Return hold ID and new revision
 B->>D: Apply versioned balance update

Отказ и восстановление

sequenceDiagram
 participant B as Spend service
 participant C as Ledger and holds DB
 participant E as Recovery operator
 B->>C: Commit hold while projection event is delayed
 Note over B,C: Outcome becomes uncertain
 E->>C: Replay from ledger and active hold cut
 E->>B: Resume from verified boundary

Два запроса могут увидеть одинаковый старый available. Повторить проверку под lock. После потери view восстановить позиции из истории.

Сверка

Пересчитать booked и holds на одном cut. Сверить остатки частично captured holds.

Гонка expiry и capture. Под одним guard прочитайте hold state и остаток. Если expiry первым зафиксировал release, поздний capture переводится в exception с проверкой PSP outcome. Если capture первым провёл сумму, expiry освобождает только оставшийся резерв. Rebuild использует snapshot ledger и hold state на одном cut. Теневая проекция не должна принимать live updates без generation fence.

Наблюдаемость

Старые holds, negative available, lag и mismatch.

Безопасность и применимость требований

Изолировать tenant и account. Аудировать инициатора release.

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

Синхронная позиция ускоряет guard ценой contention. Async view масштабирует чтение.

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

Зачем освобождать hold при capture? Иначе available дважды учитывает один расход.

Первичные источники