Files
bom-local-service/Services/CacheCleanupService.cs
T
alex 41e1f6d685 Implement multi-frame radar capture with configurable cropping
- Capture all 7 radar frames (0-6) instead of single screenshot
- Store frames in folder-based cache structure with metadata
- Extract and store minutesAgo for each frame from page display
- Add configurable screenshot cropping (default: 200px left/right)
- Fix step numbering to use whole numbers (1-22)
- Add scrubber position verification before frame capture
- Handle modal overlay blocking step forward button clicks
- Only create debug folders when scraping is actually needed
- Update API endpoints to return JSON with frame URLs
- Add separate endpoints for individual frame images
2025-12-07 12:51:44 +10:00

157 lines
5.2 KiB
C#

using BomLocalService.Utilities;
using Microsoft.Extensions.Hosting;
namespace BomLocalService.Services;
public class CacheCleanupService : BackgroundService
{
private readonly ILogger<CacheCleanupService> _logger;
private readonly string _cacheDirectory;
private readonly int _retentionHours;
private readonly TimeSpan _cleanupInterval;
public CacheCleanupService(ILogger<CacheCleanupService> logger, IConfiguration configuration)
{
_logger = logger;
_cacheDirectory = FilePathHelper.GetCacheDirectory(configuration);
_retentionHours = configuration.GetValue<int>("CacheRetentionHours", 24);
var cleanupIntervalHours = configuration.GetValue<int>("CacheCleanup:IntervalHours", 1);
_cleanupInterval = TimeSpan.FromHours(cleanupIntervalHours);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Cache cleanup service started. Retention: {RetentionHours} hours, Interval: {Interval}",
_retentionHours, _cleanupInterval);
while (!stoppingToken.IsCancellationRequested)
{
try
{
await CleanupOldCacheFilesAsync(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during cache cleanup");
}
await Task.Delay(_cleanupInterval, stoppingToken);
}
}
private Task CleanupOldCacheFilesAsync(CancellationToken cancellationToken)
{
if (!Directory.Exists(_cacheDirectory))
{
return Task.CompletedTask;
}
var cutoffTime = DateTime.UtcNow.AddHours(-_retentionHours);
var deletedCount = 0;
var totalSize = 0L;
try
{
// Get all cache folders
var folders = Directory.GetDirectories(_cacheDirectory);
foreach (var folder in folders)
{
if (cancellationToken.IsCancellationRequested)
break;
try
{
var folderInfo = new DirectoryInfo(folder);
var folderTime = folderInfo.LastWriteTimeUtc;
// Delete if folder is older than retention period
if (folderTime < cutoffTime)
{
var folderSize = GetFolderSize(folder);
Directory.Delete(folder, recursive: true);
deletedCount++;
totalSize += folderSize;
_logger.LogDebug("Deleted old cache folder: {Folder} (age: {Age})",
Path.GetFileName(folder), DateTime.UtcNow - folderTime);
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to delete cache folder: {Folder}", folder);
}
}
if (deletedCount > 0)
{
var sizeInMB = totalSize / (1024.0 * 1024.0);
_logger.LogInformation("Cache cleanup completed. Deleted {Count} folders ({Size:F2} MB)",
deletedCount, sizeInMB);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during cache folder enumeration");
}
// Also clean up old debug directories
try
{
var debugDir = Path.Combine(_cacheDirectory, "debug");
if (Directory.Exists(debugDir))
{
var debugDirs = Directory.GetDirectories(debugDir);
foreach (var dir in debugDirs)
{
if (cancellationToken.IsCancellationRequested)
break;
try
{
var dirInfo = new DirectoryInfo(dir);
if (dirInfo.LastWriteTimeUtc < cutoffTime)
{
Directory.Delete(dir, recursive: true);
_logger.LogDebug("Deleted old debug directory: {Dir}", dir);
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to delete debug directory: {Dir}", dir);
}
}
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error cleaning up debug directories: {Error}", ex.Message);
}
return Task.CompletedTask;
}
/// <summary>
/// Calculates the total size of a folder and all its contents
/// </summary>
private long GetFolderSize(string folderPath)
{
long size = 0;
try
{
var files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories);
foreach (var file in files)
{
var fileInfo = new FileInfo(file);
size += fileInfo.Length;
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error calculating folder size for: {Folder}", folderPath);
}
return size;
}
}