Написан в качестве тестового задания
Представляет собой реализованный на FastAPI основной сервер airflow, принимающий запросы от клиента, отправляющий запросы провайдерам, принимающий и обрабатывающий в асинхронном режиме ответы, их агрегацию и предоставление клиенту.
Хранение данных запросов осуществляется в MongoDB (посчитал, что для этой задачи такой тип базы данных подходит намного лучше, чем реляционные). Для доступа к БД используется асинхронный драйвер Motor
Dicslaimer Для меня это был первый опыт работы с FastAPI и MongoDB, мой основной фреймворк - это Django, а базы данных - реляционные SQL. Но они, на мой взгляд, плохо соответствовали ТЗ, а сам сервис выглядел сравнительно несложной задачей, поэтому на нем я опробовал новые для себя технологии. Управился меньше чем за два рабочих дня - думаю, дальше будет еще быстрее.
Провайдеров имитируют два самостоятельных сервера на FastAPI. По POST-запросу на /search
они с задержкой в 30 и 60 секунд возвращают xml-файлы со списком предложений.
На airflow реализован парсинг предложенных xml-файлов - для каждого провайдера написана отдельная функция. Сравнивая "сырой" xml-код с готовыми результатами парсинга в формате json, обнаружил, что у обоих провайдеров не определяется статус билета refundable
, поэтому он по дефолту устанавливается на null
.
Также у провайдера b нет составных рейсов, поэтому невозможно было определить и предусмотреть этот вариант в коде для парсинга.
У провайдера b реализовал определение модели самолета - нашел в интернете и скачал таблицу соответствия кодов IATA (которые есть в xml) и названий.
Для запуска необходим Docker.
Скачайте код на ПК и запустите сборку и скачивание образов командой:
docker-compose up --build
Будут запущены 4 контейнера - с базой данных MongoDB, контейнер с airflow и 2 контейнера с провайдерами.
Дополнительно в файле docker-compose.yml
при помощи переменных окружения можно задать параметры работы сервера и провайдеров, указать данные для доступа к БД.
Airflow, в соответствии с техзаданием, работает на порту 9000
. Для проверки API можно использовать swagger-интерфейс по адресу http://127.0.0.1:9000/docs
По POST-запросу будет создана запись в БД с уникальным search_id, этот search_id будет сразу же возвращен клиенту, а параллельно в асинхронном режиме запускаются два запроса к провайдерам. После выполнения каждого запрсоа и парсинга результатов данные добавляются в БД к ранее созданной записи. После выполнения обоих запросов статус поиска меняется с PENDING
на COMPLETED
По GET-запросу с указание соответствующего search_id и кода валюты предоставляется список предложений в соответствии с требуемым форматом, отсортированнный по цене в порядке возрастания.
Updated:
Добавил кэширование результатов запроса (в оперативную память для простоты, но можно и в другие хранилища). В кэш сохраняются отсортированные результаты поиска, если его статус COMPLETED
. При использвоании кэша не происходит обращений ни к БД, ни к серверам поиска, а также не производится повторная конвертация валют и сортировка, что значительно улучшает быстродействие.
Курсы валют обновляются при помощи запроса к серверу Нацбанка Казахстана. Обновление происходит при старте сервера, а также в 12 часов каждого дня (в качестве планировщика используется Async APScheduler). Курсы рубля, доллара и евро к тенге хранятся в БД в документе с id
rates
Так получилось, что у меня почти нет опыта в написании тестов. Тем не менее, в соответствии с техзаданием реализовал несколько тестов при помощи асинхронного pytest
. Они проверяют работу endpoint-ов сервера и парсинг. Уверен, что в дальнейшем разберусь и буду писать тесты намного лучше.
Запустить тесты можно командой
docker-compose run --rm airflow pytest
Выполнять тесты следует при работающих провайдерах и контейнере с БД.