fix(dvr,reverb): JSON error responses, Reverb secret persistence, and one-shot rule cleanup - #1355
Open
Grimothy wants to merge 2 commits into
Open
fix(dvr,reverb): JSON error responses, Reverb secret persistence, and one-shot rule cleanup#1355Grimothy wants to merge 2 commits into
Grimothy wants to merge 2 commits into
Conversation
…; persist Reverb secrets across restarts
- DvrSchedulerService::scheduleRuleImmediately now catches/logs matchRule()
failures instead of letting them propagate out of schedule_dvr, matching
the existing try/catch pattern already used by the periodic scheduler tick.
- DvrRecording's deleting hook now guards broadcastDeleted() and the VOD
channel/episode cascade with try/catch, matching the two blocks around
them that were already guarded. An uncaught exception in either path
previously surfaced as delete_dvr_recording's HTML error page instead of
a clean JSON response.
- bootstrap/app.php: force JSON rendering for any uncaught exception on the
Xtream API routes (player_api.php, get.php), since these endpoints are
consumed by TV/IPTV clients that always parse the response as JSON
regardless of the request's Accept header.
- start-container: load previously-generated secrets (REDIS_PASSWORD,
M3U_PROXY_TOKEN, REVERB_APP_ID, REVERB_APP_SECRET) from the persistent
config volume before the generate-if-unset checks run. Previously these
regenerated fresh on every boot since docker-compose doesn't set them and
the checks ran before the persisted .env file was read. A restarted (not
recreated) container would silently rotate its Reverb secret, causing
already-connected or cached clients to fail private-channel subscription
auth ("Connection is unauthorized") with no visible error — recording
status pushes (dvr.status) would silently stop arriving until the app
was fully restarted to re-fetch state from scratch.
…st deletion Once/Manual rules are one-shot — they'll never match another programme — so there's no reason to wait for the recording row itself to be deleted before cleaning up the spent rule. Previously this cascade only ran in the deleting() hook; a recording that was merely cancelled (keep footage) or completed normally left its rule enabled and orphaned indefinitely. Added the same cleanup to the updated() hook, gated on the new status being Completed/Failed/Cancelled, scoped to Once/Manual only (Series rules must stay alive for future episodes not yet matched into rows, so the siblings-based heuristic used on deletion doesn't apply here). Extracted the duplicated rule-delete try/catch into a shared deleteRuleQuietly() helper used by both hooks. Verified: DvrRecordingCascadeTest, DvrSchedulerServiceTest, XtreamScheduleDvrTest, XtreamCancelDeleteDvrTest pass (166 assertions, 0 failures). Also reproduced live against a running instance: scheduled a recording, cancelled with keep-footage, confirmed the rule was deleted once the recording settled to Completed.
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.
Summary
schedule_dvrcould return an HTML error page instead of JSON when the immediate-match path(recording a program that's already airing) threw —
DvrSchedulerService::scheduleRuleImmediately()now catches/logs
matchRule()failures, matching the existing try/catch already used by the periodicscheduler tick (
runMatchAndSchedule).delete_dvr_recordingcould do the same for a completed recording with an associated VODchannel/episode —
DvrRecording'sdeletinghook now guardsbroadcastDeleted()and the VOD cascadeblock with try/catch, matching the two blocks already guarded right next to them.
shouldRenderJsonWhenrule inbootstrap/app.phpscoped to the Xtream API routes(
player_api.php,get.php) so any other uncaught exception on these endpoints renders as JSONinstead of Laravel's default HTML error page — these routes are consumed by TV/IPTV clients that always
parse the response as JSON.
start-container:REDIS_PASSWORD,M3U_PROXY_TOKEN,REVERB_APP_ID, andREVERB_APP_SECRETarenow loaded from the persisted config volume before the generate-if-unset checks run. Previously,
since docker-compose doesn't set these and the persisted
.envwasn't read until later in the script,a restarted (not recreated) container would silently regenerate a fresh Reverb secret on every boot.
Any already-connected or cached client would then fail private-channel subscription auth ("Connection
is unauthorized") with no visible error —
dvr.status(and other) pushes would silently stop arrivinguntil the app was fully restarted to re-fetch state from scratch.
status (Completed/Failed/Cancelled), not just when the recording row is explicitly deleted. Previously,
choosing "Keep recording" to stop an in-progress recording — a common, legitimate choice — left the
spent one-shot rule enabled and orphaned in the editor's Rules list forever, since it would never match
anything again. Series rules are untouched by this change (they still only clean up on deletion, since
a completed episode doesn't mean the season is over).
Test plan
DvrRecordingCascadeTest,DvrSchedulerServiceTest,XtreamScheduleDvrTest,XtreamCancelDeleteDvrTestpassschedule_dvron an already-airing program anddelete_dvr_recordingon a completedrecording with a VOD channel via a local test container — both now return clean JSON instead of an HTML
error page
WebSocket private-channel handshake end-to-end — subscription succeeds on the very first boot
the associated rule was deleted once the recording settled to Completed (previously stayed enabled
indefinitely)