Приложение представляет из себя сервис, который на GET запрос по адресу /flights/<id:int>
возвращает из исходного .csv-файла информацию о полёте в JSON-формате типа:
{
"arrival_time": "1115",
"departure_time": "2010",
"number": "SU-275"
}
Названия полей взяты из названия столбоцов исходной .csv-таблицы:
Id,Origin,Destination,DepartureDate,DepartureTime,ArrivalDate,ArrivalTime,Number
1,SVO,BKK,20210701,2010,20210702,1115,SU-275
.
├── app
│ ├── Dockerfile
│ └── srcs
│ ├── app.py
│ ├── db.py
│ ├── flight_class.py
│ ├── flights.csv
│ ├── main.py
│ ├── requirements.txt
│ └── uwsgi.ini
├── docker-compose.yml
└── .env
- Склонировать репозиторий
git clone https://github.com/r-egorov/aviasales-intern
-
Поместить .csv-файл в директорию ./app/srcs
-
Указать название .csv-файла в файле .env под переменной
CSV_FILE
. -
Поднимаем сеть контейнеров с помощью docker-compose
docker-compose up -d
- Функционал можно проверить, отправляя запросы на адрес хоста, на котором поднят сервис.
В качестве языка программирования я выбрал Python, потому что мне с ним комфортно работать.
Для создания веб-приложения я выбрал фреймворк Flask, потому что:
- он лёгкий в освоении;
- в нем отсутвуют тяжёлые сериализаторы, которые для выполнения задания не нужны
Для чтения и парсинга .csv-файла используется стандартная библиотека csv.
Во время чтения файла данные записываются в PostgreSQL базу данных с помощью SQLAlchemy. С данной ORM я работал впервые. Оказалось, очень удобно.
В качестве продакшен-сервера я выбрал uWSGI (мне посоветовал его Flask, который предупреждает, что просто запускать скрипт в продакшене — нехорошо).
Разворачиваю приложение с помощью docker-compose, поднимая два контейнера:
- PostgreSQL с томом, в котором сохраняется база данных. Данный контейнер не имеет внешних портов.
- uWSGI+nginx. У данного контейнера открыт внешний порт 80, на который и поступают запросы. С базой данный он общается по внутренней сети docker network.
Конечно же, главная проблема — разворачивание приложения. Сначала я поделил инфраструктуру на три сервиса: nginx и uWSGI были в разных контейнерах. Они даже общались между собой, но сгенерированный JSON не доходил до источника запроса. В итоге я узнал, что для этих двух сервисов есть популярное готовое решение.
Перед написанием кода основной проблемой был выбор подхода: каким образом читать файл?
- Если он небольшого размера, то его можно прочитать в оперативную память и хранить в каком-нибудь словаре или массиве классов.
- Если большого, то тогда надо использовать БД. К тому же, это позволит сохранять данные между запусками приложения.
Так как в условии не указано, нужно ли валидировать данные, я их не валидирую. Но я проверяю строки .csv-файла на вхождение в мою БД по ID-номеру. Таким образом, между запусками сервиса файлы можно поменять, а в базе данных как останутся предыдущие данные, так и появятся новые без создания дубликатов.
Спасибо за интересное задание!