Browse Source

fix collection and network scanners (#2557)

pull/2558/head
Jason Dove 2 months ago committed by GitHub
parent
commit
f7c699248c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 35
      ErsatzTV.Application/Emby/Commands/CallEmbyCollectionScannerHandler.cs
  2. 35
      ErsatzTV.Application/Jellyfin/Commands/CallJellyfinCollectionScannerHandler.cs
  3. 35
      ErsatzTV.Application/Plex/Commands/CallPlexCollectionScannerHandler.cs
  4. 35
      ErsatzTV.Application/Plex/Commands/CallPlexNetworkScannerHandler.cs
  5. 10
      ErsatzTV.Core/Metadata/FakeLibraryId.cs
  6. 3
      ErsatzTV.Scanner/Application/Emby/Commands/SynchronizeEmbyCollections.cs
  7. 14
      ErsatzTV.Scanner/Application/Emby/Commands/SynchronizeEmbyCollectionsHandler.cs
  8. 2
      ErsatzTV.Scanner/Application/Jellyfin/Commands/SynchronizeJellyfinCollections.cs
  9. 14
      ErsatzTV.Scanner/Application/Jellyfin/Commands/SynchronizeJellyfinCollectionsHandler.cs
  10. 3
      ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexCollections.cs
  11. 14
      ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexCollectionsHandler.cs
  12. 3
      ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexNetworks.cs
  13. 14
      ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexNetworksHandler.cs
  14. 16
      ErsatzTV.Scanner/Core/Emby/EmbyCollectionScanner.cs
  15. 16
      ErsatzTV.Scanner/Core/Jellyfin/JellyfinCollectionScanner.cs
  16. 16
      ErsatzTV.Scanner/Core/Plex/PlexCollectionScanner.cs
  17. 1
      ErsatzTV.Scanner/Core/Plex/PlexNetworkScanner.cs
  18. 32
      ErsatzTV.Scanner/Worker.cs

35
ErsatzTV.Application/Emby/Commands/CallEmbyCollectionScannerHandler.cs

@ -2,7 +2,9 @@ using System.Globalization; @@ -2,7 +2,9 @@ using System.Globalization;
using ErsatzTV.Application.Libraries;
using ErsatzTV.Core;
using ErsatzTV.Core.Errors;
using ErsatzTV.Core.Interfaces.Metadata;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Metadata;
using ErsatzTV.FFmpeg.Runtime;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
@ -13,11 +15,15 @@ namespace ErsatzTV.Application.Emby; @@ -13,11 +15,15 @@ namespace ErsatzTV.Application.Emby;
public class CallEmbyCollectionScannerHandler : CallLibraryScannerHandler<SynchronizeEmbyCollections>,
IRequestHandler<SynchronizeEmbyCollections, Either<BaseError, Unit>>
{
private readonly IScannerProxyService _scannerProxyService;
public CallEmbyCollectionScannerHandler(
IDbContextFactory<TvContext> dbContextFactory,
IConfigElementRepository configElementRepository,
IScannerProxyService scannerProxyService,
IRuntimeInfo runtimeInfo) : base(dbContextFactory, configElementRepository, runtimeInfo)
{
_scannerProxyService = scannerProxyService;
}
public async Task<Either<BaseError, Unit>>
@ -68,16 +74,31 @@ public class CallEmbyCollectionScannerHandler : CallLibraryScannerHandler<Synchr @@ -68,16 +74,31 @@ public class CallEmbyCollectionScannerHandler : CallLibraryScannerHandler<Synchr
SynchronizeEmbyCollections request,
CancellationToken cancellationToken)
{
var arguments = new List<string>
Option<Guid> maybeScanId = _scannerProxyService.StartScan(FakeLibraryId.EmbyCollections);
foreach (var scanId in maybeScanId)
{
"scan-emby-collections", request.EmbyMediaSourceId.ToString(CultureInfo.InvariantCulture)
};
try
{
var arguments = new List<string>
{
"scan-emby-collections",
request.EmbyMediaSourceId.ToString(CultureInfo.InvariantCulture),
GetBaseUrl(scanId)
};
if (request.ForceScan)
{
arguments.Add("--force");
if (request.ForceScan)
{
arguments.Add("--force");
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
}
finally
{
_scannerProxyService.EndScan(scanId);
}
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
return BaseError.New("Emby collections are already scanning");
}
}

35
ErsatzTV.Application/Jellyfin/Commands/CallJellyfinCollectionScannerHandler.cs

@ -2,7 +2,9 @@ using System.Globalization; @@ -2,7 +2,9 @@ using System.Globalization;
using ErsatzTV.Application.Libraries;
using ErsatzTV.Core;
using ErsatzTV.Core.Errors;
using ErsatzTV.Core.Interfaces.Metadata;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Metadata;
using ErsatzTV.FFmpeg.Runtime;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
@ -13,11 +15,15 @@ namespace ErsatzTV.Application.Jellyfin; @@ -13,11 +15,15 @@ namespace ErsatzTV.Application.Jellyfin;
public class CallJellyfinCollectionScannerHandler : CallLibraryScannerHandler<SynchronizeJellyfinCollections>,
IRequestHandler<SynchronizeJellyfinCollections, Either<BaseError, Unit>>
{
private readonly IScannerProxyService _scannerProxyService;
public CallJellyfinCollectionScannerHandler(
IDbContextFactory<TvContext> dbContextFactory,
IConfigElementRepository configElementRepository,
IScannerProxyService scannerProxyService,
IRuntimeInfo runtimeInfo) : base(dbContextFactory, configElementRepository, runtimeInfo)
{
_scannerProxyService = scannerProxyService;
}
public async Task<Either<BaseError, Unit>>
@ -68,16 +74,31 @@ public class CallJellyfinCollectionScannerHandler : CallLibraryScannerHandler<Sy @@ -68,16 +74,31 @@ public class CallJellyfinCollectionScannerHandler : CallLibraryScannerHandler<Sy
SynchronizeJellyfinCollections request,
CancellationToken cancellationToken)
{
var arguments = new List<string>
Option<Guid> maybeScanId = _scannerProxyService.StartScan(FakeLibraryId.JellyfinCollections);
foreach (var scanId in maybeScanId)
{
"scan-jellyfin-collections", request.JellyfinMediaSourceId.ToString(CultureInfo.InvariantCulture)
};
try
{
var arguments = new List<string>
{
"scan-jellyfin-collections",
request.JellyfinMediaSourceId.ToString(CultureInfo.InvariantCulture),
GetBaseUrl(scanId),
};
if (request.ForceScan)
{
arguments.Add("--force");
if (request.ForceScan)
{
arguments.Add("--force");
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
}
finally
{
_scannerProxyService.EndScan(scanId);
}
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
return BaseError.New("Jellyfin collections are already scanning");
}
}

35
ErsatzTV.Application/Plex/Commands/CallPlexCollectionScannerHandler.cs

@ -2,7 +2,9 @@ using System.Globalization; @@ -2,7 +2,9 @@ using System.Globalization;
using ErsatzTV.Application.Libraries;
using ErsatzTV.Core;
using ErsatzTV.Core.Errors;
using ErsatzTV.Core.Interfaces.Metadata;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Metadata;
using ErsatzTV.FFmpeg.Runtime;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
@ -13,11 +15,15 @@ namespace ErsatzTV.Application.Plex; @@ -13,11 +15,15 @@ namespace ErsatzTV.Application.Plex;
public class CallPlexCollectionScannerHandler : CallLibraryScannerHandler<SynchronizePlexCollections>,
IRequestHandler<SynchronizePlexCollections, Either<BaseError, Unit>>
{
private readonly IScannerProxyService _scannerProxyService;
public CallPlexCollectionScannerHandler(
IDbContextFactory<TvContext> dbContextFactory,
IConfigElementRepository configElementRepository,
IScannerProxyService scannerProxyService,
IRuntimeInfo runtimeInfo) : base(dbContextFactory, configElementRepository, runtimeInfo)
{
_scannerProxyService = scannerProxyService;
}
public async Task<Either<BaseError, Unit>>
@ -68,16 +74,31 @@ public class CallPlexCollectionScannerHandler : CallLibraryScannerHandler<Synchr @@ -68,16 +74,31 @@ public class CallPlexCollectionScannerHandler : CallLibraryScannerHandler<Synchr
SynchronizePlexCollections request,
CancellationToken cancellationToken)
{
var arguments = new List<string>
Option<Guid> maybeScanId = _scannerProxyService.StartScan(FakeLibraryId.PlexCollections);
foreach (var scanId in maybeScanId)
{
"scan-plex-collections", request.PlexMediaSourceId.ToString(CultureInfo.InvariantCulture)
};
try
{
var arguments = new List<string>
{
"scan-plex-collections",
request.PlexMediaSourceId.ToString(CultureInfo.InvariantCulture),
GetBaseUrl(scanId)
};
if (request.ForceScan)
{
arguments.Add("--force");
if (request.ForceScan)
{
arguments.Add("--force");
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
}
finally
{
_scannerProxyService.EndScan(scanId);
}
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
return BaseError.New("Plex collections are already scanning");
}
}

35
ErsatzTV.Application/Plex/Commands/CallPlexNetworkScannerHandler.cs

@ -3,7 +3,9 @@ using ErsatzTV.Application.Libraries; @@ -3,7 +3,9 @@ using ErsatzTV.Application.Libraries;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Errors;
using ErsatzTV.Core.Interfaces.Metadata;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Metadata;
using ErsatzTV.FFmpeg.Runtime;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
@ -14,11 +16,15 @@ namespace ErsatzTV.Application.Plex; @@ -14,11 +16,15 @@ namespace ErsatzTV.Application.Plex;
public class CallPlexNetworkScannerHandler : CallLibraryScannerHandler<SynchronizePlexNetworks>,
IRequestHandler<SynchronizePlexNetworks, Either<BaseError, Unit>>
{
private readonly IScannerProxyService _scannerProxyService;
public CallPlexNetworkScannerHandler(
IDbContextFactory<TvContext> dbContextFactory,
IConfigElementRepository configElementRepository,
IScannerProxyService scannerProxyService,
IRuntimeInfo runtimeInfo) : base(dbContextFactory, configElementRepository, runtimeInfo)
{
_scannerProxyService = scannerProxyService;
}
public async Task<Either<BaseError, Unit>>
@ -70,16 +76,31 @@ public class CallPlexNetworkScannerHandler : CallLibraryScannerHandler<Synchroni @@ -70,16 +76,31 @@ public class CallPlexNetworkScannerHandler : CallLibraryScannerHandler<Synchroni
SynchronizePlexNetworks request,
CancellationToken cancellationToken)
{
var arguments = new List<string>
Option<Guid> maybeScanId = _scannerProxyService.StartScan(FakeLibraryId.PlexNetworks);
foreach (var scanId in maybeScanId)
{
"scan-plex-networks", request.PlexLibraryId.ToString(CultureInfo.InvariantCulture)
};
try
{
var arguments = new List<string>
{
"scan-plex-networks",
request.PlexLibraryId.ToString(CultureInfo.InvariantCulture),
GetBaseUrl(scanId)
};
if (request.ForceScan)
{
arguments.Add("--force");
if (request.ForceScan)
{
arguments.Add("--force");
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
}
finally
{
_scannerProxyService.EndScan(scanId);
}
}
return await base.PerformScan(parameters, arguments, cancellationToken).MapT(_ => Unit.Default);
return BaseError.New("Plex networks are already scanning");
}
}

10
ErsatzTV.Core/Metadata/FakeLibraryId.cs

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
namespace ErsatzTV.Core.Metadata;
public static class FakeLibraryId
{
public const int PlexCollections = -1;
public const int JellyfinCollections = -2;
public const int EmbyCollections = -3;
public const int PlexNetworks = -10;
}

3
ErsatzTV.Scanner/Application/Emby/Commands/SynchronizeEmbyCollections.cs

@ -2,4 +2,5 @@ @@ -2,4 +2,5 @@
namespace ErsatzTV.Scanner.Application.Emby;
public record SynchronizeEmbyCollections(int EmbyMediaSourceId, bool ForceScan) : IRequest<Either<BaseError, Unit>>;
public record SynchronizeEmbyCollections(string BaseUrl, int EmbyMediaSourceId, bool ForceScan)
: IRequest<Either<BaseError, Unit>>;

14
ErsatzTV.Scanner/Application/Emby/Commands/SynchronizeEmbyCollectionsHandler.cs

@ -3,12 +3,14 @@ using ErsatzTV.Core.Domain; @@ -3,12 +3,14 @@ using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Emby;
using ErsatzTV.Core.Interfaces.Emby;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Scanner.Core.Interfaces;
namespace ErsatzTV.Scanner.Application.Emby;
public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmbyCollections, Either<BaseError, Unit>>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly IScannerProxy _scannerProxy;
private readonly IEmbySecretStore _embySecretStore;
private readonly IMediaSourceRepository _mediaSourceRepository;
private readonly IEmbyCollectionScanner _scanner;
@ -17,12 +19,14 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby @@ -17,12 +19,14 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby
IMediaSourceRepository mediaSourceRepository,
IEmbySecretStore embySecretStore,
IEmbyCollectionScanner scanner,
IConfigElementRepository configElementRepository)
IConfigElementRepository configElementRepository,
IScannerProxy scannerProxy)
{
_mediaSourceRepository = mediaSourceRepository;
_embySecretStore = embySecretStore;
_scanner = scanner;
_configElementRepository = configElementRepository;
_scannerProxy = scannerProxy;
}
public async Task<Either<BaseError, Unit>> Handle(
@ -48,7 +52,8 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby @@ -48,7 +52,8 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby
connectionParameters,
connectionParameters.MediaSource,
request.ForceScan,
libraryRefreshInterval));
libraryRefreshInterval,
request.BaseUrl));
}
private Task<Validation<BaseError, int>> ValidateLibraryRefreshInterval(CancellationToken cancellationToken) =>
@ -82,6 +87,8 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby @@ -82,6 +87,8 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby
private async Task<Either<BaseError, Unit>> SynchronizeCollections(RequestParameters parameters)
{
_scannerProxy.SetBaseUrl(parameters.BaseUrl);
var lastScan = new DateTimeOffset(
parameters.MediaSource.LastCollectionsScan ?? SystemTime.MinValueUtc,
TimeSpan.Zero);
@ -108,7 +115,8 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby @@ -108,7 +115,8 @@ public class SynchronizeEmbyCollectionsHandler : IRequestHandler<SynchronizeEmby
ConnectionParameters ConnectionParameters,
EmbyMediaSource MediaSource,
bool ForceScan,
int LibraryRefreshInterval);
int LibraryRefreshInterval,
string BaseUrl);
private record ConnectionParameters(EmbyConnection ActiveConnection, EmbyMediaSource MediaSource)
{

2
ErsatzTV.Scanner/Application/Jellyfin/Commands/SynchronizeJellyfinCollections.cs

@ -2,5 +2,5 @@ @@ -2,5 +2,5 @@
namespace ErsatzTV.Scanner.Application.Jellyfin;
public record SynchronizeJellyfinCollections(int JellyfinMediaSourceId, bool ForceScan)
public record SynchronizeJellyfinCollections(string BaseUrl, int JellyfinMediaSourceId, bool ForceScan)
: IRequest<Either<BaseError, Unit>>;

14
ErsatzTV.Scanner/Application/Jellyfin/Commands/SynchronizeJellyfinCollectionsHandler.cs

@ -3,6 +3,7 @@ using ErsatzTV.Core.Domain; @@ -3,6 +3,7 @@ using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Jellyfin;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Jellyfin;
using ErsatzTV.Scanner.Core.Interfaces;
namespace ErsatzTV.Scanner.Application.Jellyfin;
@ -10,6 +11,7 @@ public class @@ -10,6 +11,7 @@ public class
SynchronizeJellyfinCollectionsHandler : IRequestHandler<SynchronizeJellyfinCollections, Either<BaseError, Unit>>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly IScannerProxy _scannerProxy;
private readonly IJellyfinSecretStore _jellyfinSecretStore;
private readonly IMediaSourceRepository _mediaSourceRepository;
private readonly IJellyfinCollectionScanner _scanner;
@ -18,12 +20,14 @@ public class @@ -18,12 +20,14 @@ public class
IMediaSourceRepository mediaSourceRepository,
IJellyfinSecretStore jellyfinSecretStore,
IJellyfinCollectionScanner scanner,
IConfigElementRepository configElementRepository)
IConfigElementRepository configElementRepository,
IScannerProxy scannerProxy)
{
_mediaSourceRepository = mediaSourceRepository;
_jellyfinSecretStore = jellyfinSecretStore;
_scanner = scanner;
_configElementRepository = configElementRepository;
_scannerProxy = scannerProxy;
}
@ -50,7 +54,8 @@ public class @@ -50,7 +54,8 @@ public class
connectionParameters,
connectionParameters.MediaSource,
request.ForceScan,
libraryRefreshInterval));
libraryRefreshInterval,
request.BaseUrl));
}
private Task<Validation<BaseError, int>> ValidateLibraryRefreshInterval(CancellationToken cancellationToken) =>
@ -83,6 +88,8 @@ public class @@ -83,6 +88,8 @@ public class
private async Task<Either<BaseError, Unit>> SynchronizeCollections(RequestParameters parameters)
{
_scannerProxy.SetBaseUrl(parameters.BaseUrl);
var lastScan = new DateTimeOffset(
parameters.MediaSource.LastCollectionsScan ?? SystemTime.MinValueUtc,
TimeSpan.Zero);
@ -110,7 +117,8 @@ public class @@ -110,7 +117,8 @@ public class
ConnectionParameters ConnectionParameters,
JellyfinMediaSource MediaSource,
bool ForceScan,
int LibraryRefreshInterval);
int LibraryRefreshInterval,
string BaseUrl);
private record ConnectionParameters(JellyfinMediaSource MediaSource, JellyfinConnection ActiveConnection)
{

3
ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexCollections.cs

@ -2,4 +2,5 @@ @@ -2,4 +2,5 @@
namespace ErsatzTV.Scanner.Application.Plex;
public record SynchronizePlexCollections(int PlexMediaSourceId, bool ForceScan) : IRequest<Either<BaseError, Unit>>;
public record SynchronizePlexCollections(string BaseUrl, int PlexMediaSourceId, bool ForceScan)
: IRequest<Either<BaseError, Unit>>;

14
ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexCollectionsHandler.cs

@ -3,12 +3,14 @@ using ErsatzTV.Core.Domain; @@ -3,12 +3,14 @@ using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Plex;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Plex;
using ErsatzTV.Scanner.Core.Interfaces;
namespace ErsatzTV.Scanner.Application.Plex;
public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlexCollections, Either<BaseError, Unit>>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly IScannerProxy _scannerProxy;
private readonly IMediaSourceRepository _mediaSourceRepository;
private readonly IPlexSecretStore _plexSecretStore;
private readonly IPlexCollectionScanner _scanner;
@ -17,12 +19,14 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex @@ -17,12 +19,14 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex
IMediaSourceRepository mediaSourceRepository,
IPlexSecretStore plexSecretStore,
IPlexCollectionScanner scanner,
IConfigElementRepository configElementRepository)
IConfigElementRepository configElementRepository,
IScannerProxy scannerProxy)
{
_mediaSourceRepository = mediaSourceRepository;
_plexSecretStore = plexSecretStore;
_scanner = scanner;
_configElementRepository = configElementRepository;
_scannerProxy = scannerProxy;
}
public async Task<Either<BaseError, Unit>> Handle(
@ -48,7 +52,8 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex @@ -48,7 +52,8 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex
connectionParameters,
connectionParameters.PlexMediaSource,
request.ForceScan,
libraryRefreshInterval));
libraryRefreshInterval,
request.BaseUrl));
}
private Task<Validation<BaseError, int>> ValidateLibraryRefreshInterval(CancellationToken cancellationToken) =>
@ -83,6 +88,8 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex @@ -83,6 +88,8 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex
RequestParameters parameters,
CancellationToken cancellationToken)
{
_scannerProxy.SetBaseUrl(parameters.BaseUrl);
var lastScan = new DateTimeOffset(
parameters.MediaSource.LastCollectionsScan ?? SystemTime.MinValueUtc,
TimeSpan.Zero);
@ -110,7 +117,8 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex @@ -110,7 +117,8 @@ public class SynchronizePlexCollectionsHandler : IRequestHandler<SynchronizePlex
ConnectionParameters ConnectionParameters,
PlexMediaSource MediaSource,
bool ForceScan,
int LibraryRefreshInterval);
int LibraryRefreshInterval,
string BaseUrl);
private record ConnectionParameters(PlexMediaSource PlexMediaSource, PlexConnection ActiveConnection)
{

3
ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexNetworks.cs

@ -2,4 +2,5 @@ @@ -2,4 +2,5 @@
namespace ErsatzTV.Scanner.Application.Plex;
public record SynchronizePlexNetworks(int PlexLibraryId, bool ForceScan) : IRequest<Either<BaseError, Unit>>;
public record SynchronizePlexNetworks(string BaseUrl, int PlexLibraryId, bool ForceScan)
: IRequest<Either<BaseError, Unit>>;

14
ErsatzTV.Scanner/Application/Plex/Commands/SynchronizePlexNetworksHandler.cs

@ -3,6 +3,7 @@ using ErsatzTV.Core.Domain; @@ -3,6 +3,7 @@ using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Plex;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Plex;
using ErsatzTV.Scanner.Core.Interfaces;
namespace ErsatzTV.Scanner.Application.Plex;
@ -12,6 +13,7 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet @@ -12,6 +13,7 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet
private readonly IMediaSourceRepository _mediaSourceRepository;
private readonly IPlexSecretStore _plexSecretStore;
private readonly IPlexTelevisionRepository _plexTelevisionRepository;
private readonly IScannerProxy _scannerProxy;
private readonly IPlexNetworkScanner _scanner;
public SynchronizePlexNetworksHandler(
@ -19,13 +21,15 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet @@ -19,13 +21,15 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet
IPlexSecretStore plexSecretStore,
IPlexNetworkScanner scanner,
IConfigElementRepository configElementRepository,
IPlexTelevisionRepository plexTelevisionRepository)
IPlexTelevisionRepository plexTelevisionRepository,
IScannerProxy scannerProxy)
{
_mediaSourceRepository = mediaSourceRepository;
_plexSecretStore = plexSecretStore;
_scanner = scanner;
_configElementRepository = configElementRepository;
_plexTelevisionRepository = plexTelevisionRepository;
_scannerProxy = scannerProxy;
}
public async Task<Either<BaseError, Unit>> Handle(
@ -52,7 +56,8 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet @@ -52,7 +56,8 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet
connectionParameters,
plexLibrary,
request.ForceScan,
libraryRefreshInterval));
libraryRefreshInterval,
request.BaseUrl));
}
private Task<Validation<BaseError, PlexLibrary>> PlexLibraryMustExist(
@ -92,6 +97,8 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet @@ -92,6 +97,8 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet
RequestParameters parameters,
CancellationToken cancellationToken)
{
_scannerProxy.SetBaseUrl(parameters.BaseUrl);
var lastScan = new DateTimeOffset(
parameters.Library.LastNetworksScan ?? SystemTime.MinValueUtc,
TimeSpan.Zero);
@ -120,7 +127,8 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet @@ -120,7 +127,8 @@ public class SynchronizePlexNetworksHandler : IRequestHandler<SynchronizePlexNet
ConnectionParameters ConnectionParameters,
PlexLibrary Library,
bool ForceScan,
int LibraryRefreshInterval);
int LibraryRefreshInterval,
string BaseUrl);
private record ConnectionParameters(PlexMediaSource PlexMediaSource, PlexConnection ActiveConnection)
{

16
ErsatzTV.Scanner/Core/Emby/EmbyCollectionScanner.cs

@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Emby;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.MediaSources;
using ErsatzTV.Scanner.Core.Interfaces;
using Microsoft.Extensions.Logging;
@ -62,10 +61,11 @@ public class EmbyCollectionScanner : IEmbyCollectionScanner @@ -62,10 +61,11 @@ public class EmbyCollectionScanner : IEmbyCollectionScanner
await _embyCollectionRepository.AddCollection(collection);
}
await SyncCollectionItems(address, apiKey, collection);
// save collection etag
await _embyCollectionRepository.SetEtag(collection);
if (await SyncCollectionItems(address, apiKey, collection))
{
// save collection etag
await _embyCollectionRepository.SetEtag(collection);
}
}
// remove missing collections (and remove any lingering tags from those collections)
@ -83,7 +83,7 @@ public class EmbyCollectionScanner : IEmbyCollectionScanner @@ -83,7 +83,7 @@ public class EmbyCollectionScanner : IEmbyCollectionScanner
return Unit.Default;
}
private async Task SyncCollectionItems(
private async Task<bool> SyncCollectionItems(
string address,
string apiKey,
EmbyCollection collection)
@ -111,11 +111,15 @@ public class EmbyCollectionScanner : IEmbyCollectionScanner @@ -111,11 +111,15 @@ public class EmbyCollectionScanner : IEmbyCollectionScanner
if (!await _scannerProxy.ReindexMediaItems(changedIds, CancellationToken.None))
{
_logger.LogWarning("Failed to reindex media items from scanner process");
return false;
}
return true;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to synchronize Emby collection {Name}", collection.Name);
return false;
}
}
}

16
ErsatzTV.Scanner/Core/Jellyfin/JellyfinCollectionScanner.cs

@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Jellyfin;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.MediaSources;
using ErsatzTV.Scanner.Core.Interfaces;
using Microsoft.Extensions.Logging;
@ -63,10 +62,11 @@ public class JellyfinCollectionScanner : IJellyfinCollectionScanner @@ -63,10 +62,11 @@ public class JellyfinCollectionScanner : IJellyfinCollectionScanner
await _jellyfinCollectionRepository.AddCollection(collection);
}
await SyncCollectionItems(address, apiKey, mediaSourceId, collection);
// save collection etag
await _jellyfinCollectionRepository.SetEtag(collection);
if (await SyncCollectionItems(address, apiKey, mediaSourceId, collection))
{
// save collection etag
await _jellyfinCollectionRepository.SetEtag(collection);
}
}
// remove missing collections (and remove any lingering tags from those collections)
@ -85,7 +85,7 @@ public class JellyfinCollectionScanner : IJellyfinCollectionScanner @@ -85,7 +85,7 @@ public class JellyfinCollectionScanner : IJellyfinCollectionScanner
return Unit.Default;
}
private async Task SyncCollectionItems(
private async Task<bool> SyncCollectionItems(
string address,
string apiKey,
int mediaSourceId,
@ -115,11 +115,15 @@ public class JellyfinCollectionScanner : IJellyfinCollectionScanner @@ -115,11 +115,15 @@ public class JellyfinCollectionScanner : IJellyfinCollectionScanner
if (!await _scannerProxy.ReindexMediaItems(changedIds, CancellationToken.None))
{
_logger.LogWarning("Failed to reindex media items from scanner process");
return false;
}
return true;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to synchronize Jellyfin collection {Name}", collection.Name);
return false;
}
}
}

16
ErsatzTV.Scanner/Core/Plex/PlexCollectionScanner.cs

@ -2,7 +2,6 @@ using ErsatzTV.Core; @@ -2,7 +2,6 @@ using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Plex;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.MediaSources;
using ErsatzTV.Core.Plex;
using ErsatzTV.Scanner.Core.Interfaces;
using Microsoft.Extensions.Logging;
@ -64,10 +63,11 @@ public class PlexCollectionScanner : IPlexCollectionScanner @@ -64,10 +63,11 @@ public class PlexCollectionScanner : IPlexCollectionScanner
await _plexCollectionRepository.AddCollection(collection);
}
await SyncCollectionItems(connection, token, collection, cancellationToken);
// save collection etag
await _plexCollectionRepository.SetEtag(collection);
if (await SyncCollectionItems(connection, token, collection, cancellationToken))
{
// save collection etag
await _plexCollectionRepository.SetEtag(collection);
}
}
// remove missing collections (and remove any lingering tags from those collections)
@ -85,7 +85,7 @@ public class PlexCollectionScanner : IPlexCollectionScanner @@ -85,7 +85,7 @@ public class PlexCollectionScanner : IPlexCollectionScanner
return Unit.Default;
}
private async Task SyncCollectionItems(
private async Task<bool> SyncCollectionItems(
PlexConnection connection,
PlexServerAuthToken token,
PlexCollection collection,
@ -116,11 +116,15 @@ public class PlexCollectionScanner : IPlexCollectionScanner @@ -116,11 +116,15 @@ public class PlexCollectionScanner : IPlexCollectionScanner
if (!await _scannerProxy.ReindexMediaItems(changedIds, CancellationToken.None))
{
_logger.LogWarning("Failed to reindex media items from scanner process");
return false;
}
return true;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to synchronize Plex collection {Name}", collection.Name);
return false;
}
}
}

1
ErsatzTV.Scanner/Core/Plex/PlexNetworkScanner.cs

@ -2,7 +2,6 @@ using ErsatzTV.Core; @@ -2,7 +2,6 @@ using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Plex;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.MediaSources;
using ErsatzTV.Core.Plex;
using ErsatzTV.Scanner.Core.Interfaces;
using Microsoft.Extensions.Logging;

32
ErsatzTV.Scanner/Worker.cs

@ -83,10 +83,12 @@ public class Worker : BackgroundService @@ -83,10 +83,12 @@ public class Worker : BackgroundService
var scanPlexCollectionsCommand = new Command("scan-plex-collections", "Scan Plex collections");
scanPlexCollectionsCommand.Arguments.Add(mediaSourceIdArgument);
scanPlexCollectionsCommand.Arguments.Add(baseUrlArgument);
scanPlexCollectionsCommand.Options.Add(forceOption);
var scanPlexNetworksCommand = new Command("scan-plex-networks", "Scan Plex networks");
scanPlexNetworksCommand.Arguments.Add(libraryIdArgument);
scanPlexNetworksCommand.Arguments.Add(baseUrlArgument);
scanPlexNetworksCommand.Options.Add(forceOption);
var scanEmbyCommand = new Command("scan-emby", "Scan an Emby library");
@ -97,6 +99,7 @@ public class Worker : BackgroundService @@ -97,6 +99,7 @@ public class Worker : BackgroundService
var scanEmbyCollectionsCommand = new Command("scan-emby-collections", "Scan Emby collections");
scanEmbyCollectionsCommand.Arguments.Add(mediaSourceIdArgument);
scanEmbyCollectionsCommand.Arguments.Add(baseUrlArgument);
scanEmbyCollectionsCommand.Options.Add(forceOption);
var scanJellyfinCommand = new Command("scan-jellyfin", "Scan a Jellyfin library");
@ -107,6 +110,7 @@ public class Worker : BackgroundService @@ -107,6 +110,7 @@ public class Worker : BackgroundService
var scanJellyfinCollectionsCommand = new Command("scan-jellyfin-collections", "Scan Jellyfin collections");
scanJellyfinCollectionsCommand.Arguments.Add(mediaSourceIdArgument);
scanJellyfinCollectionsCommand.Arguments.Add(baseUrlArgument);
scanJellyfinCollectionsCommand.Options.Add(forceOption);
// Show-specific scanning commands
@ -188,11 +192,16 @@ public class Worker : BackgroundService @@ -188,11 +192,16 @@ public class Worker : BackgroundService
SetProcessPriority(force);
int mediaSourceId = parseResult.GetValue(mediaSourceIdArgument);
string? baseUrl = parseResult.GetValue(baseUrlArgument);
if (baseUrl is null)
{
return;
}
using IServiceScope scope = _serviceScopeFactory.CreateScope();
IMediator mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
var scan = new SynchronizePlexCollections(mediaSourceId, force);
var scan = new SynchronizePlexCollections(baseUrl, mediaSourceId, force);
await mediator.Send(scan, token);
}
});
@ -205,11 +214,16 @@ public class Worker : BackgroundService @@ -205,11 +214,16 @@ public class Worker : BackgroundService
SetProcessPriority(force);
int libraryId = parseResult.GetValue(libraryIdArgument);
string? baseUrl = parseResult.GetValue(baseUrlArgument);
if (baseUrl is null)
{
return;
}
using IServiceScope scope = _serviceScopeFactory.CreateScope();
IMediator mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
var scan = new SynchronizePlexNetworks(libraryId, force);
var scan = new SynchronizePlexNetworks(baseUrl, libraryId, force);
await mediator.Send(scan, token);
}
});
@ -245,11 +259,16 @@ public class Worker : BackgroundService @@ -245,11 +259,16 @@ public class Worker : BackgroundService
SetProcessPriority(force);
int mediaSourceId = parseResult.GetValue(mediaSourceIdArgument);
string? baseUrl = parseResult.GetValue(baseUrlArgument);
if (baseUrl is null)
{
return;
}
using IServiceScope scope = _serviceScopeFactory.CreateScope();
IMediator mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
var scan = new SynchronizeEmbyCollections(mediaSourceId, force);
var scan = new SynchronizeEmbyCollections(baseUrl, mediaSourceId, force);
await mediator.Send(scan, token);
}
});
@ -285,11 +304,16 @@ public class Worker : BackgroundService @@ -285,11 +304,16 @@ public class Worker : BackgroundService
SetProcessPriority(force);
int mediaSourceId = parseResult.GetValue(mediaSourceIdArgument);
string? baseUrl = parseResult.GetValue(baseUrlArgument);
if (baseUrl is null)
{
return;
}
using IServiceScope scope = _serviceScopeFactory.CreateScope();
IMediator mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
var scan = new SynchronizeJellyfinCollections(mediaSourceId, force);
var scan = new SynchronizeJellyfinCollections(baseUrl, mediaSourceId, force);
await mediator.Send(scan, token);
}
});

Loading…
Cancel
Save