GithubHelp home page GithubHelp logo

test-betting-software's Introduction

Задание

Задание пока что не прикрепляю, чтобы случайно не распространить решение.

Размышления по поводу задания

Я не согласен со следующим высказыванием в задании:

События как таковые хранить не требуется, мы будем работать только с их идентификаторами.

Если события будут храниться в ставках, то очень просто получить несогласованное состояние. Например, событие N завершилось и на это событие было пару ставок. Вызван метод на обновлении статуса события N, в этот момент меняются статусы у ставок. До завершения метода на обновления статуса вызывается метод на создание еще одной ставки на событие N. В итоге, пара ставок имеют конечные статусы (выиграла, проиграла), а одна ставка создалась позднее и имеет неконечный статус (ещё не сыграла). Я предлагаю работать с событием, как с обычной сущностью и добавить метод создания, что дополнительно упростит архитектуру и понимание предметной области. Я вижу процесс следующим образом:

  1. Создание события;
  2. Создание ставок на события;
  3. Завершение события, сменой статуса;

Так же я предлагаю изменить метод создания ставки POST /bets. Метод работает с деньгами, поэтому важно, чтобы из-за проблем (например, сетевых) не случилось создание двух одинаковых ставок. Я предлагаю реализовать идемпотентность следующим образом: пусть клиент на своей стороне создает идентификатор ставки (UUID) и отправляет его в запрос. В таком случае, приложение просто убедится в том, что такая ставка уже есть и не будет создавать ее повторно. Так же не требуется прикреплять в ответ идентификатор ставки, потому что клиент и так его знает.


Дополнительные нефункциональные требования:

  1. За какое время запрос должен быть обработан на серверной стороне?

    запрос должен быть обработан не более чем за 100мс.

  2. Какое количество событий и ставок планируется хранить?

    кол-во событий — порядка 10000.

Стек

Библиотеки и технологии подобраны таким образом, чтобы продемонстрировать знания требующиеся в вакансии.

  • Python 3.11
    • FastAPI
    • SQLAlchemy ORM
    • Alembic
    • structlog
    • pytest
  • PostgreSQL
  • Docker

Реализовано

  • API
  • Миграции для базы данных
  • Логирование
  • Тестирование
  • Code-style
  • Сборка приложения

Bet Maker

Сервис позволяет создавать события, на которые можно делать ставки, и в дальнейшем отслеживать их статус.

Событие (Event)

На события можно делать ставки. Событие может находиться в одном из 3 статусов:

  • Ещё не сыграла (PENDING);
  • Выиграла (WIN);
  • Проиграла (LOSE);

Сделать ставку не получиться, если событие находиться в одном из конечных статусов (WIN, LOSE).

Ставка (Bet)

Можно делать сколь угодно ставок на одно и то же событие. Важно, чтобы событие было в неконечном статусе (WIN, LOSE).

Сумма ставки обязательно должна быть положительным числом.

Структура

Интерфейс приложения (API) и само приложение (Bets) отделены, чтобы в будущем оставить возможность реализовать дополнительные интерфейсы.

Приложение разделено на слои (Domain, Application, Infrastructure). Такое разделение дает гибкость приложению, что положительно сказывается на разработке будущих компонентов. Так же такое разделение упрощает процесс тестирования, потому что сохраняется минимальна связанность компонентов.

Запуск

Dockerfile и docker-compose файлы лежат в директории deployment.

Для запуска нужно выполнить команду ниже:

docker compose --project-name test --file deployment/docker-compose.yml up

Важно! После того как база данных поднялась, требуется применить миграции.

Переменные окружения

Переменная окружения Описание Значение по умолчанию
DB_DATABASE Название базы данных bet-maker
DB_USER Имя пользователя базы данных test
DB_PASSWORD Пароль пользователя базы данных test
DB_PORT Порт базы данных 6432
APPLICATION_PORT Порт приложения 80

Миграции

Установить переменные окружения в терминале и выполнить скрипт для применения миграций.

В моем случае переменная DB_DSN была postgresql+asyncpg://test:test@localhost:6432/bet-maker.

export DB_DSN=<ПОДКЛЮЧЕНИЕ К БАЗЕ ДАННЫХ>
alembic upgrade head

API

Находится по адресу - http://localhost/.

Документация Swagger находится по адресу - http://localhost/docs.

EVENT

POST /events/

Создать событие. Данный метод является идемпотентным.

Тело запроса: Тело запроса:

{
  "event_id": "3fa85f64-5717-4562-b3fc-2c963f66afa5"
}
  • event_id - Идентификатор события в формате UUID.

Ответ:

  • В случае корректного создания вернется пустой ответ с HTTP статусом 201.
  • В случае некорректно заданного event_id вернется ответ с HTTP статусом 422 и описанием ошибки.

PUT /events/<event_id>

Изменить статус события.

Тело запроса: Тело запроса:

{
  "status": "WIN"
}
  • status - Возможен один из вариантов статуса WIN или LOSE.

Ответ:

  • В случае корректного запроса вернется пустой ответ с HTTP статусом 200.
  • В случае некорректно выбранного статуса status вернется ответ с HTTP статусом 422 и описанием ошибки.
  • В случае несуществующего события с event_id вернется ответ с HTTP статусом 404.

BET

POST /bets/

Сделать ставку. Данный метод является идемпотентным.

Тело запроса:

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa3",
  "event_id": "3fa85f64-5717-4562-b3fc-2c963f66afa5",
  "amount": 1.11
}
  • id - Идентификатор ставки в формате UUID.
  • event_id - Идентификатор события в формате UUID.
  • amount - Сумма ставки должна строго положительным числом с двумя знаками после запятой.

Ответ:

  • В случае корректного запроса вернется пустой ответ с HTTP статусом 201.
  • Если выбранное событие не существует, то вернется ответ с HTTP статусом 400 и кодом ошибки - EVENT_NOT_FOUND.
  • Если выбранное событие имеет финальный статус, то вернется ответ с HTTP статусом 400 и кодом ошибки - EVENT_STATUS_ALREADY_IS_FINAL.
  • В случае некорректно заданного тела запроса вернется ответ с HTTP статусом 422 и описанием ошибки.

GET /bets/

Получить информацию о существующих ставках.

  • В случае корректного запроса вернется ответ с HTTP статусом 201. Тело ответа:
{
  "bets": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "amount": 0,
      "created_at": "2024-05-10T07:47:38.723Z",
      "event": {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "status": "PENDING",
        "created_at": "2024-05-10T07:47:38.723Z"
      }
    }
  ]
}
  • id - Идентификатор ставки в формате UUID.
  • amount - Сумма ставки должна строго положительным числом с двумя знаками после запятой.
  • created_at - Дата создания ставки.
  • event:id - Идентификатор события в формате UUID.
  • event:status - Возможен один из вариантов статуса WIN, LOSE, PENDING.
  • event:created_at - Дата создания события.

Локальное окружение

Подготовка локального окружения:

  1. Установка всех зависимостей
pip install -r requirements.txt
pip install -r requirements-test.txt
pip install -r requirements-dev.txt
  1. Установка pre-commit хуков
pre-commit install

Выполнение проверок перед каждым коммитом

Перед каждым git commit pre-commit выполняет следующие действия:

В случае неуспешного прохождения проверок коммит не будет создан.

Конфигурация pre-commit находится в файле .pre-commit-config.yaml.

Чтобы выполнить проверку вручную можно вызвать команду:

pre-commit run --all-files

Проверка code-style

Проверка code-style происходит с помощью утилиты Ruff. Конфигурация находится в pyproject.toml. Подробнее про настройку можно прочесть в документации Ruff.

Для запуска проверки code-style требуется выполнить команду:

ruff check .

Запуск тестов

Тесты написаны на базе фреймворка pytest. Конфигурация находится в pyproject.toml. Тесты расположены в директории tests.

Для запуска тестов требуется выполнить команду:

python -m pytest

test-betting-software's People

Contributors

n3rfy avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.