mirror of https://github.com/ErsatzTV/ErsatzTV.git
12 changed files with 159 additions and 83 deletions
@ -1,68 +1,35 @@
@@ -1,68 +1,35 @@
|
||||
using System.IO.Compression; |
||||
using System.Text.Json; |
||||
using System.Text.Json.Serialization; |
||||
using ErsatzTV.Application.MediaItems; |
||||
using ErsatzTV.Application.Troubleshooting.Queries; |
||||
using ErsatzTV.Core; |
||||
using ErsatzTV.Core.Interfaces.Metadata; |
||||
|
||||
namespace ErsatzTV.Application.Troubleshooting; |
||||
|
||||
public class ArchiveTroubleshootingResultsHandler(IMediator mediator, ILocalFileSystem localFileSystem) |
||||
public class ArchiveTroubleshootingResultsHandler(ILocalFileSystem localFileSystem) |
||||
: IRequestHandler<ArchiveTroubleshootingResults, Option<string>> |
||||
{ |
||||
private static readonly JsonSerializerOptions Options = new() |
||||
{ |
||||
Converters = { new JsonStringEnumConverter() }, |
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, |
||||
WriteIndented = true |
||||
}; |
||||
|
||||
public async Task<Option<string>> Handle(ArchiveTroubleshootingResults request, CancellationToken cancellationToken) |
||||
public Task<Option<string>> Handle(ArchiveTroubleshootingResults request, CancellationToken cancellationToken) |
||||
{ |
||||
string tempFile = Path.GetTempFileName(); |
||||
using ZipArchive zipArchive = ZipFile.Open(tempFile, ZipArchiveMode.Update); |
||||
|
||||
string transcodeFolder = Path.Combine(FileSystemLayout.TranscodeFolder, ".troubleshooting"); |
||||
|
||||
bool hasReport = false; |
||||
foreach (string file in localFileSystem.ListFiles(transcodeFolder)) |
||||
var hasReport = false; |
||||
foreach (string file in localFileSystem.ListFiles(FileSystemLayout.TranscodeTroubleshootingFolder)) |
||||
{ |
||||
string fileName = Path.GetFileName(file); |
||||
|
||||
// add to archive
|
||||
if (Path.GetFileName(file).StartsWith("ffmpeg-", StringComparison.InvariantCultureIgnoreCase)) |
||||
if (fileName.StartsWith("ffmpeg-", StringComparison.OrdinalIgnoreCase)) |
||||
{ |
||||
hasReport = true; |
||||
zipArchive.CreateEntryFromFile(file, Path.GetFileName(file)); |
||||
zipArchive.CreateEntryFromFile(file, fileName); |
||||
} |
||||
} |
||||
|
||||
Either<BaseError, MediaItemInfo> maybeMediaItemInfo = await mediator.Send(new GetMediaItemInfo(request.MediaItemId), cancellationToken); |
||||
foreach (MediaItemInfo info in maybeMediaItemInfo.RightToSeq()) |
||||
{ |
||||
string infoJson = JsonSerializer.Serialize(info, Options); |
||||
string tempMediaInfoFile = Path.GetTempFileName(); |
||||
await File.WriteAllTextAsync(tempMediaInfoFile, infoJson, cancellationToken); |
||||
zipArchive.CreateEntryFromFile(tempMediaInfoFile, "media_info.json"); |
||||
} |
||||
|
||||
TroubleshootingInfo troubleshootingInfo = await mediator.Send(new GetTroubleshootingInfo(), cancellationToken); |
||||
|
||||
string troubleshootingInfoJson = JsonSerializer.Serialize( |
||||
new |
||||
if (Path.GetExtension(file).Equals(".json", StringComparison.OrdinalIgnoreCase)) |
||||
{ |
||||
troubleshootingInfo.Version, |
||||
Environment = troubleshootingInfo.Environment.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value), |
||||
troubleshootingInfo.Health, |
||||
troubleshootingInfo.FFmpegSettings, |
||||
troubleshootingInfo.Channels, |
||||
troubleshootingInfo.FFmpegProfiles |
||||
}, |
||||
Options); |
||||
|
||||
string tempTroubleshootingInfoFile = Path.GetTempFileName(); |
||||
await File.WriteAllTextAsync(tempTroubleshootingInfoFile, troubleshootingInfoJson, cancellationToken); |
||||
zipArchive.CreateEntryFromFile(tempTroubleshootingInfoFile, "troubleshooting_info.json"); |
||||
zipArchive.CreateEntryFromFile(file, fileName); |
||||
} |
||||
} |
||||
|
||||
return hasReport ? tempFile : Option<string>.None; |
||||
return Task.FromResult(hasReport ? tempFile : Option<string>.None); |
||||
} |
||||
} |
||||
|
@ -1,5 +1,9 @@
@@ -1,5 +1,9 @@
|
||||
using CliWrap; |
||||
using ErsatzTV.Application.MediaItems; |
||||
|
||||
namespace ErsatzTV.Application.Troubleshooting; |
||||
|
||||
public record StartTroubleshootingPlayback(Command Command) : IRequest, IFFmpegWorkerRequest; |
||||
public record StartTroubleshootingPlayback( |
||||
Command Command, |
||||
MediaItemInfo MediaItemInfo, |
||||
TroubleshootingInfo TroubleshootingInfo) : IRequest, IFFmpegWorkerRequest; |
||||
|
@ -1,33 +1,71 @@
@@ -1,33 +1,71 @@
|
||||
using System.Text.Json; |
||||
using System.Text.Json.Serialization; |
||||
using CliWrap; |
||||
using CliWrap.Buffered; |
||||
using ErsatzTV.Core; |
||||
using ErsatzTV.Core.Interfaces.Locking; |
||||
using ErsatzTV.Core.Notifications; |
||||
using Microsoft.Extensions.Logging; |
||||
|
||||
namespace ErsatzTV.Application.Troubleshooting; |
||||
|
||||
public class StartTroubleshootingPlaybackHandler( |
||||
IMediator mediator, |
||||
IEntityLocker entityLocker, |
||||
ILogger<StartTroubleshootingPlaybackHandler> logger) |
||||
: IRequestHandler<StartTroubleshootingPlayback> |
||||
{ |
||||
private static readonly JsonSerializerOptions Options = new() |
||||
{ |
||||
Converters = { new JsonStringEnumConverter() }, |
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, |
||||
WriteIndented = true |
||||
}; |
||||
|
||||
public async Task Handle(StartTroubleshootingPlayback request, CancellationToken cancellationToken) |
||||
{ |
||||
logger.LogDebug("ffmpeg troubleshooting arguments {FFmpegArguments}", request.Command.Arguments); |
||||
try |
||||
{ |
||||
// write media info without title
|
||||
string infoJson = JsonSerializer.Serialize(request.MediaItemInfo with { Title = null }, Options); |
||||
await File.WriteAllTextAsync( |
||||
Path.Combine(FileSystemLayout.TranscodeTroubleshootingFolder, "media_info.json"), |
||||
infoJson, |
||||
cancellationToken); |
||||
|
||||
BufferedCommandResult result = await request.Command |
||||
.WithValidation(CommandResultValidation.None) |
||||
.ExecuteBufferedAsync(cancellationToken); |
||||
// write troubleshooting info
|
||||
string troubleshootingInfoJson = JsonSerializer.Serialize( |
||||
new |
||||
{ |
||||
request.TroubleshootingInfo.Version, |
||||
Environment = request.TroubleshootingInfo.Environment.OrderBy(x => x.Key) |
||||
.ToDictionary(x => x.Key, x => x.Value), |
||||
request.TroubleshootingInfo.Health, |
||||
request.TroubleshootingInfo.FFmpegSettings, |
||||
request.TroubleshootingInfo.FFmpegProfiles, |
||||
request.TroubleshootingInfo.Watermarks |
||||
}, |
||||
Options); |
||||
await File.WriteAllTextAsync( |
||||
Path.Combine(FileSystemLayout.TranscodeTroubleshootingFolder, "troubleshooting_info.json"), |
||||
troubleshootingInfoJson, |
||||
cancellationToken); |
||||
|
||||
entityLocker.UnlockTroubleshootingPlayback(); |
||||
logger.LogDebug("ffmpeg troubleshooting arguments {FFmpegArguments}", request.Command.Arguments); |
||||
|
||||
BufferedCommandResult result = await request.Command |
||||
.WithValidation(CommandResultValidation.None) |
||||
.ExecuteBufferedAsync(cancellationToken); |
||||
|
||||
logger.LogInformation("Troubleshooting playback completed with exit code {ExitCode}", result.ExitCode); |
||||
await mediator.Publish( |
||||
new PlaybackTroubleshootingCompletedNotification(result.ExitCode), |
||||
cancellationToken); |
||||
|
||||
foreach (KeyValuePair<string, string> env in request.Command.EnvironmentVariables) |
||||
logger.LogDebug("Troubleshooting playback completed with exit code {ExitCode}", result.ExitCode); |
||||
} |
||||
finally |
||||
{ |
||||
logger.LogInformation("{Key} => {Value}", env.Key, env.Value); |
||||
entityLocker.UnlockTroubleshootingPlayback(); |
||||
} |
||||
|
||||
// TODO: something with the result ???
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
using MediatR; |
||||
|
||||
namespace ErsatzTV.Core.Notifications; |
||||
|
||||
public record PlaybackTroubleshootingCompletedNotification(int ExitCode) : INotification; |
Loading…
Reference in new issue