better search index thread fix (#143)
* Revert "fix search index threading (#141)"
This reverts commit 3fb6da0754.
* better search index thread fix
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ErsatzTV.Core;
|
using ErsatzTV.Core;
|
||||||
using ErsatzTV.Core.Domain;
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Core.Interfaces.Metadata;
|
||||||
using ErsatzTV.Core.Interfaces.Repositories;
|
using ErsatzTV.Core.Interfaces.Repositories;
|
||||||
using ErsatzTV.Core.Interfaces.Search;
|
using ErsatzTV.Core.Interfaces.Search;
|
||||||
using LanguageExt;
|
using LanguageExt;
|
||||||
@@ -14,6 +15,7 @@ namespace ErsatzTV.Application.Search.Commands
|
|||||||
public class RebuildSearchIndexHandler : MediatR.IRequestHandler<RebuildSearchIndex, Unit>
|
public class RebuildSearchIndexHandler : MediatR.IRequestHandler<RebuildSearchIndex, Unit>
|
||||||
{
|
{
|
||||||
private readonly IConfigElementRepository _configElementRepository;
|
private readonly IConfigElementRepository _configElementRepository;
|
||||||
|
private readonly ILocalFileSystem _localFileSystem;
|
||||||
private readonly ILogger<RebuildSearchIndexHandler> _logger;
|
private readonly ILogger<RebuildSearchIndexHandler> _logger;
|
||||||
private readonly ISearchIndex _searchIndex;
|
private readonly ISearchIndex _searchIndex;
|
||||||
private readonly ISearchRepository _searchRepository;
|
private readonly ISearchRepository _searchRepository;
|
||||||
@@ -22,18 +24,22 @@ namespace ErsatzTV.Application.Search.Commands
|
|||||||
ISearchIndex searchIndex,
|
ISearchIndex searchIndex,
|
||||||
ISearchRepository searchRepository,
|
ISearchRepository searchRepository,
|
||||||
IConfigElementRepository configElementRepository,
|
IConfigElementRepository configElementRepository,
|
||||||
|
ILocalFileSystem localFileSystem,
|
||||||
ILogger<RebuildSearchIndexHandler> logger)
|
ILogger<RebuildSearchIndexHandler> logger)
|
||||||
{
|
{
|
||||||
_searchIndex = searchIndex;
|
_searchIndex = searchIndex;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_searchRepository = searchRepository;
|
_searchRepository = searchRepository;
|
||||||
_configElementRepository = configElementRepository;
|
_configElementRepository = configElementRepository;
|
||||||
|
_localFileSystem = localFileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Unit> Handle(RebuildSearchIndex request, CancellationToken cancellationToken)
|
public async Task<Unit> Handle(RebuildSearchIndex request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
bool indexFolderExists = Directory.Exists(FileSystemLayout.SearchIndexFolder);
|
bool indexFolderExists = Directory.Exists(FileSystemLayout.SearchIndexFolder);
|
||||||
|
|
||||||
|
await _searchIndex.Initialize(_localFileSystem);
|
||||||
|
|
||||||
if (!indexFolderExists ||
|
if (!indexFolderExists ||
|
||||||
await _configElementRepository.GetValue<int>(ConfigElementKey.SearchIndexVersion) <
|
await _configElementRepository.GetValue<int>(ConfigElementKey.SearchIndexVersion) <
|
||||||
_searchIndex.Version)
|
_searchIndex.Version)
|
||||||
@@ -41,7 +47,7 @@ namespace ErsatzTV.Application.Search.Commands
|
|||||||
_logger.LogDebug("Migrating search index to version {Version}", _searchIndex.Version);
|
_logger.LogDebug("Migrating search index to version {Version}", _searchIndex.Version);
|
||||||
|
|
||||||
List<int> itemIds = await _searchRepository.GetItemIdsToIndex();
|
List<int> itemIds = await _searchRepository.GetItemIdsToIndex();
|
||||||
await _searchIndex.Rebuild(itemIds);
|
await _searchIndex.Rebuild(_searchRepository, itemIds);
|
||||||
|
|
||||||
Option<ConfigElement> maybeVersion =
|
Option<ConfigElement> maybeVersion =
|
||||||
await _configElementRepository.Get(ConfigElementKey.SearchIndexVersion);
|
await _configElementRepository.Get(ConfigElementKey.SearchIndexVersion);
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ErsatzTV.Core.Domain;
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Core.Interfaces.Metadata;
|
||||||
|
using ErsatzTV.Core.Interfaces.Repositories;
|
||||||
using ErsatzTV.Core.Search;
|
using ErsatzTV.Core.Search;
|
||||||
using LanguageExt;
|
using LanguageExt;
|
||||||
|
|
||||||
namespace ErsatzTV.Core.Interfaces.Search
|
namespace ErsatzTV.Core.Interfaces.Search
|
||||||
{
|
{
|
||||||
public interface ISearchIndex
|
public interface ISearchIndex : IDisposable
|
||||||
{
|
{
|
||||||
public int Version { get; }
|
public int Version { get; }
|
||||||
Task<bool> Initialize();
|
Task<bool> Initialize(ILocalFileSystem localFileSystem);
|
||||||
Task<Unit> Rebuild(List<int> itemIds);
|
Task<Unit> Rebuild(ISearchRepository searchRepository, List<int> itemIds);
|
||||||
Task<Unit> AddItems(List<MediaItem> items);
|
Task<Unit> AddItems(List<MediaItem> items);
|
||||||
Task<Unit> UpdateItems(List<MediaItem> items);
|
Task<Unit> UpdateItems(List<MediaItem> items);
|
||||||
Task<Unit> RemoveItems(List<int> ids);
|
Task<Unit> RemoveItems(List<int> ids);
|
||||||
Task<SearchResult> Search(string query, int skip, int limit, string searchField = "");
|
Task<SearchResult> Search(string query, int skip, int limit, string searchField = "");
|
||||||
|
void Commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_searchIndex.Commit();
|
||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_searchIndex.Commit();
|
||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ namespace ErsatzTV.Core.Metadata
|
|||||||
List<int> ids = await _televisionRepository.DeleteEmptyShows(libraryPath);
|
List<int> ids = await _televisionRepository.DeleteEmptyShows(libraryPath);
|
||||||
await _searchIndex.RemoveItems(ids);
|
await _searchIndex.RemoveItems(ids);
|
||||||
|
|
||||||
|
_searchIndex.Commit();
|
||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ namespace ErsatzTV.Core.Plex
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_searchIndex.Commit();
|
||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ namespace ErsatzTV.Core.Plex
|
|||||||
|
|
||||||
await _mediator.Publish(new LibraryScanProgress(plexMediaSourceLibrary.Id, 0));
|
await _mediator.Publish(new LibraryScanProgress(plexMediaSourceLibrary.Id, 0));
|
||||||
|
|
||||||
|
_searchIndex.Commit();
|
||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
},
|
},
|
||||||
error =>
|
error =>
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
|||||||
.ThenInclude(mm => mm.Tags)
|
.ThenInclude(mm => mm.Tags)
|
||||||
.Include(mi => (mi as Show).ShowMetadata)
|
.Include(mi => (mi as Show).ShowMetadata)
|
||||||
.ThenInclude(mm => mm.Studios)
|
.ThenInclude(mm => mm.Studios)
|
||||||
|
.Include(mi => (mi as MusicVideo).MusicVideoMetadata)
|
||||||
|
.ThenInclude(mm => mm.Genres)
|
||||||
|
.Include(mi => (mi as MusicVideo).MusicVideoMetadata)
|
||||||
|
.ThenInclude(mm => mm.Tags)
|
||||||
|
.Include(mi => (mi as MusicVideo).MusicVideoMetadata)
|
||||||
|
.ThenInclude(mm => mm.Studios)
|
||||||
.OrderBy(mi => mi.Id)
|
.OrderBy(mi => mi.Id)
|
||||||
.SingleOrDefaultAsync(mi => mi.Id == id)
|
.SingleOrDefaultAsync(mi => mi.Id == id)
|
||||||
.Map(Optional);
|
.Map(Optional);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ using Query = Lucene.Net.Search.Query;
|
|||||||
|
|
||||||
namespace ErsatzTV.Infrastructure.Search
|
namespace ErsatzTV.Infrastructure.Search
|
||||||
{
|
{
|
||||||
public class SearchIndex : ISearchIndex
|
public sealed class SearchIndex : ISearchIndex
|
||||||
{
|
{
|
||||||
private const LuceneVersion AppLuceneVersion = LuceneVersion.LUCENE_48;
|
private const LuceneVersion AppLuceneVersion = LuceneVersion.LUCENE_48;
|
||||||
|
|
||||||
@@ -45,65 +45,52 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
private const string ShowType = "show";
|
private const string ShowType = "show";
|
||||||
private const string MusicVideoType = "music_video";
|
private const string MusicVideoType = "music_video";
|
||||||
|
|
||||||
private static bool _isRebuilding;
|
|
||||||
|
|
||||||
private readonly ILocalFileSystem _localFileSystem;
|
|
||||||
private readonly ILogger<SearchIndex> _logger;
|
private readonly ILogger<SearchIndex> _logger;
|
||||||
|
|
||||||
private readonly ISearchRepository _searchRepository;
|
private FSDirectory _directory;
|
||||||
|
private IndexWriter _writer;
|
||||||
|
|
||||||
public SearchIndex(
|
public SearchIndex(ILogger<SearchIndex> logger) => _logger = logger;
|
||||||
ILocalFileSystem localFileSystem,
|
|
||||||
ISearchRepository searchRepository,
|
|
||||||
ILogger<SearchIndex> logger)
|
|
||||||
{
|
|
||||||
_localFileSystem = localFileSystem;
|
|
||||||
_searchRepository = searchRepository;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Version => 2;
|
public int Version => 2;
|
||||||
|
|
||||||
public Task<bool> Initialize()
|
public Task<bool> Initialize(ILocalFileSystem localFileSystem)
|
||||||
{
|
{
|
||||||
_localFileSystem.EnsureFolderExists(FileSystemLayout.SearchIndexFolder);
|
localFileSystem.EnsureFolderExists(FileSystemLayout.SearchIndexFolder);
|
||||||
|
|
||||||
|
_directory = FSDirectory.Open(FileSystemLayout.SearchIndexFolder);
|
||||||
|
var analyzer = new StandardAnalyzer(AppLuceneVersion);
|
||||||
|
var indexConfig = new IndexWriterConfig(AppLuceneVersion, analyzer)
|
||||||
|
{ OpenMode = OpenMode.CREATE_OR_APPEND };
|
||||||
|
_writer = new IndexWriter(_directory, indexConfig);
|
||||||
|
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Unit> Rebuild(List<int> itemIds)
|
public async Task<Unit> Rebuild(ISearchRepository searchRepository, List<int> itemIds)
|
||||||
{
|
{
|
||||||
_isRebuilding = true;
|
|
||||||
|
|
||||||
await Initialize();
|
|
||||||
|
|
||||||
using var dir = FSDirectory.Open(FileSystemLayout.SearchIndexFolder);
|
|
||||||
var analyzer = new StandardAnalyzer(AppLuceneVersion);
|
|
||||||
var indexConfig = new IndexWriterConfig(AppLuceneVersion, analyzer) { OpenMode = OpenMode.CREATE };
|
|
||||||
using var writer = new IndexWriter(dir, indexConfig);
|
|
||||||
|
|
||||||
foreach (int id in itemIds)
|
foreach (int id in itemIds)
|
||||||
{
|
{
|
||||||
Option<MediaItem> maybeMediaItem = await _searchRepository.GetItemToIndex(id);
|
Option<MediaItem> maybeMediaItem = await searchRepository.GetItemToIndex(id);
|
||||||
if (maybeMediaItem.IsSome)
|
if (maybeMediaItem.IsSome)
|
||||||
{
|
{
|
||||||
MediaItem mediaItem = maybeMediaItem.ValueUnsafe();
|
MediaItem mediaItem = maybeMediaItem.ValueUnsafe();
|
||||||
switch (mediaItem)
|
switch (mediaItem)
|
||||||
{
|
{
|
||||||
case Movie movie:
|
case Movie movie:
|
||||||
UpdateMovie(movie, writer);
|
UpdateMovie(movie);
|
||||||
break;
|
break;
|
||||||
case Show show:
|
case Show show:
|
||||||
UpdateShow(show, writer);
|
UpdateShow(show);
|
||||||
break;
|
break;
|
||||||
case MusicVideo musicVideo:
|
case MusicVideo musicVideo:
|
||||||
UpdateMusicVideo(musicVideo, writer);
|
UpdateMusicVideo(musicVideo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_isRebuilding = false;
|
_writer.Commit();
|
||||||
|
|
||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,23 +98,18 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
|
|
||||||
public Task<Unit> UpdateItems(List<MediaItem> items)
|
public Task<Unit> UpdateItems(List<MediaItem> items)
|
||||||
{
|
{
|
||||||
using var dir = FSDirectory.Open(FileSystemLayout.SearchIndexFolder);
|
|
||||||
var analyzer = new StandardAnalyzer(AppLuceneVersion);
|
|
||||||
var indexConfig = new IndexWriterConfig(AppLuceneVersion, analyzer) { OpenMode = OpenMode.APPEND };
|
|
||||||
using var writer = new IndexWriter(dir, indexConfig);
|
|
||||||
|
|
||||||
foreach (MediaItem item in items)
|
foreach (MediaItem item in items)
|
||||||
{
|
{
|
||||||
switch (item)
|
switch (item)
|
||||||
{
|
{
|
||||||
case Movie movie:
|
case Movie movie:
|
||||||
UpdateMovie(movie, writer);
|
UpdateMovie(movie);
|
||||||
break;
|
break;
|
||||||
case Show show:
|
case Show show:
|
||||||
UpdateShow(show, writer);
|
UpdateShow(show);
|
||||||
break;
|
break;
|
||||||
case MusicVideo musicVideo:
|
case MusicVideo musicVideo:
|
||||||
UpdateMusicVideo(musicVideo, writer);
|
UpdateMusicVideo(musicVideo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,14 +119,9 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
|
|
||||||
public Task<Unit> RemoveItems(List<int> ids)
|
public Task<Unit> RemoveItems(List<int> ids)
|
||||||
{
|
{
|
||||||
using var dir = FSDirectory.Open(FileSystemLayout.SearchIndexFolder);
|
|
||||||
var analyzer = new StandardAnalyzer(AppLuceneVersion);
|
|
||||||
var indexConfig = new IndexWriterConfig(AppLuceneVersion, analyzer) { OpenMode = OpenMode.APPEND };
|
|
||||||
using var writer = new IndexWriter(dir, indexConfig);
|
|
||||||
|
|
||||||
foreach (int id in ids)
|
foreach (int id in ids)
|
||||||
{
|
{
|
||||||
writer.DeleteDocuments(new Term(IdField, id.ToString()));
|
_writer.DeleteDocuments(new Term(IdField, id.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(Unit.Default);
|
return Task.FromResult(Unit.Default);
|
||||||
@@ -152,14 +129,12 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
|
|
||||||
public Task<SearchResult> Search(string searchQuery, int skip, int limit, string searchField = "")
|
public Task<SearchResult> Search(string searchQuery, int skip, int limit, string searchField = "")
|
||||||
{
|
{
|
||||||
if (_isRebuilding ||
|
if (string.IsNullOrWhiteSpace(searchQuery.Replace("*", string.Empty).Replace("?", string.Empty)))
|
||||||
string.IsNullOrWhiteSpace(searchQuery.Replace("*", string.Empty).Replace("?", string.Empty)))
|
|
||||||
{
|
{
|
||||||
return new SearchResult(new List<SearchItem>(), 0).AsTask();
|
return new SearchResult(new List<SearchItem>(), 0).AsTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
using var dir = FSDirectory.Open(FileSystemLayout.SearchIndexFolder);
|
using DirectoryReader reader = _writer.GetReader(true);
|
||||||
using var reader = DirectoryReader.Open(dir);
|
|
||||||
var searcher = new IndexSearcher(reader);
|
var searcher = new IndexSearcher(reader);
|
||||||
int hitsLimit = skip + limit;
|
int hitsLimit = skip + limit;
|
||||||
using var analyzer = new StandardAnalyzer(AppLuceneVersion);
|
using var analyzer = new StandardAnalyzer(AppLuceneVersion);
|
||||||
@@ -182,6 +157,14 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
return searchResult.AsTask();
|
return searchResult.AsTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Commit() => _writer.Commit();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_writer?.Dispose();
|
||||||
|
_directory?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
private static Option<SearchPageMap> GetSearchPageMap(
|
private static Option<SearchPageMap> GetSearchPageMap(
|
||||||
IndexSearcher searcher,
|
IndexSearcher searcher,
|
||||||
Query query,
|
Query query,
|
||||||
@@ -228,7 +211,7 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
return new SearchPageMap(map);
|
return new SearchPageMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMovie(Movie movie, IndexWriter writer)
|
private void UpdateMovie(Movie movie)
|
||||||
{
|
{
|
||||||
Option<MovieMetadata> maybeMetadata = movie.MovieMetadata.HeadOrNone();
|
Option<MovieMetadata> maybeMetadata = movie.MovieMetadata.HeadOrNone();
|
||||||
if (maybeMetadata.IsSome)
|
if (maybeMetadata.IsSome)
|
||||||
@@ -277,7 +260,7 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
doc.Add(new TextField(StudioField, studio.Name, Field.Store.NO));
|
doc.Add(new TextField(StudioField, studio.Name, Field.Store.NO));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.UpdateDocument(new Term(IdField, movie.Id.ToString()), doc);
|
_writer.UpdateDocument(new Term(IdField, movie.Id.ToString()), doc);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -287,7 +270,7 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateShow(Show show, IndexWriter writer)
|
private void UpdateShow(Show show)
|
||||||
{
|
{
|
||||||
Option<ShowMetadata> maybeMetadata = show.ShowMetadata.HeadOrNone();
|
Option<ShowMetadata> maybeMetadata = show.ShowMetadata.HeadOrNone();
|
||||||
if (maybeMetadata.IsSome)
|
if (maybeMetadata.IsSome)
|
||||||
@@ -336,7 +319,7 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
doc.Add(new TextField(StudioField, studio.Name, Field.Store.NO));
|
doc.Add(new TextField(StudioField, studio.Name, Field.Store.NO));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.UpdateDocument(new Term(IdField, show.Id.ToString()), doc);
|
_writer.UpdateDocument(new Term(IdField, show.Id.ToString()), doc);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -346,7 +329,7 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMusicVideo(MusicVideo musicVideo, IndexWriter writer)
|
private void UpdateMusicVideo(MusicVideo musicVideo)
|
||||||
{
|
{
|
||||||
Option<MusicVideoMetadata> maybeMetadata = musicVideo.MusicVideoMetadata.HeadOrNone();
|
Option<MusicVideoMetadata> maybeMetadata = musicVideo.MusicVideoMetadata.HeadOrNone();
|
||||||
if (maybeMetadata.IsSome)
|
if (maybeMetadata.IsSome)
|
||||||
@@ -396,7 +379,7 @@ namespace ErsatzTV.Infrastructure.Search
|
|||||||
doc.Add(new TextField(StudioField, studio.Name, Field.Store.NO));
|
doc.Add(new TextField(StudioField, studio.Name, Field.Store.NO));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.UpdateDocument(new Term(IdField, musicVideo.Id.ToString()), doc);
|
_writer.UpdateDocument(new Term(IdField, musicVideo.Id.ToString()), doc);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -185,6 +185,7 @@ namespace ErsatzTV
|
|||||||
services.AddSingleton<IPlexSecretStore, PlexSecretStore>();
|
services.AddSingleton<IPlexSecretStore, PlexSecretStore>();
|
||||||
services.AddSingleton<IPlexTvApiClient, PlexTvApiClient>(); // TODO: does this need to be singleton?
|
services.AddSingleton<IPlexTvApiClient, PlexTvApiClient>(); // TODO: does this need to be singleton?
|
||||||
services.AddSingleton<IEntityLocker, EntityLocker>();
|
services.AddSingleton<IEntityLocker, EntityLocker>();
|
||||||
|
services.AddSingleton<ISearchIndex, SearchIndex>();
|
||||||
AddChannel<IBackgroundServiceRequest>(services);
|
AddChannel<IBackgroundServiceRequest>(services);
|
||||||
AddChannel<IPlexBackgroundServiceRequest>(services);
|
AddChannel<IPlexBackgroundServiceRequest>(services);
|
||||||
|
|
||||||
@@ -217,7 +218,6 @@ namespace ErsatzTV
|
|||||||
services.AddScoped<IPlexMovieLibraryScanner, PlexMovieLibraryScanner>();
|
services.AddScoped<IPlexMovieLibraryScanner, PlexMovieLibraryScanner>();
|
||||||
services.AddScoped<IPlexTelevisionLibraryScanner, PlexTelevisionLibraryScanner>();
|
services.AddScoped<IPlexTelevisionLibraryScanner, PlexTelevisionLibraryScanner>();
|
||||||
services.AddScoped<IPlexServerApiClient, PlexServerApiClient>();
|
services.AddScoped<IPlexServerApiClient, PlexServerApiClient>();
|
||||||
services.AddScoped<ISearchIndex, SearchIndex>();
|
|
||||||
services.AddScoped<IRuntimeInfo, RuntimeInfo>();
|
services.AddScoped<IRuntimeInfo, RuntimeInfo>();
|
||||||
services.AddScoped<IPlexPathReplacementService, PlexPathReplacementService>();
|
services.AddScoped<IPlexPathReplacementService, PlexPathReplacementService>();
|
||||||
services.AddScoped<IFFmpegStreamSelector, FFmpegStreamSelector>();
|
services.AddScoped<IFFmpegStreamSelector, FFmpegStreamSelector>();
|
||||||
|
|||||||
Reference in New Issue
Block a user