Commit Graph

2 Commits

Author SHA1 Message Date
jze9
eb2dee9093 perf(ops): начинать листинг PMC после последней залитой статьи
All checks were successful
Deploy / test (push) Successful in 3m4s
Deploy / deploy (push) Successful in 29s
Первый прогон нового конвейера показал слабое место: листинг бакета шёл с
начала, и заливка часами перемалывала уже существующие статьи как дубли —
из 300 полученных 300 оказались дублями.

S3 умеет start-after, и стартовый ключ выводится прямо из базы: ext_id вида
`pmc:PMC10000000` соответствует ключу `PMC10000000.1`, бакет отдаётся
лексикографически. Теперь при отсутствии сохранённого токена (первый прогон
после ручных заливок) листинг начинается после максимального залитого.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 21:53:07 +05:00
jze9
26de1b9de1 refactor(ops): массовая заливка — в общий конвейер вместо отдельных скриптов
All checks were successful
Deploy / deploy (push) Successful in 2m28s
Deploy / test (push) Successful in 2m49s
Заливку Википедии и PMC я сделал отдельными скриптами мимо существующей
инфраструктуры: запуск руками через ssh, состояние в файле в /tmp, никакой
видимости. Результат предсказуем — за неделю обе умерли молча (обрыв базы на
20 008 статьях из 2 млн и таймаут сети на 85 тыс. из 100 тыс.), прогресс
потерялся, а узнали мы об этом через неделю. При том что рядом лежит готовый
механизм: parse_sources, прогоны со шкалой, журнал, кнопки, ретраи Celery.

Теперь это обычные типы источника — wikipedia_ru и pmc_bulk:

- заводятся и запускаются из админки, как OpenAlex или КиберЛенинка;
- показывают ту же шкалу, журнал и кнопку остановки;
- падение воркера больше не теряет прогресс: позиция продолжения хранится в
  parse_sources.resume_token (номер статьи в дампе / токен страницы бакета),
  повторный запуск берёт следующую порцию;
- укладываются в бюджет времени таска — заливка идёт порциями, а не одним
  многосуточным процессом.

Чего не хватало конвейеру для миллионов и что добавлено:
- парсеры отдают генератор, а не список: 2 млн статей в память не влезают;
- app/bulk_writer.py — запись пачками через COPY (21 тыс. строк/с против
  6.7 тыс. построчно) с переподключением к базе при обрыве;
- эмбеддинги при массовой заливке не диспатчатся: они на порядок медленнее и
  стали бы узким местом, вектора досчитываются отдельно (reembed_missing.py).

scripts/ops/bulk_ingest_*.py удалены — их работу делает конвейер.

Проверено на проде: оба парсера отдают документы, прогон через run_parser
завершается штатно, позиция продолжения сдвигается (300 → 600), повторный
запуск продолжает с неё.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 20:32:53 +05:00