fix(events): refresh saved payout calendars once per hourly pass (WealthLedger/backend#53) #157

Merged
codex-bot merged 1 commits from fix/53-hourly-calendar-refresh into develop 2026-11-02 23:06:14 +03:00
Owner

Summary

Hourly pass перечитывает сохранённые календари выплат (dividends, bond-events) один раз за проход. Остальные источники и обычный GET не затронуты.

Linked Issue

Refs WealthLedger/backend#53 (audit 2026-10-11: BE-003, BE-014). Зависит от #55 (смержен, 169bee1).

Changes

  • sourcePolicy: kinds dividends и bond-events получили policy calendar (раньше stable).
  • CatalogEnrichmentService.readMany/requestMany принимают необязательный refreshBefore. Календарь перечитывается, только если fetchedAt < refreshBefore. Без параметра поведение прежнее (GET, bond/stock income и т.д.).
  • UpcomingEventsService.refresh принимает walkStartedAt; TbankHourlyScheduler.dispatchEvents передаёт метку начала обхода (как уже делает portfolio). Второй счёт с тем же UID видит свежий fetchedAt и не грузит календарь повторно.
  • Detail/metadata/quotes/history не форсируются. Failed refresh не перезаписывает строку, поэтому предыдущий полный календарь и forecast сохраняются (граница из #55).
  • MOEX: по решению владельца missing/malformed/cursor остаются MOEX_UNAVAILABLE (conservative failure). moex.client.ts и его spec не менялись.
  • Нет миграции, схема БД не менялась, новых слоёв нет.

Verification

  • test/upcoming-events.e2e-spec.ts (SQLite HTTP, реальный путь refresh→readMany→requestMany, без stub планировщика): 4 новых теста падали на старом коде, 30/30 проходят после фикса. Проверяют: изменённая и отменённая выплата того же окна обновляют dataRevision/события; failed refresh сохраняет строку, lastSuccessfulAt, forecast и виден как failure; два счёта с одним UID дают одну загрузку за проход; GET и обычный refresh без метки RPC не делают, detail не перечитывается; bond-календарь с постоянным ключом перечитывается только в проходе.
  • npm run verify: 42 suites / 310 tests, lint, typecheck, build — OK.
  • npm run test:e2e (все SQLite-suites): exit 0. npm run openapi:check: OK.
  • Не проверено: реальные T-Bank/MOEX (live запрещены), PostgreSQL, нагрузка одного часового прохода на MOEX. Конкретное поведение MOEX на missing-блок не проверялось.

Breaking Changes (если есть)

Нет. Публичный API/OpenAPI не менялся.

## Summary Hourly pass перечитывает сохранённые календари выплат (`dividends`, `bond-events`) один раз за проход. Остальные источники и обычный GET не затронуты. ## Linked Issue Refs WealthLedger/backend#53 (audit 2026-10-11: BE-003, BE-014). Зависит от #55 (смержен, `169bee1`). ## Changes - `sourcePolicy`: kinds `dividends` и `bond-events` получили policy `calendar` (раньше `stable`). - `CatalogEnrichmentService.readMany/requestMany` принимают необязательный `refreshBefore`. Календарь перечитывается, только если `fetchedAt < refreshBefore`. Без параметра поведение прежнее (GET, bond/stock income и т.д.). - `UpcomingEventsService.refresh` принимает `walkStartedAt`; `TbankHourlyScheduler.dispatchEvents` передаёт метку начала обхода (как уже делает portfolio). Второй счёт с тем же UID видит свежий `fetchedAt` и не грузит календарь повторно. - Detail/metadata/quotes/history не форсируются. Failed refresh не перезаписывает строку, поэтому предыдущий полный календарь и forecast сохраняются (граница из #55). - MOEX: по решению владельца missing/malformed/cursor остаются `MOEX_UNAVAILABLE` (conservative failure). `moex.client.ts` и его spec не менялись. - Нет миграции, схема БД не менялась, новых слоёв нет. ## Verification - `test/upcoming-events.e2e-spec.ts` (SQLite HTTP, реальный путь refresh→readMany→requestMany, без stub планировщика): 4 новых теста падали на старом коде, 30/30 проходят после фикса. Проверяют: изменённая и отменённая выплата того же окна обновляют `dataRevision`/события; failed refresh сохраняет строку, `lastSuccessfulAt`, forecast и виден как failure; два счёта с одним UID дают одну загрузку за проход; GET и обычный refresh без метки RPC не делают, detail не перечитывается; bond-календарь с постоянным ключом перечитывается только в проходе. - `npm run verify`: 42 suites / 310 tests, lint, typecheck, build — OK. - `npm run test:e2e` (все SQLite-suites): exit 0. `npm run openapi:check`: OK. - Не проверено: реальные T-Bank/MOEX (live запрещены), PostgreSQL, нагрузка одного часового прохода на MOEX. Конкретное поведение MOEX на missing-блок не проверялось. ## Breaking Changes (если есть) Нет. Публичный API/OpenAPI не менялся.
codex-bot added 1 commit 2026-11-02 22:54:30 +03:00
fix(events): refresh saved payout calendars once per hourly pass (WealthLedger/backend#53)
Backend verify / commits (pull_request) Successful in 1m25s
Backend verify / security (pull_request) Successful in 1m2s
Backend verify / verify (pull_request) Successful in 6m1s
d3106a5366
codex-bot merged commit aeb4647fda into develop 2026-11-02 23:06:14 +03:00
codex-bot deleted branch fix/53-hourly-calendar-refresh 2026-11-02 23:06:15 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: WealthLedger/backend#157