Comments 17
А вот в этом всём, меня смущает что logger синхронный, как быть?
Можно использовать polog в асинхронном режиме.
Спасибо за замечание, переделаю на aiologger
В целом сервис выглядит хорошо, но:
Не хватает тестов.
Не предусмотрены репликация / шардирование.
Что будет, если в процессе загрузки данных в файл выключится электричество на сервере? На диске окажется битый файл, а в БД о нем записей не будет. Со временем при постоянном пользовании сервисом такие файлы неизбежно будут возникать и накапливаться. Одно из возможных решений - писать в файл внутри транзакции БД. Но это порождает риск долгих транзакций, от которого можно избавиться, если хранить не файлы целиком, а чанки (также это может частично решить проблему с фрагментацией диска).
await request.content.read()
будто бы таки считывает файл в память полностью, после чего уже записывает на диск. То есть не соблюдается главная гарантия вашего сервиса - что он не держит файлы в памяти целиком.aiofiles
- немного сомнительная библиотека.Не вижу возможности параметризовать сервис при помощи переменных окружения.
Нет возможности запуска в контейнере.
Инициализация движка БД выглядит странно. Если по итогу все равно создается глобальная переменная, зачем это пихать в функцию?
Спасибо большое за развернутый комментарий. Почемуaiofiles
сомнительная библиотека? Какие предлагаете альтернативы?
Это обертка, насколько я помню, над тред-пулом. То есть реальной кооперативной многозадачности там нет, только ее видимость. Альтернатив, к сожалению, не знаю.
По п3. Решение довольно простое. Перед загрузкой файла делать некоторый черновик записи о файле со статусом pending. Загружать файл. Апдейтить запись на статус processed. А дальше в фоне подчищать все, что не в processed статусе и со старой временной меткой.
Это может быть опасно, поскольку неизвесно, сколько точно должна длиться загрузка. Лимитов на размер файлов тут нет, теоретически пользователь может из тайги по GPRS 100-гиговый рип "аватара 2" качать. А если автор запилит еще и возобновление загрузки после обрыва соединения, то вообще.
Можно периодически чекать не изменился ли размер файла с прошлой проверки и уже тогда грохать файл
Ещё раз спасибо за комментарии. Внёс исправления в проект:
добавил тесты
`await request.content.read()` заменил на `async for data in request.content.iter_any()`
библиотеку `aiofiles` заменил на `aiofile`
параметризовал сервис переменными окружения
добавил запуск проекта в docker'е
инициализацию движка БД перенес в область глобальной видимости модуля
заменил `logger` на `aiologger`
По оставшимся вопросам:
репликация / шардирование постановкой задачи не были предусмотрены. Заранее было оговорено, что сервис работает в рамках локальной сети заказчика и бэкап делается его силами.
Если в процессе загрузки данных в файл выключится электричество на сервере, то процесс придется начинать заново. Насколько я себе представляю, чтобы возобновить загрузку файла с определенного места нужно ещё научить клиента понимать, с какого места продолжить байтовый поток. Но клиент в данном кейсе давался уже "как есть". Чтобы избежать ссылок на битые файлы, сохранение данных о новом файле в БД сервиса происходит только после сохранения файла на диске.
При обрыве соединения клиент сможет докачивать только недостающие данные или будет грузить все по новой?
Асинхронный файловый api-сервис