2015 подписчиков
👣 Тестовое задание Billing
Микросервис баланса пользователей.
Приложение хранит в себе идентификаторы пользователей и их баланс. Взаимодействие с ним осуществляется исключительно с помощью брокера очередей.
По требованию внешней системы, микросервис может выполнить одну из следующих операций со счетом пользователя:
▪Списание
▪Зачисление
▪Перевод от пользователя к пользователю (будет плюсом, но не обязательно)
Блокирование с последующим списанием или разблокированием. Заблокированные средства недоступны для использования. Блокировка означает что некая операция находится на авторизации и ждет какого-то внешнего подтверждения, ее можно впоследствии подтвердить или отклонить
После проведения любой из этих операций генерируется событие-ответ в одну из очередей.
Основные требования к воркерам:
▪Код воркеров должен безопасно выполняться параллельно в разных процессах
▪Воркеры могут запускаться одновременно в любом числе экземпляров и выполняться произвольное время
▪Все операции должны обрабатываться корректно, без двойных списаний, отрицательный баланс не допускается
В пояснительной записке к выполненному заданию необходимо указать перечень используемых инструментов и технологий, способ развертки приложения, общий механизм работы (интерфейсы ввода/вывода)
Будет плюсом покрытие кода юнит-тестами.
Требования к окружению: Язык программирования: Go Можно использовать: любые фреймворки, реляционные БД для хранения баланса, брокеры очередей, key-value хранилища.
Особенности
▪Сервис поддерживает обработку паники.
▪Сервис поддерживает создание и хранение журнала выполненных операций.
▪Сервис поддерживает полную консистентность данных
▪Сервис поддерживает graceful shutdown.
▪Сервис НЕ поддерживает Heartbeat для базы данных.
На момент старта сервиса, должен быть уже запущен NATS.
Используемые компоненты
▪MySQL - для хранения данных
▪NATS - брокер сообщений
API
Ответ на каждый запрос включает статус его выполнения: 0. Операция прошла успешно
1.Неизвестная ошибка
2.Операция устарела
3.Для выполнения операции недостаточно средств
4.Аккаунт не найден
Credit
Списание средств со счета.
Subject/Queue - bank.credit
Request: {"uid":1,"account":1,"amount":10}
Response: {"status":1}
Debit
Зачисление средств на счет.
Subject/Queue - bank.debit
Request: {"uid":1,"account":1,"amount":10}
Response: {"status":1}
Transfer
Перевод средст с одного счета на другой.
Subject/Queue - bank.transfer
Request: {"uid":1,"src":1,"dst":2,"amount":10}
Response: {"status":1}
Acquire
Блокировка средств.
Subject/Queue - bank.acquire
Request: {"uid":1,"account":1,"amount":10}
Response: {"status":1}
Commit
Подтверждение блокированных средств.
Subject/Queue - bank.commit
Request: {"uid":1,"account":1}
Response: {"status":1}
Rollback
Возврат блокированных средств.
Subject/Queue - bank.rollback
Request: {"uid":1,"account":1}
Response: {"status":1}
Принцип работы
Для достижения идемпотентности, в каждой операции должен присутствовать ее уникальный номер uid. Каждая операция, при записи в базу данных, регистрирует действие в таблице истории. При существовании одинакового ключа (work_index) происходит ошибка базы данных, которую мы трактуем, как устаревание операции (идемпотентный случай). Аналогчно работает и таблица активов.
В сервисе используется пакет доступа к базе данных github.com/adverax/echo/database/sql, который позволяет эмулировать вложенные транзакции, а также хранить область видимости в контексте. Это позволяет нам осуществлять декомпозицию функционала работы с базой на отдельные функции, не заботясь о контексте выполнения запросов.
Для каждой таблицы используется собственный менеджер.
2 минуты
14 февраля 2023