Resi Cues 1.0.3: the next cue's name keeps moving, and Resi logins stop hammering the account #43

Merged
christian merged 3 commits from claude/resi-cues-startup-pause into main 2026-10-07 17:25:00 -04:00
Collaborator

Resi Cues feeds the Timers tile a countdown titled with the next Resi cue's name. Three problems kept that from working at North Attleboro.

1. The name and countdown froze on a 30-second Resi (1.0.1)

The board could start a few seconds before a Resi publish and learn a 2s cadence from that partial first gap. Every real 30s gap after that was thrown out as a pause, so playback read as paused 15s into each update. While "paused", the next cue never rolls over and the card's name doesn't change.

  • resi.js: the partial gap right after startup is no longer learned; one outlier gap can no longer lock out the real cadence; until a cadence is measured, a pause is only called after 45s, not 15s.
  • server.js: the Timers card is titled with the cue's name; its status line says Next cue / Held instead of repeating the name.

2. A failed login retried every second, for ever (1.0.2)

A failed login left no session, so the next 1s poll signed in again, indefinitely. Resi answers that with 429, and since the retries never let up, the account never got out of it. At NA the admin decoder picker stayed empty with Resi login failed (429). The picker made it worse: it built a fresh client, and signed in, on every admin page load.

  • After a failed login, attempts wait 15s, doubling to 5min (or Resi's Retry-After). Calls in between fail at once with the reason and the time until the next try.
  • The status names the cause: rate-limited, password rejected (check the password), or Resi unreachable.
  • The decoder picker reuses the running module's client when the login matches, otherwise one client per login, so it shares the hold-off.

3. A login without access to the venue signed in on every poll (1.0.3)

Every 401/403 was answered by signing in again on the spot. For a login that works but may not list the account's venues (media@waters.church got 403 on /venues before it was given access), that was a successful sign-in on every 1s poll.

  • A refusal straight after signing in is a permission, not an expired session. It's held off like a failed login, with "This Resi login isn't allowed to see its venues (403) — ask a Resi admin for access". Only a session over a minute old is renewed.
  • 429 on any request holds off too, not only on the login.
  • The players cache-bust fallback no longer drops the parameter for good on a 401/403/429.

Tests

  • resi.test.js: new cases start partway through a 30s Resi cycle (2s and 9s before a publish, and a 2s burst after a seek). Before: 187s of false "paused" in 400s. After: 0. 60/60 pass.
  • server.test.js: new cases cover the login hold-off (a rate-limited minute of 1s polls signs in at most 3 times, the wait is shown, it recovers, a good session isn't re-signed), a rejected password, and a login that may not see venues (2 sign-ins in two minutes, not 120). These fail on the versions before. 13/13 pass.
  • server.test.js didn't await its async tests, so one raced the next and failed on main. Tests now run one at a time.
  • tools/layout-roundtrip.test.js passes.

Same fixes as the Resi → ProPresenter bridge and Companion module resi-studio-cues (christian/Nextcue).

Running on NA Ingest since 2026-10-06 (copied by hand, 1.0.0 backed up beside it), on the media@waters.church login.

🤖 Generated with Claude Code

Resi Cues feeds the Timers tile a countdown titled with the next Resi cue's name. Three problems kept that from working at North Attleboro. ## 1. The name and countdown froze on a 30-second Resi (1.0.1) The board could start a few seconds before a Resi publish and learn a 2s cadence from that partial first gap. Every real 30s gap after that was thrown out as a pause, so playback read as *paused* 15s into each update. While "paused", the next cue never rolls over and the card's name doesn't change. - `resi.js`: the partial gap right after startup is no longer learned; one outlier gap can no longer lock out the real cadence; until a cadence is measured, a pause is only called after 45s, not 15s. - `server.js`: the Timers card is titled with the cue's name; its status line says **Next cue** / **Held** instead of repeating the name. ## 2. A failed login retried every second, for ever (1.0.2) A failed login left no session, so the next 1s poll signed in again, indefinitely. Resi answers that with **429**, and since the retries never let up, the account never got out of it. At NA the admin decoder picker stayed empty with `Resi login failed (429)`. The picker made it worse: it built a fresh client, and signed in, on every admin page load. - After a failed login, attempts wait 15s, doubling to 5min (or Resi's `Retry-After`). Calls in between fail at once with the reason and the time until the next try. - The status names the cause: rate-limited, password rejected (check the password), or Resi unreachable. - The decoder picker reuses the running module's client when the login matches, otherwise one client per login, so it shares the hold-off. ## 3. A login without access to the venue signed in on every poll (1.0.3) Every 401/403 was answered by signing in again on the spot. For a login that works but may not list the account's venues (`media@waters.church` got 403 on `/venues` before it was given access), that was a successful sign-in on every 1s poll. - A refusal straight after signing in is a permission, not an expired session. It's held off like a failed login, with "This Resi login isn't allowed to see its venues (403) — ask a Resi admin for access". Only a session over a minute old is renewed. - 429 on any request holds off too, not only on the login. - The players cache-bust fallback no longer drops the parameter for good on a 401/403/429. ## Tests - `resi.test.js`: new cases start partway through a 30s Resi cycle (2s and 9s before a publish, and a 2s burst after a seek). Before: 187s of false "paused" in 400s. After: 0. 60/60 pass. - `server.test.js`: new cases cover the login hold-off (a rate-limited minute of 1s polls signs in at most 3 times, the wait is shown, it recovers, a good session isn't re-signed), a rejected password, and a login that may not see venues (2 sign-ins in two minutes, not 120). These fail on the versions before. 13/13 pass. - `server.test.js` didn't await its async tests, so one raced the next and failed on `main`. Tests now run one at a time. - `tools/layout-roundtrip.test.js` passes. Same fixes as the Resi → ProPresenter bridge and Companion module resi-studio-cues (christian/Nextcue). **Running on NA Ingest** since 2026-10-06 (copied by hand, 1.0.0 backed up beside it), on the `media@waters.church` login. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
christian added 1 commit 2026-10-06 14:59:32 -04:00
On a Resi that publishes every ~30s, the board could start a few seconds
before a publish and learn a 2s cadence from that partial first gap. Every
honest 30s gap after that was thrown out as a pause, so playback read as
paused 15s into every update: the countdown froze, and the next cue -- and
the name on the Timers card -- stopped moving on.

- The partial gap right after startup is no longer learned, and one outlier
  gap can no longer lock out the real cadence.
- Until a cadence is measured, a pause is only called after 45s, not 15s.
- The Timers card is titled with the cue's name; its status line now says
  "Next cue" / "Held" instead of repeating the name.
- server.test.js awaited nothing, so an async test raced the next one and
  failed on main; tests now run one at a time.

Same fix as the Resi -> ProPresenter bridge and the Companion module 0.1.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
christian added 1 commit 2026-10-06 15:44:24 -04:00
A failed login left no session, so the next 1s poll signed in again, and the
next, for ever. Resi answers that with 429s, and since the retries never let
up the account never got out of them: at North Attleboro the decoder picker
stayed empty with "Resi login failed (429)". The picker made it worse by
building a fresh client -- and signing in -- on every admin page load.

- After a failed login, further attempts wait 15s, doubling to 5min (or as
  long as Resi's Retry-After asks); calls in between fail at once with the
  reason and how long until the next try.
- The status says what happened: rate-limited, password rejected, or Resi
  unreachable.
- The decoder picker reuses the running module's client when the login
  matches, otherwise one client per login, so it shares the hold-off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
christian changed title from Resi Cues 1.0.1: the next cue's name keeps moving on a 30-second Resi to Resi Cues 1.0.2: the next cue's name keeps moving, and a failed login stops hammering Resi 2026-10-06 15:44:42 -04:00
christian added 1 commit 2026-10-06 16:27:47 -04:00
Every 401/403 was answered by signing in again on the spot. For a login that
works but may not list the account's venues (media@waters.church at North
Attleboro got 403 on /venues), that was a successful sign-in on every 1s poll
-- the pattern that had just got another Resi account locked.

- A refusal straight after signing in is a permission, not an expired
  session: it is held off like a failed login, with the message "This Resi
  login isn't allowed to see its venues (403) — ask a Resi admin for access".
  Only a session over a minute old is renewed.
- 429 on any request holds off too, not only on the login.
- The players cache-bust fallback no longer drops the parameter for good on a
  401/403/429, which are about the login rather than the parameter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
christian changed title from Resi Cues 1.0.2: the next cue's name keeps moving, and a failed login stops hammering Resi to Resi Cues 1.0.3: the next cue's name keeps moving, and Resi logins stop hammering the account 2026-10-07 17:24:45 -04:00
christian merged commit 60f82690f3 into main 2026-10-07 17:25:00 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: michael/ProdDash#43