diff --git a/ErsatzTV.Application/Streaming/Commands/StartFFmpegSessionHandler.cs b/ErsatzTV.Application/Streaming/Commands/StartFFmpegSessionHandler.cs index 4f8a3daae..72b941b57 100644 --- a/ErsatzTV.Application/Streaming/Commands/StartFFmpegSessionHandler.cs +++ b/ErsatzTV.Application/Streaming/Commands/StartFFmpegSessionHandler.cs @@ -8,6 +8,7 @@ using ErsatzTV.Core.Errors; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Metadata; using LanguageExt; +using Microsoft.Extensions.Logging; using static LanguageExt.Prelude; namespace ErsatzTV.Application.Streaming.Commands @@ -15,24 +16,29 @@ namespace ErsatzTV.Application.Streaming.Commands public class StartFFmpegSessionHandler : MediatR.IRequestHandler> { private readonly ChannelWriter _channel; + private readonly ILogger _logger; private readonly IFFmpegSegmenterService _ffmpegSegmenterService; private readonly ILocalFileSystem _localFileSystem; public StartFFmpegSessionHandler( IFFmpegSegmenterService ffmpegSegmenterService, ILocalFileSystem localFileSystem, - ChannelWriter channel) + ChannelWriter channel, + ILogger logger) { _ffmpegSegmenterService = ffmpegSegmenterService; _localFileSystem = localFileSystem; _channel = channel; + _logger = logger; } public Task> Handle(StartFFmpegSession request, CancellationToken cancellationToken) => Validate(request) .MapT(_ => StartProcess(request)) // this weirdness is needed to maintain the error type (.ToEitherAsync() just gives BaseError) +#pragma warning disable VSTHRD103 .Bind(v => v.ToEither().MapLeft(seq => seq.Head()).MapAsync, Unit>(identity)); +#pragma warning restore VSTHRD103 private async Task StartProcess(StartFFmpegSession request) { @@ -44,13 +50,20 @@ namespace ErsatzTV.Application.Streaming.Commands return Unit.Default; } - private Task> Validate(StartFFmpegSession request) => - ProcessMustNotExist(request) - .BindT(_ => FolderMustBeEmpty(request)); + private async Task> Validate(StartFFmpegSession request) + { + Validation existResult = await ProcessMustNotExist(request); + if (existResult.IsFail) + { + return existResult; + } + + return await FolderMustBeEmpty(request); + } private Task> ProcessMustNotExist(StartFFmpegSession request) => Optional(_ffmpegSegmenterService.ProcessExistsForChannel(request.ChannelNumber)) - .Filter(containsKey => containsKey == false) + .Filter(exists => exists == false) .Map(_ => Unit.Default) .ToValidation(new ChannelHasProcess()) .AsTask(); @@ -58,6 +71,8 @@ namespace ErsatzTV.Application.Streaming.Commands private Task> FolderMustBeEmpty(StartFFmpegSession request) { string folder = Path.Combine(FileSystemLayout.TranscodeFolder, request.ChannelNumber); + _logger.LogInformation("Preparing transcode folder {Folder}", folder); + _localFileSystem.EnsureFolderExists(folder); _localFileSystem.EmptyFolder(folder); diff --git a/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs b/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs index ee489b6f2..bb630cadb 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs @@ -146,7 +146,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg var localStatisticsProvider = new LocalStatisticsProvider( metadataRepository.Object, - new LocalFileSystem(), + new LocalFileSystem(new Mock>().Object), new Mock>().Object); await localStatisticsProvider.RefreshStatistics( diff --git a/ErsatzTV.Core/Metadata/LocalFileSystem.cs b/ErsatzTV.Core/Metadata/LocalFileSystem.cs index c7979875d..ba07fdc72 100644 --- a/ErsatzTV.Core/Metadata/LocalFileSystem.cs +++ b/ErsatzTV.Core/Metadata/LocalFileSystem.cs @@ -5,17 +5,32 @@ using System.Threading.Tasks; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Metadata; using LanguageExt; +using Microsoft.Extensions.Logging; using static LanguageExt.Prelude; namespace ErsatzTV.Core.Metadata { public class LocalFileSystem : ILocalFileSystem { + private readonly ILogger _logger; + + public LocalFileSystem(ILogger logger) + { + _logger = logger; + } + public Unit EnsureFolderExists(string folder) { - if (!Directory.Exists(folder)) + try { - Directory.CreateDirectory(folder); + if (!Directory.Exists(folder)) + { + Directory.CreateDirectory(folder); + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to ensure folder exists at {Folder}", folder); } return Unit.Default; @@ -59,14 +74,21 @@ namespace ErsatzTV.Core.Metadata public Unit EmptyFolder(string folder) { - foreach (string file in Directory.GetFiles(folder)) + try { - File.Delete(file); - } + foreach (string file in Directory.GetFiles(folder)) + { + File.Delete(file); + } - foreach (string directory in Directory.GetDirectories(folder)) + foreach (string directory in Directory.GetDirectories(folder)) + { + Directory.Delete(directory, true); + } + } + catch (Exception ex) { - Directory.Delete(directory, true); + _logger.LogWarning(ex, "Failed to empty folder at {Folder}", folder); } return Unit.Default;