mirror of https://github.com/ErsatzTV/ErsatzTV.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.0 KiB
93 lines
3.0 KiB
using System.Collections.Concurrent; |
|
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 System.Diagnostics.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 |
|
} |
|
} |
|
}
|
|
|