Данный проект является телеграм-ботом для локальных чатов. Бот выполнен на стеке:
- python version 3.11.0
- SQLAlchemy для взаимодействия с БД
- Alembic для реализации миграций в БД
- FastAPI как веб-фреймворк
- Pydantic как сериализатор и валидатор данных
- Opensensus как инструмент для телеметрии и трассировки
- пакет
main
- Центральный директорий приложения, который содержит настройки, конфигурации веб-фраймворка, celery- пакет
settings
- Содержит настройки приложения.- модуль init.py - Точка входа в настройки
- модуль default.py - Модуль, содержащий основные настройки приложения
database
Пакет содержит инструменты для упрощения и улучшения работы с ORM- модуль webserver.py - Центральная конфигурация и инициализация FastApi приложения
- пакет
- пакет tests - Тесты приложения
- пакет
alembic
- это центральный пакет для осуществления автогенерации миграций/миграций/отката миграций в БД. Подробнее можно почитать здесь про данный инструмент- пакет
versions
- пакет с миграциями файлов - модуль env.py - Конфигурационный модуль для миграций
- пакет
- пакет-приложение
my_app
- Это пакет-приложения сущностей. Созданная для примера. Здесь необходимо реализовывать модели, маршруты и бизнес-логику с сущностями бизнес-логики.- пакет
models
- пакет с модулями-классами сущностей БД - пакет
routes
- содержит маршруты для api приложения с определенной бизнес-логикой - пакет
schemas
- содержит схемы сериализации/десериализации бизнес-сущностей Pydantic
- пакет
- пакет-приложение
auth
- Пакет приложение сущностей с пользователями, авторизационными методами, способами аутентификации, реализации токенов OAuth2 by JWT utils
- стандартный пакет с прикладными утилитами- модуль base_client.py является абстрактным классом-родителей для всех http-клиентов (Скоро будет изменен. В процессе реализации по паттерну Фабрика)
- модуль custom_json_logger.py содержит классы-форматтеры логов для централизации логов в json формат
- модуль middlewares.py содержит перечень Middleware-обработчиков для запросов по HTTP в сервер. (Логгер запросов, например)
- модуль dependencies.py содержит классы и функции зависимостей для адресов сервиса (Примеси сессии БД, например)
- модуль structs.py здесь будут содержаться константные для проекта(но не для пакета с бизнес-сущностью) структуры для удобства использования
- модуль server.py запускает настроенный веб-сервер приложения
- папка
requirements
- папка с зависимостями проекта - файл tox.ini - Конфигурация для codestyle проекта
Настройка количества воркеров FastAPI, которые будут запущены в одном процессе:
import os
WORKERS_COUNT = int(os.getenv('WORKERS_COUNT', 1))
Настройка доступа к БД выглядит следующим образом:
import os
DATABASE_SETTINGS = {
'default': {
'database': os.getenv('DB_NAME', 'bread_bot'),
'user': os.getenv('DB_USER', 'bread_bot'),
'password': os.getenv('DB_PASSWORD', 'bread_bot'),
'host': os.getenv('DB_HOST', '127.0.0.1'),
'port': os.getenv('DB_PORT', '5432'),
}
}
SQLAlchemy сама организует, каким количеством пулов подключений оперировать. Необходимо приложению задавать настройку, какой максимум возможно поддерживать по подключениям:
import os
DB_MAX_POOL = int(os.getenv('DB_MAX_POOL', 20))
Внимание: Это общее количество воркеров на всё приложение и на все воркеры. То есть, каждому воркеру будет выделена часть сессий, а не все общее количество. Иначе говоря в коде ниже каждому из 10ти воркеров будет предъявлено по 5 рабочих сессий БД:
import math
WORKERS_COUNT = 10
DB_MAX_POOL = 50
DB_POOL_SIZE = max(math.ceil(DB_MAX_POOL / WORKERS_COUNT), 1)
Также, если есть необходимость, то можно заниматься ограничением сессий с помощью pgbouncer. Файл настройки pgbouncer: pgbouncer.ini
Необходимо указывать все используемые приложения в проекте (как в django)
APP_MODULES = [
'my_app',
'auth',
]
FastAPI использует в качестве веб-сервера uvicorn. Есть несколько вариантов запуска приложения:
uvicorn bread_bot.main.webserver:app
python server.py
Не секрет, что fastapi умеет автодокументировать в swagger, redoc, openapi.json все маршруты и точки входа. Поэтому мой совет как разработчика тщательно описывать схемы Pydantic для удобства и читабельности проекта. Желательно с кейсами использования. Все можно найти в официальной спецификации фреймворка.
Реализован CRUDMixin для оперирования простыми командами как get, filter, first, create, update, итд итп. Также асинхронные аналоги данных методов. Расширять данную модель можно до бесконечности
Самая главная зависимость - это poetry
pip install poetry
Далее оперируется вся работа с зависимостями через него:
poetry add requests
poetry add pytest --dev
poetry install
poetry install --only main
Для начала везде, где Вы видите слово bread_bot
- тут может оказаться наименование вашего микросервиса. Ну логично,
да?
Необходимо установить все зависимости в проекте:
pip install poetry && poetry install
Представьте на секунду, что вы уже поставили PostgreSQL. И теперь нужно создать БД с пользователем и паролем:
CREATE DATABASE bread_bot;
CREATE ROLE bread_bot with LOGIN PASSWORD 'my_password';
GRANT ALL PRIVILEGES ON DATABASE bread_bot TO bread_bot;
GRANT USAGE, CREATE ON SCHEMA public TO bread_bot; -- Начиная с Postgresql 15 GRANT ALL PRIVILEGES ON DATABASE не даёт пользователю прав на public схему
Миграция схемы баз данных
alembic upgrade head
Откат миграции базы данных
alembic downgrade -1
Авто-генерация схемы базы данных
alembic revision --autogenerate -m 'my migration message'
Применение схемы для procrastinate в БД
procrastinate --app=bread_bot.main.procrastinate.app schema --apply
Запуск воркера procrastinate
procrastinate --verbose --app=bread_bot.main.procrastinate.app worker --concurrency=30
Запускаем локально веб-сервер
uvicorn bread_bot.main.webserver:app --reload
или так:
python server.py
Запустить проверку codestyle проекта (А эта проверка будет работать и при CI)
black ./
Запустить тесты:
pytest bread_bot/tests
Запустить тесты в docker:
docker build -f ci/Dockerfile.tests -t bread_bot:tests . && docker run bread_bot:tests poetry run pytest bread_bot
Запустить создания данных по покрытию тестами
coverage run -m pytest bread_bot/tests
Запустить вывод отчета по покрытию тестами
coverage report -m
Запустить вывод отчета в html формате
coverage html
Удалить данные отчета
coverage erase
Можно использовать последовательность:
coverage erase && coverage run pytest bread_bot/tests && coverage html
Функциональность бота описана в About.md