Browse Source

fix transcode folder preparation (#404)

pull/405/head
Jason Dove 5 years ago committed by GitHub
parent
commit
8cd9b23787
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      ErsatzTV.Application/Streaming/Commands/StartFFmpegSessionHandler.cs
  2. 2
      ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs
  3. 36
      ErsatzTV.Core/Metadata/LocalFileSystem.cs

25
ErsatzTV.Application/Streaming/Commands/StartFFmpegSessionHandler.cs

@ -8,6 +8,7 @@ using ErsatzTV.Core.Errors;
using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg;
using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Metadata;
using LanguageExt; using LanguageExt;
using Microsoft.Extensions.Logging;
using static LanguageExt.Prelude; using static LanguageExt.Prelude;
namespace ErsatzTV.Application.Streaming.Commands namespace ErsatzTV.Application.Streaming.Commands
@ -15,24 +16,29 @@ namespace ErsatzTV.Application.Streaming.Commands
public class StartFFmpegSessionHandler : MediatR.IRequestHandler<StartFFmpegSession, Either<BaseError, Unit>> public class StartFFmpegSessionHandler : MediatR.IRequestHandler<StartFFmpegSession, Either<BaseError, Unit>>
{ {
private readonly ChannelWriter<IFFmpegWorkerRequest> _channel; private readonly ChannelWriter<IFFmpegWorkerRequest> _channel;
private readonly ILogger<StartFFmpegSessionHandler> _logger;
private readonly IFFmpegSegmenterService _ffmpegSegmenterService; private readonly IFFmpegSegmenterService _ffmpegSegmenterService;
private readonly ILocalFileSystem _localFileSystem; private readonly ILocalFileSystem _localFileSystem;
public StartFFmpegSessionHandler( public StartFFmpegSessionHandler(
IFFmpegSegmenterService ffmpegSegmenterService, IFFmpegSegmenterService ffmpegSegmenterService,
ILocalFileSystem localFileSystem, ILocalFileSystem localFileSystem,
ChannelWriter<IFFmpegWorkerRequest> channel) ChannelWriter<IFFmpegWorkerRequest> channel,
ILogger<StartFFmpegSessionHandler> logger)
{ {
_ffmpegSegmenterService = ffmpegSegmenterService; _ffmpegSegmenterService = ffmpegSegmenterService;
_localFileSystem = localFileSystem; _localFileSystem = localFileSystem;
_channel = channel; _channel = channel;
_logger = logger;
} }
public Task<Either<BaseError, Unit>> Handle(StartFFmpegSession request, CancellationToken cancellationToken) => public Task<Either<BaseError, Unit>> Handle(StartFFmpegSession request, CancellationToken cancellationToken) =>
Validate(request) Validate(request)
.MapT(_ => StartProcess(request)) .MapT(_ => StartProcess(request))
// this weirdness is needed to maintain the error type (.ToEitherAsync() just gives BaseError) // 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<BaseError, Task<Unit>, Unit>(identity)); .Bind(v => v.ToEither().MapLeft(seq => seq.Head()).MapAsync<BaseError, Task<Unit>, Unit>(identity));
#pragma warning restore VSTHRD103
private async Task<Unit> StartProcess(StartFFmpegSession request) private async Task<Unit> StartProcess(StartFFmpegSession request)
{ {
@ -44,13 +50,20 @@ namespace ErsatzTV.Application.Streaming.Commands
return Unit.Default; return Unit.Default;
} }
private Task<Validation<BaseError, Unit>> Validate(StartFFmpegSession request) => private async Task<Validation<BaseError, Unit>> Validate(StartFFmpegSession request)
ProcessMustNotExist(request) {
.BindT(_ => FolderMustBeEmpty(request)); Validation<BaseError, Unit> existResult = await ProcessMustNotExist(request);
if (existResult.IsFail)
{
return existResult;
}
return await FolderMustBeEmpty(request);
}
private Task<Validation<BaseError, Unit>> ProcessMustNotExist(StartFFmpegSession request) => private Task<Validation<BaseError, Unit>> ProcessMustNotExist(StartFFmpegSession request) =>
Optional(_ffmpegSegmenterService.ProcessExistsForChannel(request.ChannelNumber)) Optional(_ffmpegSegmenterService.ProcessExistsForChannel(request.ChannelNumber))
.Filter(containsKey => containsKey == false) .Filter(exists => exists == false)
.Map(_ => Unit.Default) .Map(_ => Unit.Default)
.ToValidation<BaseError>(new ChannelHasProcess()) .ToValidation<BaseError>(new ChannelHasProcess())
.AsTask(); .AsTask();
@ -58,6 +71,8 @@ namespace ErsatzTV.Application.Streaming.Commands
private Task<Validation<BaseError, Unit>> FolderMustBeEmpty(StartFFmpegSession request) private Task<Validation<BaseError, Unit>> FolderMustBeEmpty(StartFFmpegSession request)
{ {
string folder = Path.Combine(FileSystemLayout.TranscodeFolder, request.ChannelNumber); string folder = Path.Combine(FileSystemLayout.TranscodeFolder, request.ChannelNumber);
_logger.LogInformation("Preparing transcode folder {Folder}", folder);
_localFileSystem.EnsureFolderExists(folder); _localFileSystem.EnsureFolderExists(folder);
_localFileSystem.EmptyFolder(folder); _localFileSystem.EmptyFolder(folder);

2
ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs

@ -146,7 +146,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg
var localStatisticsProvider = new LocalStatisticsProvider( var localStatisticsProvider = new LocalStatisticsProvider(
metadataRepository.Object, metadataRepository.Object,
new LocalFileSystem(), new LocalFileSystem(new Mock<ILogger<LocalFileSystem>>().Object),
new Mock<ILogger<LocalStatisticsProvider>>().Object); new Mock<ILogger<LocalStatisticsProvider>>().Object);
await localStatisticsProvider.RefreshStatistics( await localStatisticsProvider.RefreshStatistics(

36
ErsatzTV.Core/Metadata/LocalFileSystem.cs

@ -5,17 +5,32 @@ using System.Threading.Tasks;
using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Metadata;
using LanguageExt; using LanguageExt;
using Microsoft.Extensions.Logging;
using static LanguageExt.Prelude; using static LanguageExt.Prelude;
namespace ErsatzTV.Core.Metadata namespace ErsatzTV.Core.Metadata
{ {
public class LocalFileSystem : ILocalFileSystem public class LocalFileSystem : ILocalFileSystem
{ {
private readonly ILogger<LocalFileSystem> _logger;
public LocalFileSystem(ILogger<LocalFileSystem> logger)
{
_logger = logger;
}
public Unit EnsureFolderExists(string folder) public Unit EnsureFolderExists(string folder)
{ {
if (!Directory.Exists(folder)) try
{
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
}
catch (Exception ex)
{ {
Directory.CreateDirectory(folder); _logger.LogWarning(ex, "Failed to ensure folder exists at {Folder}", folder);
} }
return Unit.Default; return Unit.Default;
@ -59,14 +74,21 @@ namespace ErsatzTV.Core.Metadata
public Unit EmptyFolder(string folder) 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; return Unit.Default;

Loading…
Cancel
Save