Skip to content

fix(dlp,shdr): force-close a live entity once it retires from the feed - #322

Merged
cubehouse merged 1 commit into
mainfrom
worktree-fix-show-retirement-closed
Aug 19, 2026
Merged

fix(dlp,shdr): force-close a live entity once it retires from the feed#322
cubehouse merged 1 commit into
mainfrom
worktree-fix-show-retirement-closed

Conversation

@cubehouse

Copy link
Copy Markdown
Member

Summary

A seasonal show's run ends and it leaves the upstream feed entirely — no
POI/facility entry, no wait-times row, nothing for buildLiveData() to key
off. Dropping the row from the build achieves nothing: the collector is
upsert-only with no delete path, so the last live value (often OPERATING)
just sits there forever. Confirmed independently on two park modules: DLP's
"Angel's Pop Star Party" frozen 50+ days, four SHDR shows frozen up to 17
days.

Fix

Adds an opt-in retirement gate to Destination.getLiveData(): once a
previously-live entity has been missing from a full buildLiveData()
snapshot for longer than liveEntityRetirementMs (7 days by default), emit
a synthetic {id, status: 'CLOSED'} row — a genuine value change the
collector will actually write, clearing the frozen state.

  • Off by default. Only ever applies to full snapshots (scope === undefined)
    — a partial/streaming build's absentees carry no meaning.
  • Enabled explicitly on DisneylandParis and ShanghaiDisneylandResort,
    the two destinations where the pattern is confirmed. Not defaulted on
    library-wide: a destination whose buildLiveData() legitimately omits
    entities for unrelated reasons would get them wrongly force-closed.
  • 7-day default is conservative on purpose. Both confirmed real cases were
    stale far longer (17 and 50+ days), so a week already improves on both by
    an order of magnitude while tolerating a normal multi-day show hiatus.

Calibration data

Added src/tools/liveDataRetirement/capture.ts — polls local live data for
DLP/SHDR and logs id/status/showtime-count per entity per poll. Now
running hourly via cron so the 7-day default can be checked against a real
absence-pattern dataset rather than guessed twice.

Testing

  • src/__tests__/liveEntityRetirement.test.ts — the shared mechanism in
    isolation (default-off, under-threshold, over-threshold, reappearance
    resets the clock, scoped builds are never gated).
  • src/parks/dlp/__tests__/showRetirement.test.ts and
    src/parks/shdr/__tests__/showRetirement.test.ts — real park classes
    wired up, reproducing the exact frozen-show shape from each issue.
  • src/tools/liveDataRetirement/__tests__/capture.test.ts — pure
    row-formatting logic.
  • Full suite green (2059 tests), tsc --noEmit clean, npm run build
    clean.
  • Sanity-checked against real upstream data for both destinations
    (npm run dev -- disneylandparis / shanghaidisneylandresort) — live
    data path unaffected, no crashes. (SHDR's getEntities() fails on a
    pre-existing, unrelated bug — a theme-park ancestor id with unescaped
    ; characters reaching an entity id — confirmed present on main before
    this branch; filed separately.)

Test plan

  • Full test suite passes
  • Typecheck and build pass
  • Real upstream sanity check for DLP and SHDR
  • Watch the DLP/SHDR staleness dashboard over the next 1-2 weeks to
    confirm the known frozen rows (Angel's Pop Star Party, SHDR 10th
    Birthday Bash) actually clear once the retirement window elapses

🤖 Generated with Claude Code

A seasonal show's run ends and it leaves the upstream feed entirely — no
POI/facility entry, no wait-times row, nothing for buildLiveData() to key
off. Dropping the row from the build achieves nothing: the collector is
upsert-only with no delete path, so the last live value (often OPERATING)
just sits there forever. Confirmed independently on two park modules: DLP's
"Angel's Pop Star Party" frozen 50+ days, four SHDR shows frozen up to 17
days (#74, #83).

Adds an opt-in retirement gate to Destination.getLiveData(): once a
previously-live entity has been missing from a full buildLiveData()
snapshot for longer than liveEntityRetirementMs (7 days by default), emit a
synthetic {id, status: CLOSED} row — a genuine value change the collector
will actually write, clearing the frozen state. Off by default and only
ever applied to full snapshots; enabled explicitly on DisneylandParis and
ShanghaiDisneylandResort, the two destinations where the pattern is
confirmed.

Also adds a small capture tool (src/tools/liveDataRetirement) that polls
local live data and logs id/status/showtime-count per entity, to build a
real absence-pattern dataset for tuning the retirement window over time.
Scheduled hourly via cron against DLP and SHDR.
@cubehouse
cubehouse merged commit 1cb612e into main Aug 19, 2026
4 checks passed
@cubehouse
cubehouse deleted the worktree-fix-show-retirement-closed branch August 19, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant