Контекст
Travel-продукту нужны не отдельные выгрузки, а собственная рабочая база: экскурсии, гиды, города, расписания и отзывы должны быть связаны между собой и регулярно обновляться. Эти данные используются в витринах, фильтрах, аналитике и внутренних процессах.
Полная перезагрузка при каждом обновлении создает тысячи лишних запросов, увеличивает время синхронизации и быстрее упирается в ограничения партнерского API. При этом сбой на одном типе данных не должен заставлять начинать весь процесс заново.
Бизнес-задача
Нужно было построить управляемый сервис автоматического сбора и актуализации данных Tripster в PostgreSQL. Он должен поддерживать большой объем записей, продолжать работу после частичных сбоев и показывать, какие данные еще ждут обновления.
- Первично собрать связанные справочники и контент.
- Обновлять только изменившиеся сущности.
- Не терять задачи при ограничениях API и остановках.
- Контролировать расхождения между источником и базой.
- Оставить критические решения и live-запуски человеку.
Что было реализовано
Создан Python CLI-сервис, который получает данные из партнерского API, валидирует ответы через Pydantic, нормализует различающиеся форматы и сохраняет сущности в PostgreSQL через SQLAlchemy. Отдельные команды покрывают первичную загрузку, инкрементальные обновления, обработку очереди, проверку расхождений и обновление расписаний.
Основной рабочий режим - не повторная полная выгрузка, а инкрементальный цикл. Сервис хранит курсоры, находит изменившиеся экскурсии и ставит связанные расписания и отзывы в устойчивую очередь. Reconcile-проход проверяет легкие списочные данные и добавляет в очередь то, что могло разойтись.
- Страны, города, гиды, экскурсии, расписания и отзывы в связанной схеме.
- Full, incremental, reconcile и backlog-команды для разных режимов работы.
- Курсоры обновления и журнал запусков.
- Повторяемые upsert-операции вместо дублирования записей.
- Равномерный темп запросов, обработка 429 и пауза перед продолжением.
- Проверка целостности и ограниченные live-аудиты перед рабочими запусками.
Как решения помогают бизнесу
| Решение | Задача | Польза |
|---|---|---|
| Инкрементальная синхронизация | Не повторяет полную выгрузку ради небольших изменений. | Меньше запросов и короче регулярный цикл обновления. |
| Курсоры по типам данных | Фиксируют подтвержденную точку продолжения. | Следующий запуск продолжает работу с понятного состояния. |
| Устойчивая backlog-очередь | Сохраняет связанные задачи на расписания и отзывы. | Большой объем обрабатывается управляемыми пакетами. |
| Reconcile-проверка | Находит расхождения без массовых detail-запросов. | База актуализируется экономнее и предсказуемее. |
| Валидация и нормализация | Приводит разные ответы API к устойчивой модели. | Ошибки формата обнаруживаются до записи в рабочие таблицы. |
| Идемпотентные upsert-операции | Обновляют существующие записи по стабильным ключам. | Повторный запуск не размножает сущности. |
| Контроль темпа и 429 | Не допускает резких всплесков запросов и корректно реагирует на лимиты. | Синхронизация бережнее работает с партнерским API. |
| Human-in-the-Loop процесс | Отделяет AI-генерацию от решений с операционным риском. | Архитектура, live-аудиты и рабочие запуски проходят человеческую проверку. |
Почему выбрана такая архитектура
Контур актуализации travel-данных
Автоматика поддерживает рабочую базу, а человек контролирует архитектуру, live-проверки и запуск изменений.
- Партнерский API
- Проверка и нормализация
- PostgreSQL
- Incremental, backlog и reconcile
- Актуальная рабочая база
- Human-in-the-Loop контроль
Полная синхронизация - стартовый и аварийный режим
Полный проход нужен для первичного наполнения или контролируемого восстановления. Регулярная актуализация строится на incremental, backlog и reconcile, чтобы не создавать тысячи повторных запросов.
Очередь отделяет обнаружение изменений от тяжелых обновлений
Изменившаяся экскурсия быстро попадает в базу, а связанные расписания и отзывы обновляются пакетами. Размер пакета можно согласовать с доступным окном и лимитами API.
Reconcile закрывает разрывы между курсорами и источником
Легкий списочный проход сравнивает состояние источника с базой и ставит отличающиеся записи в очередь. Это страховка от пропущенных изменений без постоянной полной выгрузки.
Ограничения источника учитываются явно
Live-аудит показал, что фильтр обновления для справочника гидов нельзя считать надежным. Поэтому сервис не обещает ложный incremental для этого раздела: режим его обновления выбирается отдельно и проверяется контролируемыми запусками.
AI создает, человек отвечает за выпуск изменений
Весь код и документация проекта сгенерированы AI. Human-in-the-Loop оставляет ответственность у человека: он формулирует требования, проверяет архитектуру и код, запускает ограниченные live-аудиты, разбирает инциденты и подтверждает изменения перед рабочими синхронизациями.
Результат
В рабочей базе собрано 30 503 экскурсии, 8 516 гидов, 30 189 расписаний и 953 868 отзывов. Дополнительно связаны 123 страны и 937 городов. Это не демонстрационная выборка, а объем, на котором проверялись схема, upsert-операции и процесс обновления.
Регулярный процесс обновляет изменившиеся экскурсии, сохраняет связанные задачи в backlog и отдельными пакетами актуализирует расписания и отзывы. Reconcile помогает обнаружить расхождения, а журнал запусков и курсоры делают состояние процесса проверяемым.
Актуальность зависит от расписания запусков и скорости обработки backlog - это не обещание real-time. Часть редко используемых полей сохраняется в raw_data, а изменения схемы сейчас выполняются через ensure_schema, без Alembic-миграций. Эти ограничения зафиксированы и учитываются при эксплуатации.
Где это применимо
Подход подходит продуктам, которым нужен собственный актуализируемый слой данных поверх внешнего каталога.
- Туристические витрины и каталоги экскурсий.
- Агрегаторы предложений из нескольких источников.
- Региональные и тематические travel-проекты.
- Внутренняя аналитика контента, гидов и отзывов.
- Подготовка данных для поиска и рекомендаций.
- Интеграционные слои для CRM и back-office систем.
Вывод
Главный результат проекта - не разовая выгрузка, а управляемая актуализация большого travel-каталога. Инкрементальные проходы, backlog и reconcile снижают нагрузку на источник и позволяют видеть незавершенную работу.
AI ускорил создание всего кода и документации, но не получил право самостоятельно принимать рискованные решения. Human-in-the-Loop связал скорость генерации с инженерной проверкой и ответственным запуском.