* fix validation in new form layout * pin mediatr to last oss version * update dependencies * cleanup code in core * cleanup code in ffmpeg * cleanup code in infra * cleanup code in scanner * cleanup code in application * cleanup main code * cleanup test code * solution-wide code cleanup
102 lines
3.1 KiB
C#
102 lines
3.1 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Diagnostics;
|
|
using ErsatzTV.Core.Domain;
|
|
using ErsatzTV.Core.Interfaces.Plex;
|
|
using ErsatzTV.Core.Interfaces.Repositories;
|
|
using ErsatzTV.Core.Plex;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace ErsatzTV.Application.Plex;
|
|
|
|
public abstract class PlexBaseConnectionHandler(
|
|
IPlexServerApiClient plexServerApiClient,
|
|
IMediaSourceRepository mediaSourceRepository,
|
|
ILogger logger)
|
|
{
|
|
protected async Task<Option<PlexConnection>> FindConnectionToActivate(
|
|
PlexMediaSource server,
|
|
PlexServerAuthToken token)
|
|
{
|
|
Option<PlexConnection> result = Option<PlexConnection>.None;
|
|
|
|
foreach (PlexConnection connection in server.Connections)
|
|
{
|
|
connection.IsActive = false;
|
|
}
|
|
|
|
using var cts = new CancellationTokenSource();
|
|
|
|
ConcurrentDictionary<PlexConnection, TimeSpan> successfulTimes = new();
|
|
var tasks = server.Connections
|
|
.Map(connection => PingPlexConnection(connection, token, successfulTimes, cts.Token))
|
|
.ToList();
|
|
|
|
while (tasks.Count > 0)
|
|
{
|
|
Task completed = await Task.WhenAny(tasks);
|
|
if (completed.IsCompletedSuccessfully)
|
|
{
|
|
if (!successfulTimes.IsEmpty)
|
|
{
|
|
await cts.CancelAsync();
|
|
break;
|
|
}
|
|
}
|
|
|
|
tasks.Remove(completed);
|
|
}
|
|
|
|
Option<PlexConnection> maybeBest =
|
|
successfulTimes.OrderByDescending(kv => kv.Value).Select(kvp => kvp.Key).HeadOrNone();
|
|
foreach (PlexConnection connection in maybeBest)
|
|
{
|
|
connection.IsActive = true;
|
|
}
|
|
|
|
if (server.Connections.All(c => !c.IsActive))
|
|
{
|
|
logger.LogError("Unable to locate Plex");
|
|
server.Connections.Head().IsActive = true;
|
|
}
|
|
|
|
await mediaSourceRepository.Update(server, [], []);
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task PingPlexConnection(
|
|
PlexConnection connection,
|
|
PlexServerAuthToken token,
|
|
ConcurrentDictionary<PlexConnection, TimeSpan> successfulTimes,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
logger.LogDebug("Attempting to locate to Plex at {Uri}", connection.Uri);
|
|
var sw = new Stopwatch();
|
|
sw.Start();
|
|
bool pingResult = await plexServerApiClient.Ping(connection, token, cancellationToken);
|
|
sw.Stop();
|
|
if (pingResult)
|
|
{
|
|
logger.LogInformation(
|
|
"Located Plex at {Uri} in {Milliseconds} ms",
|
|
connection.Uri,
|
|
sw.ElapsedMilliseconds);
|
|
successfulTimes.TryAdd(connection, sw.Elapsed);
|
|
}
|
|
else
|
|
{
|
|
logger.LogDebug(
|
|
"Unable to locate Plex at {Uri} after {Milliseconds} ms",
|
|
connection.Uri,
|
|
sw.ElapsedMilliseconds);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// do nothing
|
|
}
|
|
}
|
|
}
|