Align decoder startup deadlines and deploy resilient 7.0.8

This commit is contained in:
2026-10-13 09:07:29 +02:00
parent 0a834d863b
commit 0ab790d1e4
10 changed files with 527 additions and 66 deletions
+20 -7
View File
@@ -39,6 +39,12 @@ public sealed class LiveStreamProbe
}
}
// Distinguish a rejected finite sample from process startup/I/O/cancellation failures.
public sealed class ProbeProcessException : InvalidOperationException
{
public ProbeProcessException(int exitCode) : base("Decoder stream probe process failed (exit code " + exitCode.ToString(CultureInfo.InvariantCulture) + ").") { }
}
public Task<List<MediaStream>> Get(string url, CancellationToken caller, int? programme = null)
{
if (programme != null) url += "?programme=" + programme.Value.ToString(CultureInfo.InvariantCulture);
@@ -166,12 +172,19 @@ public sealed class LiveStreamProbe
if (await Snapshot(limits.InitialBytes))
{
attempts = 1;
json = await fileProbe(samplePath, programme, false, token);
analysisReturned = true;
try { Parse(json, programme); return json; }
catch (Exception error) when (error is InvalidOperationException || error is JsonException)
try
{
cause = "initial_video_unavailable";
json = await fileProbe(samplePath, programme, false, token);
analysisReturned = true;
}
catch (ProbeProcessException) { cause = "initial_probe_process_failed"; }
if (analysisReturned)
{
try { Parse(json, programme); return json; }
catch (Exception error) when (error is InvalidOperationException || error is JsonException)
{
cause = "initial_video_unavailable";
}
}
}
@@ -198,7 +211,7 @@ public sealed class LiveStreamProbe
cause = error is OperationCanceledException ? "deadline"
: error is IOException ? "capture_io_failure"
: error is HttpRequestException ? "capture_http_failure"
: error.Message.StartsWith("Decoder stream probe process failed", StringComparison.Ordinal) ? "probe_process_failed"
: error is ProbeProcessException ? "probe_process_failed"
: attempts > 0 && !analysisReturned ? "probe_analysis_failure"
: attempts > 0 ? ProbeCause(json, programme) : capturedBytes == 0 ? "capture_empty" : "capture_unavailable";
throw new InvalidOperationException($"Decoder probe failed: cause={cause}; expectedProgramme={programme?.ToString(CultureInfo.InvariantCulture) ?? "none"}; {ProbeSummary(json)}; sampleBytes={sampleBytes}; capturedBytes={capturedBytes}; elapsedMs={watch.ElapsedMilliseconds}; attempts={attempts}; captureStop={captureStop}.");
@@ -261,7 +274,7 @@ public sealed class LiveStreamProbe
{
await process.WaitForExitAsync(token);
await errors;
if (process.ExitCode != 0) throw new InvalidOperationException("Decoder stream probe process failed (exit code " + process.ExitCode.ToString(CultureInfo.InvariantCulture) + ").");
if (process.ExitCode != 0) throw new ProbeProcessException(process.ExitCode);
return await output;
}
finally