feat: harden recording lifecycle and refresh fnOS UI
This commit is contained in:
@@ -16,6 +16,7 @@ public sealed class DashboardService
|
||||
private readonly ISystemLogRepository _systemLogRepository;
|
||||
private readonly ISystemSettingsService _systemSettingsService;
|
||||
private readonly IStorageGuardService _storageGuardService;
|
||||
private readonly IOperationsMetricsRepository _operationsMetricsRepository;
|
||||
|
||||
public DashboardService(
|
||||
ILiveRoomRepository liveRoomRepository,
|
||||
@@ -24,7 +25,8 @@ public sealed class DashboardService
|
||||
IRecordResultRepository recordResultRepository,
|
||||
ISystemLogRepository systemLogRepository,
|
||||
ISystemSettingsService systemSettingsService,
|
||||
IStorageGuardService storageGuardService)
|
||||
IStorageGuardService storageGuardService,
|
||||
IOperationsMetricsRepository operationsMetricsRepository)
|
||||
{
|
||||
_liveRoomRepository = liveRoomRepository;
|
||||
_recordSessionRepository = recordSessionRepository;
|
||||
@@ -33,6 +35,7 @@ public sealed class DashboardService
|
||||
_systemLogRepository = systemLogRepository;
|
||||
_systemSettingsService = systemSettingsService;
|
||||
_storageGuardService = storageGuardService;
|
||||
_operationsMetricsRepository = operationsMetricsRepository;
|
||||
}
|
||||
|
||||
public async Task<DashboardDto> GetDashboardAsync(CancellationToken cancellationToken = default)
|
||||
@@ -45,6 +48,7 @@ public sealed class DashboardService
|
||||
var todayUtcStart = new DateTimeOffset(todayBeijingDate.ToDateTime(TimeOnly.MinValue), ChinaTime.Zone.GetUtcOffset(beijingNow.DateTime)).ToUniversalTime();
|
||||
var todayUtcEnd = new DateTimeOffset(todayBeijingDate.ToDateTime(TimeOnly.MaxValue), ChinaTime.Zone.GetUtcOffset(beijingNow.DateTime)).ToUniversalTime();
|
||||
var recentErrorSince = now.AddHours(-24);
|
||||
var currentErrorSince = now.AddMinutes(-30);
|
||||
|
||||
// Run queries sequentially — DbContext is not thread-safe
|
||||
var activeRecordingCount = await _recordSessionRepository.CountByStatusAsync(RecordSessionStatus.Running, cancellationToken);
|
||||
@@ -53,6 +57,7 @@ public sealed class DashboardService
|
||||
var totalRoomCount = await _liveRoomRepository.CountAsync(cancellationToken);
|
||||
var activeSessionCount = await _recordSessionRepository.CountActiveAsync(cancellationToken);
|
||||
var recentErrorCount = await _systemLogRepository.CountRecentErrorsAsync(recentErrorSince, cancellationToken);
|
||||
var currentErrorCount = await _systemLogRepository.CountRecentErrorsAsync(currentErrorSince, cancellationToken);
|
||||
var todayRecordingSeconds = await _recordTaskRepository.SumDurationSecondsAsync(todayUtcStart, todayUtcEnd, cancellationToken);
|
||||
var (todayTotalBytes, todayTotalDanmaku) = await _recordResultRepository.GetTodayAggregateAsync(todayUtcStart, todayUtcEnd, cancellationToken);
|
||||
var recentSessions = await _recordSessionRepository.ListRecentAsync(5, cancellationToken);
|
||||
@@ -62,6 +67,7 @@ public sealed class DashboardService
|
||||
var pendingTranscodeCount = await _recordTaskRepository.CountByStatusAsync(RecordTaskStatus.Processing, cancellationToken);
|
||||
var pendingUploadCount = await _recordResultRepository.CountPendingUploadAsync(cancellationToken);
|
||||
var queuedDataBytes = await _recordResultRepository.SumPendingUploadBytesAsync(cancellationToken);
|
||||
var operationsMetrics = await _operationsMetricsRepository.GetAsync(cancellationToken);
|
||||
|
||||
return new DashboardDto
|
||||
{
|
||||
@@ -74,17 +80,31 @@ public sealed class DashboardService
|
||||
TodayDanmakuCount = todayTotalDanmaku,
|
||||
ActiveSessionCount = activeSessionCount,
|
||||
RecentErrorCount = recentErrorCount,
|
||||
CurrentErrorCount = currentErrorCount,
|
||||
StorageStatus = new StorageStatusDto
|
||||
{
|
||||
IsEnabled = storageCheck.IsEnabled,
|
||||
IsAvailable = storageCheck.IsAvailable,
|
||||
HasEnoughSpace = storageCheck.HasEnoughSpace,
|
||||
Message = storageCheck.Message ?? string.Empty,
|
||||
CheckedPath = storageCheck.CheckedPath,
|
||||
TotalBytes = storageCheck.TotalBytes,
|
||||
UsedBytes = storageCheck.UsedBytes,
|
||||
AvailableBytes = storageCheck.AvailableBytes,
|
||||
RequiredBytes = storageCheck.RequiredBytes,
|
||||
Tier = storageCheck.Tier.ToString(),
|
||||
UsagePercent = storageCheck.UsagePercent
|
||||
UsagePercent = storageCheck.UsagePercent,
|
||||
FreePercent = storageCheck.FreePercent,
|
||||
GreenThresholdPercent = storageCheck.GreenThresholdPercent,
|
||||
RedThresholdPercent = storageCheck.RedThresholdPercent
|
||||
},
|
||||
PendingTranscodeCount = pendingTranscodeCount,
|
||||
PendingUploadCount = pendingUploadCount,
|
||||
QueuedDataBytes = queuedDataBytes,
|
||||
OldestTranscodeUpdatedAt = operationsMetrics.OldestTranscodeUpdatedAt,
|
||||
OldestUploadProgressAt = operationsMetrics.OldestUploadProgressAt,
|
||||
StalledUploadCount = operationsMetrics.StalledUploadCount,
|
||||
UploadCleanupFailureCount = operationsMetrics.CleanupFailureCount,
|
||||
RecentSessions = recentSessions
|
||||
.Select(MapRecentSession)
|
||||
.ToList(),
|
||||
|
||||
Reference in New Issue
Block a user