Найти тему
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 минуты