fix: consolidate storage tier with old MB thresholds into single tier system

- CanStartNewRecording now purely based on Tier==Green (was HasEnoughSpace||Green)
- PollingBackgroundService now uses ShouldPauseActive instead of MB-based CheckShouldPause
- Both pause and start checks consolidated into single guardCheck call
- Old MB pause/resume thresholds still work as secondary safety via hasEnoughSpace

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
This commit is contained in:
2026-06-05 11:57:20 +08:00
co-authored by Claude Opus 4.8 noreply@anthropic.com
parent 0831b33ea0
commit e640d5b5cc
2 changed files with 26 additions and 24 deletions
@@ -40,12 +40,14 @@ public sealed record StorageGuardResult(
public double UsagePercent { get; init; } public double UsagePercent { get; init; }
/// <summary> /// <summary>
/// True if new recordings can be started. False in Yellow and Red tiers. /// True if new recordings can be started. Only true in Green tier.
/// This replaces the old binary HasEnoughSpace check — the tier system is the single source of truth.
/// </summary> /// </summary>
public bool CanStartNewRecording => HasEnoughSpace || Tier == StorageTier.Green; public bool CanStartNewRecording => Tier == StorageTier.Green;
/// <summary> /// <summary>
/// True if active recordings should be paused. Only true in Red tier. /// True if active recordings should be paused. Only true in Red tier.
/// This replaces the old MB-based CheckShouldPause — consolidated into the tier system.
/// </summary> /// </summary>
public bool ShouldPauseActive => Tier == StorageTier.Red; public bool ShouldPauseActive => Tier == StorageTier.Red;
} }
@@ -355,8 +355,8 @@ public sealed class LiveRoomPollingBackgroundService : BackgroundService, ILiveR
return; return;
} }
var pauseCheck = storageGuardService.CheckShouldPause(settings); var guardCheck = storageGuardService.CheckCanStartOrResume(settings);
if (!pauseCheck.HasEnoughSpace) if (guardCheck.ShouldPauseActive)
{ {
await PauseActiveSessionsForLowStorageAsync( await PauseActiveSessionsForLowStorageAsync(
dbContext, dbContext,
@@ -366,7 +366,7 @@ public sealed class LiveRoomPollingBackgroundService : BackgroundService, ILiveR
webhookNotificationService, webhookNotificationService,
liveRoom, liveRoom,
liveRoom.Id, liveRoom.Id,
pauseCheck.Message, guardCheck.Message,
cancellationToken); cancellationToken);
} }
@@ -382,25 +382,6 @@ public sealed class LiveRoomPollingBackgroundService : BackgroundService, ILiveR
return; return;
} }
var startCheck = storageGuardService.CheckCanStartOrResume(settings);
if (!startCheck.CanStartNewRecording)
{
await UpdateAutoStartDecisionAsync(
dbContext,
liveRoom,
AutoStartDecisionCodes.SkippedStorage,
$"Auto-start skipped because storage tier is {startCheck.Tier}.",
startCheck.Message,
cancellationToken);
await logService.WriteAsync(
SystemLogLevel.Warning,
"Storage",
"Auto-start recording skipped because storage is below resume threshold.",
startCheck.Message,
liveRoomId: liveRoom.Id,
cancellationToken: cancellationToken);
return;
}
var reconciledStaleSessionIds = await ReconcileStaleActiveSessionsAsync( var reconciledStaleSessionIds = await ReconcileStaleActiveSessionsAsync(
dbContext, dbContext,
@@ -418,6 +399,25 @@ public sealed class LiveRoomPollingBackgroundService : BackgroundService, ILiveR
cancellationToken: cancellationToken); cancellationToken: cancellationToken);
} }
if (!guardCheck.CanStartNewRecording)
{
await UpdateAutoStartDecisionAsync(
dbContext,
liveRoom,
AutoStartDecisionCodes.SkippedStorage,
$"Auto-start skipped because storage tier is {guardCheck.Tier}.",
guardCheck.Message,
cancellationToken);
await logService.WriteAsync(
SystemLogLevel.Warning,
"Storage",
"Auto-start recording skipped because storage tier is not Green.",
guardCheck.Message,
liveRoomId: liveRoom.Id,
cancellationToken: cancellationToken);
return;
}
var hasRunningSession = await dbContext.RecordSessions.AnyAsync( var hasRunningSession = await dbContext.RecordSessions.AnyAsync(
item => item.LiveRoomId == liveRoom.Id && item => item.LiveRoomId == liveRoom.Id &&
(item.Status == RecordSessionStatus.Starting || (item.Status == RecordSessionStatus.Starting ||