mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
fix(epg): remove cached XMLTV data after source deletion (#1548)
* fix(epg): remove cached XMLTV data after source deletion * fix(epg): close source reconciliation review races * fix(epg): serialize cleanup with replacement imports * fix(epg): report retired worker exits as cancellations * fix(epg): preserve source metadata through cache cleanup * refactor(epg): separate worker runtime and import lifecycle * fix(epg): skip cleanup for unchanged source settings * fix(epg): cancel retired error rows and pending retries * fix(epg): redact diagnostics and mirror committed settings after cleanup errors * fix(epg): preserve metadata writer order independently of timestamps
This commit is contained in:
1 parent
baba0529ef
commit
9de480826c
55 files changed
+3538
-615
No files matched your search
@@ -758,7 +758,7 @@ This project uses modern Angular signal-based APIs and patterns. **ALWAYS** use
|
||||
- `database.events.ts` - Database CRUD operations
|
||||
- `playlist.events.ts` - Playlist import/update
|
||||
- `playlist-open.events.ts` - Playlist files handed over by the OS (argv, file association, macOS `open-file`); the queue itself lives in `services/playlist-open-request.ts`
|
||||
- `epg.events.ts` - EPG IPC registration; freshness/fetch orchestration lives in `epg-fetch.service.ts`, manual channel-mapping resolution and CRUD in `epg-mapping.service.ts`, worker lifecycle in `epg-worker.service.ts`, DB lookups in `epg-query.service.ts`
|
||||
- `epg.events.ts` - EPG IPC registration; freshness/fetch orchestration lives in `epg-fetch.service.ts`, manual channel-mapping resolution and CRUD in `epg-mapping.service.ts`, source orchestration in `epg-worker.service.ts`, per-import lifecycle in `epg-fetch-operation.ts`, worker bootstrap/shutdown and clear protocol in `epg-worker-runtime.ts`, DB lookups in `epg-query.service.ts`
|
||||
- `xtream.events.ts` - Xtream Codes API
|
||||
- `stalker.events.ts` - Stalker portal API
|
||||
- `connectivity-guard.events.ts` - `CONNECTIVITY_GUARD_RESET`: forgets the connection failures recorded for a portal host. Both portal handlers above run every request through the per-host circuit breaker (rules in `@iptvnator/shared/host-health`, process-wide instance in `util/host-connectivity-guard.ts`; the web backend runs the same breaker over its proxy routes) — after 2 consecutive connection-level failures (no HTTP response; `ETIMEDOUT`/`ENOTFOUND`/`ECONNREFUSED`/… but never `ECONNRESET`) requests to that endpoint fail immediately for 30 s. The key is `URL.origin`, not `URL.host`, which would give `http://panel` and `https://panel` one shared record and let a dead TLS listener fast-fail the working HTTP one instead of hanging the full 30 s/15 s axios timeout again, with one half-open trial request afterwards. Any HTTP response (4xx and 5xx included) clears the record. The refusal is a real `Error` whose wording is a renderer contract (`buildHostConnectivityFastFailMessage` in `libs/shared/interfaces`): it must carry no `HTTP Error <code>`, no timeout wording and none of the auth phrases, or Stalker endpoint discovery misclassifies it and lazy portal repair fires against a host just declared dead. Discovery probes are exempt via the `skipConnectionGuard` payload flag (bypass + no failure counting, but successes still clear the record). Every user-driven retry/refresh that issues portal requests must reset BEFORE its first request, or the affordance fast-fails and looks broken; automatic and first-load paths deliberately do not reset. Current senders: Xtream content-gate Retry, Stalker catalog append retry (`retryContentPage`), Stalker search-page retry, `StalkerItvCacheService.refresh()` (Live TV refresh), both account-info dialogs' Retry, the destructive Xtream refresh (`XtreamRefreshFlowService`, before it deletes the cached catalog — one flow shared by both entry points, `PlaylistRefreshActionService.refreshXtream()` and `RecentPlaylistsComponent.refreshXtreamPlaylist()`, which supply only a progress reporter), `StalkerPortalDiscoveryService.discover()`, and `PortalStatusService` on `skipCache`. Kill switch: `IPTVNATOR_DISABLE_CONNECTIVITY_GUARD=1`. Contract: `docs/architecture/host-connectivity-guard.md`
|
||||
@@ -1670,6 +1670,28 @@ No formal migration system yet. Schema changes are applied via raw SQL in the `c
|
||||
|
||||
<!-- nx configuration end-->
|
||||
|
||||
## XMLTV Source Removal
|
||||
|
||||
Saving Settings → EPG reconciles cached XMLTV with committed global URLs and
|
||||
all enabled M3U playlist sources. Startup runs the same reconciliation after
|
||||
settings load and playlist migration. Ordinary saves skip unchanged normalized
|
||||
source sets; an explicitly edited EPG field can retry a failed cleanup.
|
||||
A cleanup failure after persistence still mirrors committed settings to Electron;
|
||||
the form stays dirty for retry. Failed storage writes never mirror to main.
|
||||
Failed settings reads and incomplete playlist migration never authorize pruning.
|
||||
Removed sources retire queued/running imports and dismiss retained error rows
|
||||
before worker-owned deletion. Retry waits for reconciliation and rechecks its
|
||||
error row, including after trust-setting writes. Shared channel IDs survive while
|
||||
another source has programmes or per-source channel metadata. The additive
|
||||
`epg_channel_sources` table preserves each imported source's name, logo, URL and
|
||||
timestamp plus transaction-ordered `write_order`, so removal restores the latest
|
||||
surviving snapshot even when import timestamps tie; ambiguous legacy metadata
|
||||
falls back to the XMLTV ID until reimport. Manual mappings remain user preferences, but no
|
||||
longer resolve deleted data. Renderer lookup generations, Xtream previews and Stalker mapping-cache
|
||||
invalidation prevent late results from restoring removed programmes. Provider
|
||||
EPG is independent. See `docs/architecture/m3u-playlist-module.md`
|
||||
("XMLTV source lifecycle").
|
||||
|
||||
## Portal Connectivity Preference
|
||||
|
||||
- Half-open trial slots follow the complete request lifetime with no elapsed-time
|
||||
|
||||
Reference in new issue
Block a user