async fixes (#128)

* refactor local metadata provider

* resolve async warnings

* more async fixes
This commit is contained in:
Jason Dove
2021-04-03 11:01:20 -05:00
committed by GitHub
parent 633586ddba
commit d4a2197dfa
38 changed files with 525 additions and 649 deletions
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Metadata;
using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ErsatzTV.Services.RunOnce
{
public class CacheCleanerService : IHostedService
{
private readonly ILogger<CacheCleanerService> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
public CacheCleanerService(
IServiceScopeFactory serviceScopeFactory,
ILogger<CacheCleanerService> logger)
{
_serviceScopeFactory = serviceScopeFactory;
_logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
using IServiceScope scope = _serviceScopeFactory.CreateScope();
await using TvContext dbContext = scope.ServiceProvider.GetRequiredService<TvContext>();
if (Directory.Exists(FileSystemLayout.LegacyImageCacheFolder))
{
_logger.LogInformation("Migrating channel logos from legacy image cache folder");
List<string> logos = await dbContext.Channels
.SelectMany(c => c.Artwork)
.Where(a => a.ArtworkKind == ArtworkKind.Logo)
.Map(a => a.Path)
.ToListAsync(cancellationToken);
ILocalFileSystem localFileSystem = scope.ServiceProvider.GetRequiredService<ILocalFileSystem>();
foreach (string logo in logos)
{
string legacyPath = Path.Combine(FileSystemLayout.LegacyImageCacheFolder, logo);
if (File.Exists(legacyPath))
{
string subfolder = logo.Substring(0, 2);
string newPath = Path.Combine(FileSystemLayout.LogoCacheFolder, subfolder, logo);
await localFileSystem.CopyFile(legacyPath, newPath);
}
}
_logger.LogInformation("Deleting legacy image cache folder");
Directory.Delete(FileSystemLayout.LegacyImageCacheFolder, true);
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}
@@ -0,0 +1,38 @@
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ErsatzTV.Services.RunOnce
{
public class DatabaseMigratorService : IHostedService
{
private readonly ILogger<DatabaseMigratorService> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
public DatabaseMigratorService(
IServiceScopeFactory serviceScopeFactory,
ILogger<DatabaseMigratorService> logger)
{
_serviceScopeFactory = serviceScopeFactory;
_logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Applying database migrations");
using IServiceScope scope = _serviceScopeFactory.CreateScope();
await using TvContext dbContext = scope.ServiceProvider.GetRequiredService<TvContext>();
await dbContext.Database.MigrateAsync(cancellationToken);
await DbInitializer.Initialize(dbContext, cancellationToken);
_logger.LogInformation("Done applying database migrations");
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}
+28 -23
View File
@@ -15,50 +15,55 @@ using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ErsatzTV.Services
{
public class SchedulerService : IHostedService
public class SchedulerService : BackgroundService
{
private readonly ChannelWriter<IBackgroundServiceRequest> _channel;
private readonly IEntityLocker _entityLocker;
private readonly ILogger<SchedulerService> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
private Timer _timer;
public SchedulerService(
IServiceScopeFactory serviceScopeFactory,
ChannelWriter<IBackgroundServiceRequest> channel,
IEntityLocker entityLocker)
IEntityLocker entityLocker,
ILogger<SchedulerService> logger)
{
_serviceScopeFactory = serviceScopeFactory;
_channel = channel;
_entityLocker = entityLocker;
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
_timer = new Timer(
async _ => await DoWork(cancellationToken),
null,
TimeSpan.FromSeconds(0), // fire immediately
TimeSpan.FromHours(1)); // repeat every hour
while (!cancellationToken.IsCancellationRequested)
{
if (!cancellationToken.IsCancellationRequested)
{
await DoWork(cancellationToken);
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
await Task.Delay(TimeSpan.FromHours(1), cancellationToken);
}
}
private async Task DoWork(CancellationToken cancellationToken)
{
await RebuildSearchIndex(cancellationToken);
await BuildPlayouts(cancellationToken);
await ScanLocalMediaSources(cancellationToken);
await ScanPlexMediaSources(cancellationToken);
try
{
await RebuildSearchIndex(cancellationToken);
await BuildPlayouts(cancellationToken);
await ScanLocalMediaSources(cancellationToken);
await ScanPlexMediaSources(cancellationToken);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error during scheduler run");
}
}
private async Task BuildPlayouts(CancellationToken cancellationToken)
@@ -114,7 +119,7 @@ namespace ErsatzTV.Services
}
}
private async Task RebuildSearchIndex(CancellationToken cancellationToken) =>
await _channel.WriteAsync(new RebuildSearchIndex(), cancellationToken);
private ValueTask RebuildSearchIndex(CancellationToken cancellationToken) =>
_channel.WriteAsync(new RebuildSearchIndex(), cancellationToken);
}
}