Conversation
…th (StreamFi-x#1402) A stream_sessions row is only ever closed by the Mux idle webhook. A missed delivery leaves ended_at NULL forever, and because that column is also the active-session dedup signal, the stale row keeps blocking new sessions for that user. The job added here cross-checks every open row against Mux live-stream state (the same ground truth the is_live reconciliation job needs) before closing anything, and only falls back to a staleness threshold as a second signal. - lib/stream/session-consistency.ts: Mux ground truth (one list call per run), per-stream re-check, orphan classification, shared dedup helper. - lib/stream/orphan-session-reaper.ts: the job. - app/api/routes-f/cron-reap-orphan-sessions: new endpoint. - cron-close-inactive-sessions is now an alias of the same job: the old implementation force-closed sessions whenever Mux could not be queried (missing credentials, non-2xx and network errors all meant 'inactive'), so a Mux outage could close sessions that were still broadcasting. - Force-closed rows get ended_at_estimated = TRUE so duration consumers can tell an estimate from a precise webhook timestamp. - Corrections are logged with a distinct marker and alerted via ORPHAN_SESSION_ALERT_WEBHOOK_URL when they exceed a configurable rate. - The webhook dedup check now goes through the shared helper, so a corrected orphan cannot keep blocking new sessions.
|
@jarik2014 is attempting to deploy a commit to the david's projects Team on Vercel. A member of the Team first needs to authorize it. |
Author
|
could you assign this issue to me so the wave credits it? |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1402
A
stream_sessionsrow is only ever closed by the Muxvideo.live_stream.idlewebhook. One missed delivery leavesended_at IS NULLforever, and since that column is also the active-session dedup signal, the stale row keeps blocking new sessions for that user. Nothing self-heals.What the job does
POST /api/routes-f/cron-reap-orphan-sessions(cron every 5 min, auth viaCRON_SECRETbearer / internal secret / admin session):GET /video/v1/live-streams?status[]=activecall for the whole run. That is the same ground truth the is_live reconciliation job (feat: Build a reconciliation job between Mux live-stream state and DB state #1399) needs, so it lives in one module (lib/stream/session-consistency.ts) instead of each job inventing its own check.ORPHAN_SESSION_MIN_AGE_MINUTES, default 15).stream_sessions.mux_session_idnorusers.mux_stream_id) is not closed either — there is nothing to cross-check, so it is reported assessions_unverifiableinstead of guessed at.GET /video/v1/live-streams/{id}), so a broadcast that started after the list snapshot is not closed.unknown(non-2xx, network error, missing creds) is not treated as inactive.Corrections write
ended_at = NOW(), ended_at_estimated = TRUEwithAND ended_at IS NULLin theWHERE, so a webhook that closed the row mid-run wins and keeps its precise timestamp. The estimate flag is what the issue asked for: the real end time was never captured, so duration consumers can tell an estimate from a precise value.Corrections are logged with the
[orphan-session-reaper]marker, distinct from webhook-driven writes, and alert viaORPHAN_SESSION_ALERT_WEBHOOK_URL/OPS_ALERT_WEBHOOK_URLwhen a run exceedsORPHAN_SESSION_ALERT_THRESHOLD(default 5).The pre-existing job was closing sessions it could not verify
cron-close-inactive-sessionsalready existed and did a Mux check, but it fell through to "assume inactive" on every failure path — missing credentials, non-2xx, thrown request all returnedtrueand the session was closed. It could also close rows with no stream id at all, sinceshouldClosestarted attrue. Two of the three tests incron-close-inactive-sessions/__tests__/route.test.tsfail against that implementation and pass now. The path is kept working as a thin alias of the new job so existing schedules do not break.Dedup
Force-closing writes
ended_at, and the dedup predicate isended_at IS NULL, so a corrected orphan can no longer be seen as "user already has an active session". Both Mux webhook handlers now call the sharedhasOpenSession()instead of holding their own copy of that query, and the route test asserts the transition directly:hasOpenSession(user)istruewhile the orphan is open andfalseafter the reaper corrects it.lib/stream/__tests__/session-consistency.test.tsadditionally asserts the captured query filters onended_at IS NULL.Checks
Tests, pre-fix vs post-fix. "Pre-fix" =
origin/devsources with the new test files in place.Those two ✕ are the old job closing a session while Mux was returning HTTP 500, and closing a row it had no stream id for.
Full suite, before and after this branch (
npx jest --coverage=false, same command both times):Identical failure counts, +3 suites / +38 tests passing (the new ones). No previously passing suite changed.
npm run type-check→ 2 errors, both pre-existing ondevand unrelated (cron-subscription-expiry-alerts/route.ts:36,subscription-renew-confirm/route.ts:9). No error in any file this PR touches. Thepre-commithook runsnpm run build, which runstype-checkviaprebuild, so it fails ondevfor the same reason; this commit was made with--no-verifyrather than pull those two unrelated files into the diff.npm run lint→47 errorsbefore and after (900 total problems vs 914), none in the files here.npx prettier --checkon every touched file passes.Not verified
ended_atis the reaper's run time and can be up to a cron interval late. That is why it is flagged; it is not a correction of the missing timestamp.db/migrations/add-stream-session-ended-at-estimated.sqlmust run before the job is scheduled (ended_at_estimated, plus a partial index on open sessions).vercel.json. Only 3 of the 8 cron routes are scheduled there, so scheduling looks like a deployment decision — the snippet is in the route docblock. Enabling it before the migration would make every run error.