[bug] Реиндекс эмбеддингов: счётчик «Indexed X of Y» не обновляется в реалтайме (только по перезагрузке) — follow-up #242 #262

Closed
opened 2026-06-30 08:56:59 +03:00 by vvzvlad · 0 comments
Owner

Баг: счётчик «Indexed X of Y» при реиндексации эмбеддингов не обновляется в реалтайме

Регрессия/недоделка по итогам PR #242 (live reindex progress). Замечание из ревью: vvzvlad/gitmost#242 (comment).

Симптом

После нажатия Reindex now в настройках AI → Embeddings:

  • счётчик корректно сбрасывается в 0 (Indexed 0 of 479 pages) — предсев прогресса работает;
  • но дальше не обновляется в реалтайме — висит на стартовом значении;
  • правильное (актуальное) число появляется только после перезагрузки страницы.

На скриншоте из обсуждения видно зависшее Indexed 0 of 479 pages при включённом Semantic search.

Ожидаемое поведение

Пока идёт фоновый реиндекс, счётчик должен сам подрастать (0 → total) с шагом опроса ~5 c, без ручной перезагрузки страницы — ровно ради этого в #242 добавлялись live-прогресс в Redis и клиентский поллинг.

Локализация проблемы

Бэкенд, судя по всему, отдаёт корректные данные: в getMasked() при активном прогоне indexedPages берётся из живого Redis-прогресса (progress.done), а reindexing = progress != null; воркер инкрементит done по каждой странице (embedding-reindex-progress.service.ts). Именно поэтому перезагрузка страницы показывает верное число — одиночный GET статуса возвращает текущий done.

Значит, ломается клиентский realtime-путь — фоновый опрос настроек не доезжает до перерисовки:

  • поллинг настроен через refetchInterval-функцию nextReindexPollInterval() и useAiSettingsQuery();
  • дедлайн опроса ставится в onSuccess мутации реиндекса (setReindexDeadline(Date.now() + REINDEX_POLL_CAP_MS)), а гасится эффектом на [reindexDeadline, settings] через isReindexComplete().

Кандидаты на причину (нужно проверить)

  1. Поллинг фактически не стартует/останавливается слишком рано: первый рефетч после invalidateQueries может прийти в момент, когда reindexing ещё/уже false, а indexedPages >= totalPages (DB-fallback) → isReindexComplete() === true → дедлайн обнуляется, опрос прекращается, число замирает на 0 до перезагрузки.
  2. Гонка предсева прогресса (короткий TTL pre-seed на enqueue) vs. старт воркера: на первых поллах progress может быть null → отдаётся DB-count, и условие остановки срабатывает преждевременно.
  3. refetchInterval-функция получает query.state.data, но возвращает false, потому что reindexDeadline к моменту вычисления уже null (порядок onSuccess уровня хука vs. уровня вызова mutate).

Шаги воспроизведения

  1. Включить Semantic search, настроить рабочие embeddings.
  2. Нажать Reindex now.
  3. Наблюдать счётчик Indexed X of Y, не перезагружая страницу.
  4. Счётчик стоит на 0; после F5 показывает актуальное значение.

Уточнить при отладке

Реально ли done инкрементится в Redis в реальном времени (HINCRBY на каждую страницу) или only к концу прогона — от этого зависит, чисто ли это клиентский баг или ещё и серверный (буферизация инкрементов). Проверяется наблюдением ключа ai:reindex:progress:<workspaceId> во время прогона.


Связано: PR #242, комментарий #242 (comment)

## Баг: счётчик «Indexed X of Y» при реиндексации эмбеддингов не обновляется в реалтайме Регрессия/недоделка по итогам PR #242 (live reindex progress). Замечание из ревью: vvzvlad/gitmost#242 (comment). ### Симптом После нажатия **Reindex now** в настройках AI → Embeddings: - счётчик корректно **сбрасывается в 0** (`Indexed 0 of 479 pages`) — предсев прогресса работает; - но дальше **не обновляется в реалтайме** — висит на стартовом значении; - **правильное (актуальное) число появляется только после перезагрузки страницы**. На скриншоте из обсуждения видно зависшее `Indexed 0 of 479 pages` при включённом Semantic search. ### Ожидаемое поведение Пока идёт фоновый реиндекс, счётчик должен сам подрастать (0 → total) с шагом опроса ~5 c, без ручной перезагрузки страницы — ровно ради этого в #242 добавлялись live-прогресс в Redis и клиентский поллинг. ### Локализация проблемы Бэкенд, судя по всему, отдаёт корректные данные: в [getMasked()](apps/server/src/integrations/ai/ai-settings.service.ts) при активном прогоне `indexedPages` берётся из живого Redis-прогресса (`progress.done`), а `reindexing = progress != null`; воркер инкрементит `done` по каждой странице ([embedding-reindex-progress.service.ts](apps/server/src/integrations/ai/embedding-reindex-progress.service.ts)). Именно поэтому **перезагрузка страницы показывает верное число** — одиночный GET статуса возвращает текущий `done`. Значит, ломается **клиентский realtime-путь** — фоновый опрос настроек не доезжает до перерисовки: - поллинг настроен через `refetchInterval`-функцию [nextReindexPollInterval()](apps/client/src/features/workspace/components/settings/components/ai-provider-settings.tsx) и [useAiSettingsQuery()](apps/client/src/features/workspace/queries/ai-settings-query.ts); - дедлайн опроса ставится в `onSuccess` мутации реиндекса (`setReindexDeadline(Date.now() + REINDEX_POLL_CAP_MS)`), а гасится эффектом на `[reindexDeadline, settings]` через `isReindexComplete()`. ### Кандидаты на причину (нужно проверить) 1. Поллинг фактически **не стартует/останавливается слишком рано**: первый рефетч после `invalidateQueries` может прийти в момент, когда `reindexing` ещё/уже `false`, а `indexedPages >= totalPages` (DB-fallback) → `isReindexComplete()` === true → дедлайн обнуляется, опрос прекращается, число замирает на 0 до перезагрузки. 2. Гонка предсева прогресса (короткий TTL pre-seed на enqueue) vs. старт воркера: на первых поллах `progress` может быть `null` → отдаётся DB-count, и условие остановки срабатывает преждевременно. 3. `refetchInterval`-функция получает `query.state.data`, но возвращает `false`, потому что `reindexDeadline` к моменту вычисления уже `null` (порядок `onSuccess` уровня хука vs. уровня вызова `mutate`). ### Шаги воспроизведения 1. Включить Semantic search, настроить рабочие embeddings. 2. Нажать **Reindex now**. 3. Наблюдать счётчик `Indexed X of Y`, не перезагружая страницу. 4. Счётчик стоит на 0; после `F5` показывает актуальное значение. ### Уточнить при отладке Реально ли `done` инкрементится в Redis в реальном времени (HINCRBY на каждую страницу) или only к концу прогона — от этого зависит, чисто ли это клиентский баг или ещё и серверный (буферизация инкрементов). Проверяется наблюдением ключа `ai:reindex:progress:<workspaceId>` во время прогона. --- Связано: PR #242, комментарий https://gitea.vvzvlad.xyz/vvzvlad/gitmost/pulls/242#issuecomment-3769
vvzvlad added the bug label 2026-06-30 08:56:59 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#262