fix(xtrim): не триммить un-acked pending + null-гард parseStreamEntries (баг #3) #9

Merged
claude merged 1 commits from dev into main 2026-06-03 13:02:49 +00:00
Owner

Баг #3: consumer падал навсегда (TypeError: Cannot read properties of null) и переставал читать стрим.

Два корня:

  1. XtrimSupervisor триммил по lastDeliveredId → сносил собственные un-acked pending. Теперь нижняя граница = самый старый un-acked ID (XPENDING/xpendingMinId), сравнение ID числовое.
  2. parseStreamEntries падал на [id,null] обрезанных записей при перечитке PEL. Добавлен гард.

Проверено на реальном Redis (новый integration-тест в CI). Unit: 211 зелёных, typecheck чистый. parser2 1.1.2→1.1.3.

Баг #3: consumer падал навсегда (TypeError: Cannot read properties of null) и переставал читать стрим. Два корня: 1. XtrimSupervisor триммил по lastDeliveredId → сносил собственные un-acked pending. Теперь нижняя граница = самый старый un-acked ID (XPENDING/xpendingMinId), сравнение ID числовое. 2. parseStreamEntries падал на [id,null] обрезанных записей при перечитке PEL. Добавлен гард. Проверено на реальном Redis (новый integration-тест в CI). Unit: 211 зелёных, typecheck чистый. parser2 1.1.2→1.1.3.
claude added 1 commit 2026-06-03 13:02:40 +00:00
fix(xtrim): не триммить un-acked pending + гард null-записей в parseStreamEntries
CI / Typecheck (pull_request) Has been cancelled
CI / Unit tests (pull_request) Has been cancelled
CI / Integration tests (pull_request) Has been cancelled
CI / Build (pull_request) Has been cancelled
CI / Lint (pull_request) Has been cancelled
c8b7107c3a
Баг #3: consumer падал навсегда с TypeError "Cannot read properties of null
(reading 'length')" и переставал читать стрим. Два корня:

1. XtrimSupervisor.trim() брал MINID = lastDeliveredId. Но un-acked pending
   записи старше lastDeliveredId (доставлены, не подтверждены) → XTRIM сносил
   собственные pending группы. Теперь нижняя граница trim — самый старый
   un-acked ID из XPENDING (новый метод RedisStore.xpendingMinId), а сравнение
   stream-ID числовое по <ms>-<seq>, не лексикографическое ('1000' < '999').

2. parseStreamEntries падал на null rawFields: при перечитывании PEL
   (XREADGROUP ... 0) Redis отдаёт [id, null] для обрезанных ID. Добавлен
   гард `if (!rawFields) continue` — обрезанные записи пропускаются.

Триггер: consumer отстаёт от писателя (бутстрап с genesis) → растёт pending →
XtrimSupervisor сносит pending → PEL отдаёт null → краш в бесконечном цикле.

Воспроизведено и проверено на реальном Redis (новый integration-тест
xtrim.integration.test.ts, гоняется в CI): trim сохраняет все un-acked pending,
PEL-перечитка не падает на null. Unit: 211 зелёных.

parser2 1.1.2→1.1.3. ship-reader без изменений.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude merged commit 19a905d54b into main 2026-06-03 13:02:49 +00:00
Sign in to join this conversation.