retry building the quick connect store in the startup probe, not just reading it
This commit is contained in:
@@ -52,6 +52,7 @@ using Jellyfin.Server.Implementations.SystemBackupService;
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Events;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Common.Updates;
|
||||
@@ -670,29 +671,45 @@ namespace Emby.Server.Implementations
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the quick connect store here so a store that cannot be reached stops startup, rather than
|
||||
/// being discovered on the first request that needs it. A read rather than a resolve because a
|
||||
/// shared store built with <c>abortConnect=false</c> constructs without touching the network, and
|
||||
/// retried until <see cref="_quickConnectProbeDeadline"/> so a starting instance rides out the blip
|
||||
/// a running one already tolerates.
|
||||
/// Builds and reads the quick connect store here so a store that cannot be reached stops startup,
|
||||
/// rather than being discovered on the first request that needs it. Both halves sit inside the
|
||||
/// retry: a store built with <c>abortConnect=false</c> constructs without touching the network and
|
||||
/// only the read settles it, while one built without that option connects eagerly and fails at the
|
||||
/// resolve. Retried until <see cref="_quickConnectProbeDeadline"/> so a starting instance rides out
|
||||
/// the blip a running one already tolerates.
|
||||
/// </summary>
|
||||
private async Task ProbeQuickConnectStoreAsync()
|
||||
{
|
||||
var store = Resolve<IQuickConnectStore>();
|
||||
var startTimestamp = Stopwatch.GetTimestamp();
|
||||
var reported = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
// A throwing singleton factory is not cached, so the resolve is retried along with the read.
|
||||
var store = Resolve<IQuickConnectStore>();
|
||||
await store.GetRequestBySecretAsync(StartupProbeSecret).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Stopwatch.GetElapsedTime(startTimestamp) + _quickConnectProbeRetryDelay < _quickConnectProbeDeadline)
|
||||
var elapsed = Stopwatch.GetElapsedTime(startTimestamp);
|
||||
if (elapsed + _quickConnectProbeRetryDelay < _quickConnectProbeDeadline)
|
||||
{
|
||||
Logger.LogWarning(ex, "Quick connect store is not reachable yet, retrying.");
|
||||
if (!reported)
|
||||
{
|
||||
reported = true;
|
||||
Logger.LogWarning(
|
||||
ex,
|
||||
"Quick connect store is not reachable yet, retrying for up to {Seconds}s.",
|
||||
(int)_quickConnectProbeDeadline.TotalSeconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug(ex, "Quick connect store is still not reachable, retrying.");
|
||||
}
|
||||
|
||||
await Task.Delay(_quickConnectProbeRetryDelay).ConfigureAwait(false);
|
||||
continue;
|
||||
}
|
||||
@@ -701,8 +718,14 @@ namespace Emby.Server.Implementations
|
||||
ex,
|
||||
"Quick connect is configured against the shared valkey/Redis store at {Key} and it is UNREACHABLE after {Seconds}s, so the server will not start. Bring valkey up, or clear that setting to keep quick connect state on this instance alone.",
|
||||
TranscodeStoreOptions.RedisConnectionStringKey,
|
||||
(int)_quickConnectProbeDeadline.TotalSeconds);
|
||||
throw;
|
||||
(int)elapsed.TotalSeconds);
|
||||
|
||||
if (ex is ServiceUnavailableException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new ServiceUnavailableException("Quick connect store is unreachable.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user