From b80419ade2aa3440568de0c3cf258f343505c535 Mon Sep 17 00:00:00 2001 From: nanxun Date: Fri, 24 Apr 2026 15:53:07 +0800 Subject: [PATCH] fix: restore scheduler auto-start on sqlite --- .../Services/FfmpegService.cs | 7 ++- .../LiveRoomPollingBackgroundService.cs | 51 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/LiveRecorder.Infrastructure/Services/FfmpegService.cs b/src/LiveRecorder.Infrastructure/Services/FfmpegService.cs index 844e63f..8ed2c2c 100644 --- a/src/LiveRecorder.Infrastructure/Services/FfmpegService.cs +++ b/src/LiveRecorder.Infrastructure/Services/FfmpegService.cs @@ -412,10 +412,13 @@ public sealed partial class FfmpegService : IFfmpegService .Include(item => item.Result) .Where(item => item.OutputFormat == RecordOutputFormat.Mp4 && (item.Status == RecordTaskStatus.Processing || - item.Status == RecordTaskStatus.Completed)) + item.Status == RecordTaskStatus.Completed)) + .ToListAsync(cancellationToken); + + candidates = candidates .OrderBy(static item => item.UpdatedAt) .Take(100) - .ToListAsync(cancellationToken); + .ToList(); var queuedTaskIds = new List(); var repairedInterruptedTasks = 0; diff --git a/src/LiveRecorder.Infrastructure/Services/LiveRoomPollingBackgroundService.cs b/src/LiveRecorder.Infrastructure/Services/LiveRoomPollingBackgroundService.cs index 2cae959..f6e3f1d 100644 --- a/src/LiveRecorder.Infrastructure/Services/LiveRoomPollingBackgroundService.cs +++ b/src/LiveRecorder.Infrastructure/Services/LiveRoomPollingBackgroundService.cs @@ -184,6 +184,22 @@ public sealed class LiveRoomPollingBackgroundService : BackgroundService return; } + var reconciledStaleSessionIds = await ReconcileStaleActiveSessionsAsync( + dbContext, + ffmpegService, + liveRoom.Id, + cancellationToken); + foreach (var reconciledSessionId in reconciledStaleSessionIds) + { + await logService.WriteAsync( + SystemLogLevel.Warning, + "Scheduler", + "Recovered a stale active recording session before auto-start check.", + liveRoomId: liveRoom.Id, + recordSessionId: reconciledSessionId, + cancellationToken: cancellationToken); + } + var hasRunningSession = await dbContext.RecordSessions.AnyAsync( item => item.LiveRoomId == liveRoom.Id && (item.Status == RecordSessionStatus.Starting || @@ -368,6 +384,41 @@ public sealed class LiveRoomPollingBackgroundService : BackgroundService } } + private static async Task> ReconcileStaleActiveSessionsAsync( + LiveRecorderDbContext dbContext, + IFfmpegService ffmpegService, + Guid liveRoomId, + CancellationToken cancellationToken) + { + var activeSessionIds = await dbContext.RecordSessions + .Where(item => item.LiveRoomId == liveRoomId && + (item.Status == RecordSessionStatus.Starting || + item.Status == RecordSessionStatus.Running || + item.Status == RecordSessionStatus.Stopping)) + .ToListAsync(cancellationToken); + + var orderedActiveSessionIds = activeSessionIds + .OrderBy(item => item.CreatedAt) + .Select(item => item.Id) + .ToList(); + + if (orderedActiveSessionIds.Count == 0) + { + return []; + } + + var reconciledSessionIds = new List(); + foreach (var activeSessionId in orderedActiveSessionIds) + { + if (await ffmpegService.TryReconcileInactiveSessionAsync(activeSessionId, cancellationToken)) + { + reconciledSessionIds.Add(activeSessionId); + } + } + + return reconciledSessionIds; + } + private static bool IsTransientPollingException(Exception exception, CancellationToken cancellationToken) { if (exception is OperationCanceledException && cancellationToken.IsCancellationRequested)