Browse Source

bug fixes and logging (#786)

pull/787/head
Jason Dove 4 years ago committed by GitHub
parent
commit
daf7114ce2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 2
      ErsatzTV.Application/Streaming/HlsSessionWorker.cs
  3. 12
      ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs
  4. 4
      ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs
  5. 24
      ErsatzTV.Infrastructure/Images/ImageCache.cs
  6. 21
      ErsatzTV/Services/RunOnce/RebuildSearchIndexService.cs
  7. 5
      ErsatzTV/Services/SchedulerService.cs
  8. 4
      ErsatzTV/Startup.cs

2
CHANGELOG.md

@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix processing local movie fallback metadata - Fix processing local movie fallback metadata
- Fix search edge case where very recently added items (hours) would not be returned by relative date queries - Fix search edge case where very recently added items (hours) would not be returned by relative date queries
- Fix search index validation on startup; improper validation was causing a rebuild with every startup - Fix search index validation on startup; improper validation was causing a rebuild with every startup
- Block library scanning until search index has been recreated/upgraded
- Fix occasional erroneous log messages when HLS channel playback times out because all clients have left
### Added ### Added
- Add `show_genre` and `show_tag` to search index for seasons and episodes - Add `show_genre` and `show_tag` to search index for seasons and episodes

2
ErsatzTV.Application/Streaming/HlsSessionWorker.cs

@ -276,7 +276,7 @@ public class HlsSessionWorker : IHlsSessionWorker
return false; return false;
} }
} }
catch (TaskCanceledException) catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)
{ {
_logger.LogInformation("Terminating HLS process for channel {Channel}", _channelNumber); _logger.LogInformation("Terminating HLS process for channel {Channel}", _channelNumber);
return false; return false;

12
ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs

@ -14,6 +14,7 @@ using ErsatzTV.Core.Scheduling;
using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions; using ErsatzTV.Infrastructure.Extensions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace ErsatzTV.Application.Streaming; namespace ErsatzTV.Application.Streaming;
@ -24,6 +25,7 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
private readonly IFFmpegProcessService _ffmpegProcessService; private readonly IFFmpegProcessService _ffmpegProcessService;
private readonly IJellyfinPathReplacementService _jellyfinPathReplacementService; private readonly IJellyfinPathReplacementService _jellyfinPathReplacementService;
private readonly ILocalFileSystem _localFileSystem; private readonly ILocalFileSystem _localFileSystem;
private readonly ILogger<GetPlayoutItemProcessByChannelNumberHandler> _logger;
private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly IMediaCollectionRepository _mediaCollectionRepository;
private readonly IPlexPathReplacementService _plexPathReplacementService; private readonly IPlexPathReplacementService _plexPathReplacementService;
private readonly ISongVideoGenerator _songVideoGenerator; private readonly ISongVideoGenerator _songVideoGenerator;
@ -39,7 +41,8 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
IMediaCollectionRepository mediaCollectionRepository, IMediaCollectionRepository mediaCollectionRepository,
ITelevisionRepository televisionRepository, ITelevisionRepository televisionRepository,
IArtistRepository artistRepository, IArtistRepository artistRepository,
ISongVideoGenerator songVideoGenerator) ISongVideoGenerator songVideoGenerator,
ILogger<GetPlayoutItemProcessByChannelNumberHandler> logger)
: base(dbContextFactory) : base(dbContextFactory)
{ {
_ffmpegProcessService = ffmpegProcessService; _ffmpegProcessService = ffmpegProcessService;
@ -51,6 +54,7 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
_televisionRepository = televisionRepository; _televisionRepository = televisionRepository;
_artistRepository = artistRepository; _artistRepository = artistRepository;
_songVideoGenerator = songVideoGenerator; _songVideoGenerator = songVideoGenerator;
_logger = logger;
} }
protected override async Task<Either<BaseError, PlayoutItemProcessModel>> GetProcess( protected override async Task<Either<BaseError, PlayoutItemProcessModel>> GetProcess(
@ -201,6 +205,12 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
DateTimeOffset finish = maybeDuration.Match(d => now.Add(d), () => now); DateTimeOffset finish = maybeDuration.Match(d => now.Add(d), () => now);
_logger.LogWarning(
"Error locating playout item {@Error}. Will display error from {Start} to {Finish}",
error,
now,
finish);
switch (error) switch (error)
{ {
case UnableToLocatePlayoutItem: case UnableToLocatePlayoutItem:

4
ErsatzTV.Application/Subtitles/Commands/ExtractEmbeddedSubtitlesHandler.cs

@ -155,7 +155,7 @@ public class ExtractEmbeddedSubtitlesHandler : IRequestHandler<ExtractEmbeddedSu
return Unit.Default; return Unit.Default;
} }
catch (TaskCanceledException) catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)
{ {
return Unit.Default; return Unit.Default;
} }
@ -210,7 +210,7 @@ public class ExtractEmbeddedSubtitlesHandler : IRequestHandler<ExtractEmbeddedSu
.ToListAsync(cancellationToken); .ToListAsync(cancellationToken);
result.AddRange(otherVideoIds); result.AddRange(otherVideoIds);
} }
catch (TaskCanceledException) catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)
{ {
// do nothing // do nothing
} }

24
ErsatzTV.Infrastructure/Images/ImageCache.cs

@ -121,22 +121,19 @@ public class ImageCache : IImageCache
string targetFile = GetPathForImage(fileName, artworkKind, Option<int>.None); string targetFile = GetPathForImage(fileName, artworkKind, Option<int>.None);
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
using (FileStream fs = File.OpenRead(targetFile)) using (var image = await Image.LoadAsync<Rgba32>(targetFile))
{ {
using (var image = await Image.LoadAsync<Rgba32>(fs)) // resize before calculating blur hash; it doesn't need giant images
if (image.Height > 200)
{ {
// resize before calculating blur hash; it doesn't need giant images image.Mutate(i => i.Resize(0, 200));
if (image.Height > 200)
{
image.Mutate(i => i.Resize(0, 200));
}
else if (image.Width > 200)
{
image.Mutate(i => i.Resize(200, 0));
}
return Blurhasher.Encode(image, x, y);
} }
else if (image.Width > 200)
{
image.Mutate(i => i.Resize(200, 0));
}
return Blurhasher.Encode(image, x, y);
} }
} }
@ -151,6 +148,7 @@ public class ImageCache : IImageCache
_localFileSystem.EnsureFolderExists(folder); _localFileSystem.EnsureFolderExists(folder);
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
// ReSharper disable once UseAwaitUsing
using (FileStream fs = File.OpenWrite(targetFile)) using (FileStream fs = File.OpenWrite(targetFile))
{ {
using (Image<Rgb24> image = Blurhasher.Decode(blurHash, targetSize.Width, targetSize.Height)) using (Image<Rgb24> image = Blurhasher.Decode(blurHash, targetSize.Width, targetSize.Height))

21
ErsatzTV/Services/RunOnce/RebuildSearchIndexService.cs

@ -0,0 +1,21 @@
using ErsatzTV.Application.Search;
using MediatR;
namespace ErsatzTV.Services.RunOnce;
public class RebuildSearchIndexService : IHostedService
{
private readonly IServiceScopeFactory _serviceScopeFactory;
public RebuildSearchIndexService(IServiceScopeFactory serviceScopeFactory) =>
_serviceScopeFactory = serviceScopeFactory;
public async Task StartAsync(CancellationToken cancellationToken)
{
using IServiceScope scope = _serviceScopeFactory.CreateScope();
IMediator mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
await mediator.Send(new RebuildSearchIndex(), cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

5
ErsatzTV/Services/SchedulerService.cs

@ -8,7 +8,6 @@ using ErsatzTV.Application.MediaCollections;
using ErsatzTV.Application.MediaSources; using ErsatzTV.Application.MediaSources;
using ErsatzTV.Application.Playouts; using ErsatzTV.Application.Playouts;
using ErsatzTV.Application.Plex; using ErsatzTV.Application.Plex;
using ErsatzTV.Application.Search;
using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Locking; using ErsatzTV.Core.Interfaces.Locking;
using ErsatzTV.Core.Scheduling; using ErsatzTV.Core.Scheduling;
@ -93,7 +92,6 @@ public class SchedulerService : BackgroundService
try try
{ {
await DeleteOrphanedArtwork(cancellationToken); await DeleteOrphanedArtwork(cancellationToken);
await RebuildSearchIndex(cancellationToken);
await BuildPlayouts(cancellationToken); await BuildPlayouts(cancellationToken);
await ScanLocalMediaSources(cancellationToken); await ScanLocalMediaSources(cancellationToken);
await ScanPlexMediaSources(cancellationToken); await ScanPlexMediaSources(cancellationToken);
@ -266,9 +264,6 @@ public class SchedulerService : BackgroundService
} }
} }
private ValueTask RebuildSearchIndex(CancellationToken cancellationToken) =>
_workerChannel.WriteAsync(new RebuildSearchIndex(), cancellationToken);
private ValueTask DeleteOrphanedArtwork(CancellationToken cancellationToken) => private ValueTask DeleteOrphanedArtwork(CancellationToken cancellationToken) =>
_workerChannel.WriteAsync(new DeleteOrphanedArtwork(), cancellationToken); _workerChannel.WriteAsync(new DeleteOrphanedArtwork(), cancellationToken);
} }

4
ErsatzTV/Startup.cs

@ -418,11 +418,15 @@ public class Startup
// services.AddTransient(typeof(IRequestHandler<,>), typeof(GetRecentLogEntriesHandler<>)); // services.AddTransient(typeof(IRequestHandler<,>), typeof(GetRecentLogEntriesHandler<>));
// run-once/blocking startup services
services.AddHostedService<EndpointValidatorService>(); services.AddHostedService<EndpointValidatorService>();
services.AddHostedService<DatabaseMigratorService>(); services.AddHostedService<DatabaseMigratorService>();
services.AddHostedService<CacheCleanerService>(); services.AddHostedService<CacheCleanerService>();
services.AddHostedService<ResourceExtractorService>(); services.AddHostedService<ResourceExtractorService>();
services.AddHostedService<PlatformSettingsService>(); services.AddHostedService<PlatformSettingsService>();
services.AddHostedService<RebuildSearchIndexService>();
// background services
services.AddHostedService<EmbyService>(); services.AddHostedService<EmbyService>();
services.AddHostedService<JellyfinService>(); services.AddHostedService<JellyfinService>();
services.AddHostedService<PlexService>(); services.AddHostedService<PlexService>();

Loading…
Cancel
Save