Allow native guide import to complete without plugin-imposed short timeout
This commit is contained in:
@@ -98,7 +98,9 @@ public sealed class ChannelSyncTask : IScheduledTask
|
|||||||
}
|
}
|
||||||
progress.Report(10);
|
progress.Report(10);
|
||||||
var refreshStarted=DateTime.UtcNow;
|
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();
|
token.ThrowIfCancellationRequested();
|
||||||
if(worker.LastExecutionResult?.Status!=TaskCompletionStatus.Completed||worker.LastExecutionResult.StartTimeUtc<refreshStarted.AddSeconds(-1))
|
if(worker.LastExecutionResult?.Status!=TaskCompletionStatus.Completed||worker.LastExecutionResult.StartTimeUtc<refreshStarted.AddSeconds(-1))
|
||||||
throw new InvalidOperationException("Native guide refresh did not complete successfully.");
|
throw new InvalidOperationException("Native guide refresh did not complete successfully.");
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||||
<AssemblyVersion>7.0.10.0</AssemblyVersion>
|
<AssemblyVersion>7.0.11.0</AssemblyVersion>
|
||||||
<FileVersion>7.0.10.0</FileVersion>
|
<FileVersion>7.0.11.0</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0|AnyCPU'">
|
||||||
|
|||||||
@@ -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.
|
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.
|
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.
|
||||||
|
|||||||
@@ -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.Store.Save(c.SecondOwner.Id,new ChannelPreferences{HiddenIds=new[]{c.OldId.ToString()}},CancellationToken.None);
|
||||||
await c.Run();
|
await c.Run();
|
||||||
check(c.Executions==1&&c.SourceCalls==1,"changed bouquet invokes native RefreshGuide once without opening a receiver stream");
|
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);
|
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(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");
|
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 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 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 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 Dictionary<(Guid,Guid),UserItemData> Data=new();
|
||||||
public PreferencesStore Store;public ChannelSyncTask Task;public Worker Worker=new();
|
public PreferencesStore Store;public ChannelSyncTask Task;public Worker Worker=new();
|
||||||
public TaskCompletionSource Block;public TaskCompletionSource Started=new(TaskCreationOptions.RunContinuationsAsynchronously);
|
public TaskCompletionSource Block;public TaskCompletionSource Started=new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
@@ -135,7 +136,7 @@ public static class ChannelSyncTests
|
|||||||
case "get_Name":return "Enigma2";
|
case "get_Name":return "Enigma2";
|
||||||
case "GetChannelsAsync":c.SourceCalls++;return System.Threading.Tasks.Task.FromResult<IEnumerable<ChannelInfo>>(c.Current);
|
case "GetChannelsAsync":c.SourceCalls++;return System.Threading.Tasks.Task.FromResult<IEnumerable<ChannelInfo>>(c.Current);
|
||||||
case "get_ScheduledTasks":return new IScheduledTaskWorker[]{c.Worker};
|
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 "GetItemList":return c.Items;
|
||||||
case "GetUsers":return new[]{c.Owner,c.SecondOwner};
|
case "GetUsers":return new[]{c.Owner,c.SecondOwner};
|
||||||
case "GetUserDataBatch":
|
case "GetUserDataBatch":
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ guid: "193f29f9-ea6c-4595-a6f6-55e79d7c590a"
|
|||||||
# The version of the plugin, starting at 1. Note that the AssemblyVersion
|
# The version of the plugin, starting at 1. Note that the AssemblyVersion
|
||||||
# and FileVersion flags in the `.csproj` file must have two additional
|
# and FileVersion flags in the `.csproj` file must have two additional
|
||||||
# fiels, e.g. 1.0.0 to be built correctly.
|
# 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
|
# The supported Jellyfin version, usually the earliest binary-compatible
|
||||||
# version. Based on the Jellyfin components from NuGet.
|
# version. Based on the Jellyfin components from NuGet.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import urllib.error
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
VERSION = '7.0.10.0'
|
VERSION = '7.0.11.0'
|
||||||
ABI = '12.2.0.0'
|
ABI = '12.2.0.0'
|
||||||
GUID = '193f29f9-ea6c-4595-a6f6-55e79d7c590a'
|
GUID = '193f29f9-ea6c-4595-a6f6-55e79d7c590a'
|
||||||
DLL = 'Jellyfin.Plugin.Enigma2.dll'
|
DLL = 'Jellyfin.Plugin.Enigma2.dll'
|
||||||
|
|||||||
Reference in New Issue
Block a user