Перейти к содержанию

Готовность и передача учебного FastAPI-проекта

Оглавление серии

Последний снимок «Окна» соединяет каталог, DTO, базу, конкурентный запрет, ключ повторения, личные операции и outbox. Передача такого проекта требует объяснить, что подготовлено и что ещё не подтверждено исполнением. Результат главы — договор собственной учебной среды, маршрут readiness и закрытие Engine при штатном завершении. Публикация и подключение настоящих пользователей в этой серии не выполняются.

Сначала различим четыре факта. Исходники написаны; первичная документация прочитана; зависимости ещё не разрешены; сценарии приложения не запускались. Наличие ZIP подтверждает набор файлов, но не их фактическую совместимость в конкретной среде. Поэтому requirements.txt содержит диапазоны семейств API и прямое пояснение об отсутствии lockfile. Читатель должен получить точные версии в собственной среде и сохранить их после самостоятельной проверки, не приписывая архиву такой результат заранее.

Процесс и ресурс подключения

Engine создаётся отдельно от Session одного запроса. Он управляет пулом подключений и живёт на протяжении процесса. Lifespan с asynccontextmanager охватывает жизненный цикл приложения. После yield, в finally, вызывается engine.dispose. Этот шаг освобождает ресурсы пула при штатном завершении. Он не гарантирует исполнение при принудительном уничтожении процесса или отказе машины. Договор завершения всегда ограничен тем, что программа получила возможность выполнить cleanup.

Почему lifespan асинхронный, а маршруты базы обычные def? Мы используем синхронный SQLAlchemy и драйвер Psycopg; блокирующая работа маршрутов объявлена синхронно. Контекст жизненного цикла относится к интерфейсу FastAPI и не означает, что вся база стала асинхронной. Нельзя просто заменить def на async def вокруг прежних синхронных запросов и считать, что они перестали блокировать поток. Для иного профиля потребовалась бы согласованная смена engine, сессий и драйвера.

Миграции не запускаются в lifespan. У нескольких рабочих процессов одновременное изменение схемы при старте усложнило бы готовность и диагностику. В показанном договоре reader применяет migrate.py отдельным шагом до запуска API в собственной учебной базе. Advisory lock runner согласовывает его экземпляры, но не делает старт приложения универсальным процессом релиза. История схемы и жизнь HTTP-процесса имеют разные обязанности и разные причины отказа.

Полные файлы шага

Показанные файлы полностью совпадают с выбранным состоянием архива. Остальные согласованные файлы находятся в examples/fastapi-booking-lab/lesson-16/.

RELEASE.md

# Передача учебного проекта Окно

Статус примеров: not_run. Пакеты не устанавливались, SQL не выполнялся.
Документационный профиль: Python 3.14; Pydantic 2; SQLAlchemy 2.0;
Psycopg 3; PostgreSQL 18; FastAPI с поддержкой Pydantic 2.
Диапазоны requirements.txt не являются проверенной совместимостью.
После самостоятельного разрешения зависимостей сохраните точный lockfile.

1. Используйте новую собственную учебную базу, не рабочие данные.
2. Перед запуском API примените migrate.py один раз отдельным шагом.
3. Миграция 002 требует btree_gist и не пройдёт при старых пересечениях.
4. Включайте demo_enabled только на localhost, задавайте два разных токена.
5. Запускайте uvicorn main:app --host 127.0.0.1 --port 8000 из этого каталога.
6. /ready проверяет доступ к базе и имена миграций, не внешнюю доставку.
7. drain.py обрабатывает одно событие и пишет в stdout; это учебный получатель.
8. Для повторной доставки используйте event_id; ровно один раз не обещается.
9. Перед публичной эксплуатацией замените весь demo provider настоящим входом.
10. Остановка закрывает engine; пропущенный сигнал не даёт гарантий cleanup.

Ожидаемые сценарии самостоятельной проверки описаны в статьях курса.
Этот пакет не был выпущен, развернут или подключён к аккаунтам пользователя.

Ожидаемый результат

Это ожидаемый договор для самостоятельного исследования; пример не выполнялся.

/ready при доступной базе и пяти известных миграциях → {"ready":true}
/ready при недоступной базе или неполной истории → 503
Штатное завершение lifespan → engine.dispose()

Что означает /ready

Readiness отвечает, может ли текущий процесс работать с нужной базой и известной историей схемы. /ready читает schema_migrations и требует пять имён файлов. Если база недоступна или нужные имена отсутствуют, возвращается 503. Успех возвращает ready=true. Маршрут не показывает адрес подключения и исходное исключение клиенту. Так публичный сигнал остаётся компактным, а внутренние сведения не превращаются в ответ о готовности.

Проверка имён имеет предел. Она не сравнивает фактические определения ограничений с желаемым SQL и не доказывает, что администратор не изменял таблицу вне runner. Проверку checksum выполняет migrate.py, а наш readiness предполагает соблюдение процесса миграций. Это важный договор доверия к истории. Если проекту нужна более строгая диагностика схемы, её нужно проектировать отдельно, а не обещать её из наличия одного SELECT имён.

/ready также не означает доставку всех событий outbox. Pending-записи могут ожидать собственного обработчика, даже если API готов сохранять новые брони. Получатель этого курса — stdout, не внешний почтовый сервис. Поэтому положительный readiness нельзя показывать пользователю как подтверждение отправленного уведомления. Для реального сопровождения разные компоненты требуют разных сигналов. Здесь один маршрут отвечает только за работу API с ожидаемой учебной схемой.

Передача полного состояния

Выберите lesson-16 целиком. Файлы main.py, schemas.py, service.py, auth.py, db.py и SQL-история согласованы между собой. Смешивание main.py последней главы с ранними моделями приведёт к отсутствующим именам и другому договору, а не к допустимой экономии файлов. Каждый снимок автономен для изучения своей ступени, но сохранённая собственная база может продолжать историю миграций, если предыдущие файлы не переписывались и её вымышленные данные соответствуют новым ограничениям.

Нижняя граница FastAPI в requirements не является сертификацией всех выпусков между ней и единицей. Так же Psycopg binary зависит от платформы установки, а Python выбран по документированному профилю 3.14. Мы не создавали виртуальное окружение и не устанавливали пакеты. Перед действительной работой читатель самостоятельно разрешает зависимости, сохраняет результат и выполняет сценарии на своей машине. Статья честно отделяет предполагаемый API-контракт от фактически наблюдённой совместимости.

Учебный вход остаётся выключенным по умолчанию. Включение двух локальных токенов подходит для разбора собственности в собственном профиле, но не является релизом production-аутентификации. Настоящий запуск для внешних людей потребует другой источник личности и правила эксплуатации. Это не мешает изучить готовые предметные операции: они уже получают владельца server-side и проверяют его до чтения и отмены. Смене провайдера не следует уничтожать этот слой правил.

Ожидаемые самостоятельные сценарии перечислены в RELEASE.md: каталог, неизвестный ресурс, нормализация времени, конкурентное пересечение, идемпотентный повтор, отказ чужому владельцу, отмена, продолжение списка и оставшееся pending-событие. Автор их не выполнял; формулировки результата остаются ожидаемыми. Полный архив предназначен для локального изучения, а не для автоматической загрузки на хостинг. Мы получили связанный проект с объяснёнными границами: HTTP задаёт договор, сервис фиксирует операцию, PostgreSQL удерживает инвариант, outbox сохраняет последующий факт.

Передача включает происхождение ограничений

RELEASE.md объясняет, откуда берутся главные свойства проекта. Запрет пересечения обеспечивает конкретная SQL-миграция, принадлежность карточки — условие владельца, повтор намерения — таблица idempotency и критический участок сервиса. Если передать только HTTP-файл, получатель может видеть знакомые адреса, но не получить эти гарантии. Поэтому архив содержит полные состояния и историю, а курс связывает каждый механизм с отдельным результатом.

Статус not_run также относится ко всем ступеням, а не только к последней. Ранний компактный пример не объявляется проверенным лишь потому, что в нём меньше строк. При самостоятельном исследовании reader может получить собственные наблюдения, записать точные версии и результаты, но это будет новое свидетельство. Авторский пакет сохраняет честную границу подготовки. Такая передача делает работу reviewable: другой человек видит готовый материал, ожидаемый договор, файлы и конкретные неисполненные действия, не угадывая, какие части подтверждены реальным запуском и какие следуют из документации.

Документация и исходники

Механизмы главы сверены с первичными источниками: документация 1, документация 2, документация 3. Полный архив «Окна» содержит все шестнадцать состояний. Пакеты, приложение и миграции не запускались.