mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 11:06:16 -08:00
fix(settings): defer a stale Xtream hydration as soon as the catalog is withheld
On Electron a relock that overtook the initial content hydration waited for the category reload before the content reload set the deferral flag; the older unlocked hydration could publish its streams in that window. withholdCatalog() now sets the flag itself, before anything is awaited. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
870e526f9c
commit
eb770b16d6
3 files changed
+41
-1
No files matched your search
@@ -190,7 +190,9 @@ on either side.
|
||||
answered before every state patch, so a read issued under an older lock
|
||||
version is dropped instead of published. A lock change that overtakes
|
||||
the INITIAL hydration (the content is not initialized yet, so the reload
|
||||
has nothing to re-read) sets a deferred-reload flag instead: the
|
||||
has nothing to re-read) sets a deferred-reload flag instead — already
|
||||
when `withholdCatalog()` empties the lists, before the category reload is
|
||||
awaited: the
|
||||
hydration then publishes empty lists in place of the rows it read under
|
||||
the previous lock state (categories included), and the filtered reload
|
||||
of categories and content runs as soon as the hydration settles, on
|
||||
|
||||
+31
@@ -173,6 +173,37 @@ describe('withContent parental-lock reloads', () => {
|
||||
expect(store.serialStreams()).toEqual([]);
|
||||
});
|
||||
|
||||
it('suppresses a hydration publication as soon as the catalog is withheld', async () => {
|
||||
const live = createDeferred<unknown[]>();
|
||||
let calls = 0;
|
||||
let liveAfterHydrationPublish: unknown;
|
||||
dataSource.getContent.mockImplementation(() => {
|
||||
calls += 1;
|
||||
if (calls === 1) {
|
||||
return live.promise;
|
||||
}
|
||||
if (calls === 2) {
|
||||
// The hydration published its live rows just before this
|
||||
// (vod) read: capture what it left on screen.
|
||||
liveAfterHydrationPublish = store.liveStreams();
|
||||
}
|
||||
return Promise.resolve([{ xtream_id: calls }]);
|
||||
});
|
||||
const initialization = store.initializeContent();
|
||||
await waitForCondition(() => calls === 1);
|
||||
|
||||
// Relock: the catalog is withheld BEFORE any reload has run, then
|
||||
// the hydration's pending (unlocked) live read resolves.
|
||||
store.withholdCatalog();
|
||||
live.resolve([{ xtream_id: 1 }]);
|
||||
await initialization;
|
||||
|
||||
expect(liveAfterHydrationPublish).toEqual([]);
|
||||
// The deferred reload refilled the list with fresh rows.
|
||||
expect(store.liveStreams()).not.toEqual([{ xtream_id: 1 }]);
|
||||
expect(store.liveStreams()).not.toEqual([]);
|
||||
});
|
||||
|
||||
it('empties the category lists when their reload fails', async () => {
|
||||
dataSource.getCategories.mockResolvedValue([{ category_id: 'x' }]);
|
||||
await store.reloadCategories();
|
||||
|
||||
@@ -1524,6 +1524,13 @@ export function withContent() {
|
||||
* refills the lists.
|
||||
*/
|
||||
withholdCatalog(): void {
|
||||
// Before any reload is awaited: an initial hydration
|
||||
// still in flight read its rows under the previous lock
|
||||
// state, and must not publish them while the category
|
||||
// reload runs. The deferred reload refills afterwards.
|
||||
if (!store.isContentInitialized()) {
|
||||
reloadAfterInitialization = true;
|
||||
}
|
||||
patchState(store, {
|
||||
liveCategories: [],
|
||||
vodCategories: [],
|
||||
|
||||
Reference in new issue
Block a user