Задание: ТЗ
От клиента на сервер приходит http-запрос на транзакцию (пополнение / списание {перевод между счетами - не реализовано в силу сроков}).
Предполагается, что транзакция может исполняться продолжительное время, поэтому запросы необходимо обрабатывать асинхронно:
-
Осуществляется валидация входных данных http-запроса. При успешной валидации данные о запрашиваемой транзакции кладутся в БД со статусом
open
и после этого клиент получает http-код ответа202 Accepted
(запрос принят на обработку). При неуспешной валидации клиенту отдаётся http-код ответа422
. Eсли не удалось добавить данные о транзакции в БД и при прочих ошибках сервера клиенту отдается http-код ответа500 Internal server error
. -
В фоне для каждого пользователя в своей горутине данные о транзакциях извлекаются из БД в порядке добавления и выполняются. При успешном выаполнении транзакции её статус изменяется на
closed
, в противном случае наrejected
(На этом моменте можно при помощи отдельного микросервиса оповещать клиента условно по электронной почте о принятии/отклонении транзакции. -
Если сервер падает - данные о транзакциях пользователей из БД не исчезают; при поднятии сервера автоматически запускается их дальнейшая обработка.
- Для роутинга: https://github.com/julienschmidt/httprouter
- Для чтения конфига: https://github.com/ilyakaznacheev/cleanenv
- Для работы с Postgres: https://github.com/jackc/pgx
- Для работы с миграциями: github.com/golang-migrate/migrate/v4
- Для валидации данных запросов: github.com/go-playground/validator/v10
Хранение и работа с деньгами в БД осуществляю в типа bigint
, т.к.:
- Нет плавающей точки — меньше неточностей
- Можно производить стандартные математические операции и не бояться, что потеряются где-то копейки
- В международном стандарте денежных единиц видно, что число знаков после запятой у них может быть разное. А значит для простоты разработки все стоит хранить в минимальной дробной денежной единице валюты, осущеставляя конвертацию при выводе
git clone https://github.com/aakosarev/transaction-system
docker-compose up
POST http://localhost:8181/user/new
Request Body:
{
"name":"Test Name"
}
Response Status Code 200:
{
"user_id": "7d710c24-f737-4284-96b9-41d75a9d83ca"
}
GET http://localhost:8181/user/{uuid}
Response Status Code 200:
{
"id": "7d710c24-f737-4284-96b9-41d75a9d83ca",
"name": "test_2",
"balance": 0
}
POST http://localhost:8181/user/transaction
Request Body:
{
"user_id":"7d710c24-f737-4284-96b9-41d75a9d83ca",
"amount":200,
"transaction_type":"replenishment"
}
replenishment
- пополнение; write-off
- списание;
Response Status Code 202:
{
"message": "The transaction is queued"
}
- При постановки транзакции в очередь в столбце
tr_status
будет значениеopen
- После успешного выполнения транзакции в столбце
tr_status
будет значениеclosed
- При отклонении транзакции в столбце
tr_status
будет значениеrejected