mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 10:06:15 -08:00
fix(dashboard): read M3U favorites after queued favorite writes
getM3uFavoriteChannels could query SQLite before a just-toggled favorite was written: updateFavorites is serialized per playlist and can land late, while the dashboard reads as soon as the store changes and never reloads because playlistFavoritesReloadKey is unchanged. Await the playlist's write queue tail (which never rejects) before reading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
28b022ff48
commit
5e9e77d8db
3 files changed
+54
No files matched your search
@@ -0,0 +1,8 @@
|
||||
---
|
||||
type: fix
|
||||
area: dashboard
|
||||
---
|
||||
|
||||
An M3U channel added to favorites right before opening the dashboard now
|
||||
appears in the favorites rail immediately, instead of only after the next
|
||||
reload.
|
||||
@@ -345,6 +345,49 @@ describe('PlaylistsService', () => {
|
||||
expect(electron.dbGetAppPlaylists).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('reads resolved M3U favorites only after a queued favorites write lands', async () => {
|
||||
let storedFavorites: string[] = [];
|
||||
let releaseWrite!: () => void;
|
||||
const writeGate = new Promise<void>((resolve) => {
|
||||
releaseWrite = resolve;
|
||||
});
|
||||
const electron = {
|
||||
dbGetAppPlaylist: jest.fn(async () => {
|
||||
await writeGate;
|
||||
return { _id: 'playlist-1', favorites: storedFavorites };
|
||||
}),
|
||||
dbGetAppPlaylistFavoriteChannels: jest.fn(async () =>
|
||||
storedFavorites.map((id) => ({ id }))
|
||||
),
|
||||
dbGetAppPlaylists: jest.fn(async () => []),
|
||||
dbGetAppState: jest.fn(async (key: string) =>
|
||||
key === SQLITE_PLAYLIST_MIGRATION_FLAG ||
|
||||
key === STALKER_PLAYLIST_METADATA_MIGRATION_FLAG
|
||||
? '1'
|
||||
: null
|
||||
),
|
||||
dbSetAppState: jest.fn(),
|
||||
dbUpsertAppPlaylist: jest.fn(async (playlist: Playlist) => {
|
||||
storedFavorites = playlist.favorites as string[];
|
||||
}),
|
||||
dbUpsertAppPlaylists: jest.fn(),
|
||||
};
|
||||
testWindow.electron = electron;
|
||||
|
||||
const service = createService();
|
||||
const write = firstValueFrom(
|
||||
service.updateFavorites('playlist-1', ['channel-1'])
|
||||
);
|
||||
const read = firstValueFrom(
|
||||
service.getM3uFavoriteChannels('playlist-1')
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve));
|
||||
releaseWrite();
|
||||
|
||||
await write;
|
||||
await expect(read).resolves.toEqual([{ id: 'channel-1' }]);
|
||||
});
|
||||
|
||||
it('falls back from resolved M3U favorites when SQLite playlist migration is incomplete', async () => {
|
||||
const electron = {
|
||||
dbGetAppPlaylist: jest.fn(),
|
||||
|
||||
@@ -1092,6 +1092,9 @@ export class PlaylistsService {
|
||||
|
||||
return from(
|
||||
(async () => {
|
||||
// A favorite toggled just before this read may still be queued;
|
||||
// the queue tail never rejects.
|
||||
await this.playlistWriteQueues.get(playlistId);
|
||||
const alreadyMigrated = await electron.dbGetAppState(
|
||||
SQLITE_PLAYLIST_MIGRATION_FLAG
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user