From eb95d10628f4dbb41a8c651ef5a6cb9490625978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kacprzak?= Date: Fri, 23 Oct 2026 19:35:16 +0200 Subject: [PATCH] Allow native guide import to complete without plugin-imposed short timeout --- Jellyfin.Plugin.Enigma2/ChannelSyncTask.cs | 4 +++- Jellyfin.Plugin.Enigma2/Jellyfin.Plugin.Enigma2.csproj | 4 ++-- README.md | 4 ++++ Tests/ChannelSyncTests.cs | 5 +++-- build.yaml | 2 +- deploy-plugin-only.py | 2 +- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Jellyfin.Plugin.Enigma2/ChannelSyncTask.cs b/Jellyfin.Plugin.Enigma2/ChannelSyncTask.cs index 9fa034a..49e80ff 100644 --- a/Jellyfin.Plugin.Enigma2/ChannelSyncTask.cs +++ b/Jellyfin.Plugin.Enigma2/ChannelSyncTask.cs @@ -98,7 +98,9 @@ public sealed class ChannelSyncTask : IScheduledTask } progress.Report(10); var refreshStarted=DateTime.UtcNow; - await tasks.Execute(worker,new TaskOptions{MaxRuntimeTicks=TimeSpan.FromMinutes(5).Ticks}).WaitAsync(token).ConfigureAwait(false); + // A first seven-day import may take much longer than a channel check. + // Keep the native job's ordinary execution/cancellation policy. + await tasks.Execute(worker,new TaskOptions()).WaitAsync(token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); if(worker.LastExecutionResult?.Status!=TaskCompletionStatus.Completed||worker.LastExecutionResult.StartTimeUtc net10.0 - 7.0.10.0 - 7.0.10.0 + 7.0.11.0 + 7.0.11.0 diff --git a/README.md b/README.md index bc776ba..edc61c0 100644 --- a/README.md +++ b/README.md @@ -84,3 +84,7 @@ Zadanie pobiera bukiety z limitem30s i wykrywa zmiany referencji, nazw, kolejno Przed natywnym odświeżeniem zapisuje własny checkpoint w `data/decoder-integration/channel-sync.json`: stare identyfikatory/ref/nazwy oraz natywne ulubione. Po jednoznacznej migracji aktualizuje natywne ulubione oraz ulubione/ukryte/kolejność we własnych preferencjach użytkowników. Aktualizacje plików preferencji używają tych samych blokad co edytor, zachowują aktualne ustawienia i usuwają duplikaty. Błąd/anulowanie pozostawia checkpoint do ponowienia również wtedy, gdy natywne zadanie usunęło już stare kanały. Bezpośrednich zapisów do bazy Jellyfina nie ma. Stan ostatniej kontroli/synchronizacji jest dostępny w administracyjnym DecoderIntegration/Status. 120 kontroli .NET10 przeszło: dokładnie6h/start, zmiany numerów i logo, migracja natywnych i własnych preferencji, rozdzielenie użytkowników, pusta lista, zajęty przewodnik, częściowa awaria i ponowienie, współbieżność, anulowanie oraz wyłączenie funkcji. Źródła ani nagrania produkcyjne nie były używane w tych testach. Stan przed wdrożeniem: produkcja7.0.9, kandydat7.0.10. + +### 7.0.11 — czas pełnego importu EPG + +7.0.10 wdrożono o17:27UTC. Zadanie startowe poprawnie uruchomiło natywny RefreshGuide i wprowadziło aktualne referencje Pulsu/Pulsu2/WP/TVN24. Pełny import7dni EPG przekroczył jednak narzucone5min i został anulowany o17:32:55UTC. Własna synchronizacja prawidłowo zgłosiła błąd i zachowała checkpoint216starych wpisów; nie oznaczono importu jako udanego. W7.0.11 usunięto własny limit czasu natywnego zadania — używane są zwykłe zasady jego wykonania i anulowania. Limit30s dotyczy tylko wstępnego pobrania bukietu. Dodano regresję na brak krótkiego MaxRuntimeTicks. Checkpoint i natywne preferencje pozostają zgodne pomiędzy7.0.10 i7.0.11, więc start nowej wersji ponawia migrację z oryginalnego stanu sprzed odświeżenia. diff --git a/Tests/ChannelSyncTests.cs b/Tests/ChannelSyncTests.cs index d902ab9..3ce9370 100644 --- a/Tests/ChannelSyncTests.cs +++ b/Tests/ChannelSyncTests.cs @@ -34,6 +34,7 @@ public static class ChannelSyncTests await c.Store.Save(c.SecondOwner.Id,new ChannelPreferences{HiddenIds=new[]{c.OldId.ToString()}},CancellationToken.None); await c.Run(); check(c.Executions==1&&c.SourceCalls==1,"changed bouquet invokes native RefreshGuide once without opening a receiver stream"); + check(c.NativeRuntimePolicy,"full guide import retains native runtime policy without an artificial short timeout"); var prefs=await c.Store.Load(c.Owner.Id,CancellationToken.None); check(prefs.FavoriteIds.SequenceEqual(new[]{c.NewId.ToString("N")})&&prefs.HiddenIds.SequenceEqual(new[]{c.NewId.ToString("N")})&&prefs.OrderedIds.SequenceEqual(new[]{c.OtherId.ToString("N"),c.NewId.ToString("N")})&&prefs.DefaultView=="favorites","native channel migration remaps and deduplicates saved favorites, hidden IDs and ordering"); check(c.Data[(c.Owner.Id,c.NewId)].IsFavorite&&c.Data[(c.Owner.Id,c.NewId)].PlayCount==7,"native favorite migration preserves existing play history"); @@ -95,7 +96,7 @@ public static class ChannelSyncTests public Guid OldId=Guid.NewGuid(),NewId=Guid.NewGuid(),OtherId=Guid.NewGuid(); public User Owner=new("sync-owner","test","test"),SecondOwner=new("sync-second","test","test"); public ChannelInfo[] Current={new(){Id=SavedChannelPlaybackTests.Current,Name="TV PULS HD",Number="1"}}; - public BaseItem[] Items;public int Executions,SourceCalls;public bool Fail; + public BaseItem[] Items;public int Executions,SourceCalls;public bool Fail,NativeRuntimePolicy; public Dictionary<(Guid,Guid),UserItemData> Data=new(); public PreferencesStore Store;public ChannelSyncTask Task;public Worker Worker=new(); public TaskCompletionSource Block;public TaskCompletionSource Started=new(TaskCreationOptions.RunContinuationsAsynchronously); @@ -135,7 +136,7 @@ public static class ChannelSyncTests case "get_Name":return "Enigma2"; case "GetChannelsAsync":c.SourceCalls++;return System.Threading.Tasks.Task.FromResult>(c.Current); case "get_ScheduledTasks":return new IScheduledTaskWorker[]{c.Worker}; - case "Execute":if(!ReferenceEquals(args[0],c.Worker))throw new Exception("Wrong native task");return c.Execute(); + case "Execute":if(!ReferenceEquals(args[0],c.Worker))throw new Exception("Wrong native task");c.NativeRuntimePolicy=((TaskOptions)args[1]).MaxRuntimeTicks==null;return c.Execute(); case "GetItemList":return c.Items; case "GetUsers":return new[]{c.Owner,c.SecondOwner}; case "GetUserDataBatch": diff --git a/build.yaml b/build.yaml index d2d3806..885806e 100644 --- a/build.yaml +++ b/build.yaml @@ -8,7 +8,7 @@ guid: "193f29f9-ea6c-4595-a6f6-55e79d7c590a" # The version of the plugin, starting at 1. Note that the AssemblyVersion # and FileVersion flags in the `.csproj` file must have two additional # fiels, e.g. 1.0.0 to be built correctly. -version: "7.0.10.0" # Please increment with each pull request +version: "7.0.11.0" # Please increment with each pull request # The supported Jellyfin version, usually the earliest binary-compatible # version. Based on the Jellyfin components from NuGet. diff --git a/deploy-plugin-only.py b/deploy-plugin-only.py index 7aef4c2..082e60f 100644 --- a/deploy-plugin-only.py +++ b/deploy-plugin-only.py @@ -13,7 +13,7 @@ import urllib.error import urllib.request import uuid -VERSION = '7.0.10.0' +VERSION = '7.0.11.0' ABI = '12.2.0.0' GUID = '193f29f9-ea6c-4595-a6f6-55e79d7c590a' DLL = 'Jellyfin.Plugin.Enigma2.dll'