feat: harden recording lifecycle and refresh fnOS UI
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
using LiveRecorder.Domain.Entities;
|
||||
using LiveRecorder.Domain.Enums;
|
||||
using LiveRecorder.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LiveRecorder.Tests;
|
||||
|
||||
public sealed class ShutdownRecoveryDispatchTests : IDisposable
|
||||
{
|
||||
private readonly string _temporaryDirectory = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
$"liverecorder-shutdown-dispatch-{Guid.NewGuid():N}");
|
||||
|
||||
[Fact]
|
||||
public async Task RecoveredProcessingTask_CreatesDurableCompletionDispatch()
|
||||
{
|
||||
Directory.CreateDirectory(_temporaryDirectory);
|
||||
var outputPath = Path.Combine(_temporaryDirectory, "recovered.mp4");
|
||||
await File.WriteAllBytesAsync(outputPath, [1, 2, 3, 4]);
|
||||
|
||||
var options = new DbContextOptionsBuilder<LiveRecorderDbContext>()
|
||||
.UseInMemoryDatabase($"shutdown-recovery-dispatch-{Guid.NewGuid():N}")
|
||||
.Options;
|
||||
await using var context = new LiveRecorderDbContext(options);
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var room = new LiveRoom(
|
||||
LivePlatformType.Douyin,
|
||||
"https://live.example/recovery",
|
||||
"recovery-room",
|
||||
"https://live.example/recovery",
|
||||
now.AddHours(-1));
|
||||
var session = new RecordSession(
|
||||
room.Id,
|
||||
"origin",
|
||||
RecordOutputFormat.Mp4,
|
||||
RecordSaveMode.Segmented,
|
||||
now.AddMinutes(-30));
|
||||
session.MarkStopped(now, "Application shutdown deferred MP4 finalization.");
|
||||
var task = new RecordTask(
|
||||
room.Id,
|
||||
session.Id,
|
||||
1,
|
||||
"origin",
|
||||
RecordOutputFormat.Mp4,
|
||||
now.AddMinutes(-30));
|
||||
task.MarkStarting("https://stream.example/recovery", outputPath, now.AddMinutes(-30));
|
||||
task.MarkProcessing("Waiting for restart recovery.", now);
|
||||
var result = new RecordResult(
|
||||
task.Id,
|
||||
outputPath,
|
||||
new FileInfo(outputPath).Length,
|
||||
1_800,
|
||||
null,
|
||||
0,
|
||||
RecordTaskStatus.Processing,
|
||||
task.ErrorMessage,
|
||||
now);
|
||||
|
||||
context.AddRange(room, session, task, result);
|
||||
await context.SaveChangesAsync();
|
||||
Assert.Empty(context.RecordCompletionDispatches);
|
||||
|
||||
task.MarkCompleted(now.AddMinutes(1), 1_800);
|
||||
session.MarkCompleted(now.AddMinutes(1));
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
var dispatch = await context.RecordCompletionDispatches.SingleAsync();
|
||||
Assert.Equal(task.Id, dispatch.RecordTaskId);
|
||||
Assert.False(dispatch.UploadDispatched);
|
||||
Assert.Null(dispatch.CompletedAt);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_temporaryDirectory))
|
||||
{
|
||||
Directory.Delete(_temporaryDirectory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user