LedgerCore
Учёт по двойной записи: проводки, балансы и сторно. Повторная команда возвращает исходный результат, а конкурирующие списания блокируют счета до проверки остатка.
Весы двойной записи
Проводка кладёт гири на обе чаши: дебет и кредит. Штамп опускается, только когда коромысло в равновесии, а пробитый талон с тем же ключом второй раз не проходит.
Модель
В каждой транзакции две и больше проводки, и по каждой валюте дебет равен кредиту. Суммы хранятся целыми копейками в 64 битах, дробных денег в базе нет. Балансы выводятся из проводок, а история не редактируется: сторно — это новая транзакция с перевёрнутыми сторонами.
Запись
Каждый запрос несёт ключ идемпотентности. Повтор с тем же ключом и тем же телом возвращает исходную транзакцию, с другим телом — отказ. Затронутые счета блокируются в стабильном порядке, поэтому из двух одновременных списаний последнего рубля пройдёт только одно. Отложенные ограничения PostgreSQL проверяют весь набор проводок в момент коммита.
Технически
- Двойная запись с проверкой баланса по каждой валюте.
- Ключ идемпотентности с advisory-блокировкой PostgreSQL.
- Блокировка счетов в порядке UUID против гонок.
- Сторно только новой транзакцией, одно на исходную.
- Изменение и удаление проводок запрещены на уровне базы.