using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using RainOpsMini.Helpers; using RainOpsMini.Helpers.SquadGameLog; using RainOpsMini.Models; using SqlSugar; using System; using System.Threading; using System.Threading.Tasks; namespace RainOpsMini.Services { public class DatabaseCleanupService : IHostedService { private readonly ILogger _logger; public DatabaseCleanupService(ILogger logger) { _logger = logger; } public Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("[Cleanup] Database Cleanup Service starting..."); // Run cleanup in a background thread to not block startup Task.Run(() => { try { CleanupDatabase(); } catch (Exception ex) { _logger.LogError(ex, "[Cleanup] Fatal error during cleanup task."); } }); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } private void CleanupDatabase() { try { using (var db = DbHelper.GetInstance()) { _logger.LogInformation("[Cleanup] Checking tables for cleanup..."); // 1. Clean ChatLogs (Keep latest 1000 - Existing logic) CleanTableCount(db, 1000); // 2. Clean Game Logs (Keep 7 days) int retentionDays = 7; CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); CleanTableByDate(db, retentionDays); } } catch (Exception ex) { _logger.LogError(ex, "[Cleanup] Error accessing database."); } } private void CleanTableCount(SqlSugarScope db, int keepCount) where T : class, new() { try { var total = db.Queryable().Count(); if (total > keepCount) { var tableName = db.EntityMaintenance.GetTableName(); _logger.LogInformation($"[Cleanup] Cleaning table {tableName}. Total rows: {total}, Limit: {keepCount}"); string sql = $"DELETE FROM {tableName} WHERE Id NOT IN (SELECT Id FROM {tableName} ORDER BY Id DESC LIMIT {keepCount})"; int affected = db.Ado.ExecuteCommand(sql); _logger.LogInformation($"[Cleanup] Removed {affected} old records from {tableName}."); } } catch (Exception ex) { _logger.LogError(ex, $"[Cleanup] Failed to clean table {typeof(T).Name} by count"); } } private void CleanTableByDate(SqlSugarScope db, int days) where T : class, new() { try { var date = DateTime.Now.AddDays(-days); var tableName = db.EntityMaintenance.GetTableName(); // Assumes LogTime column exists and is mapped int affected = db.Deleteable().Where("LogTime < @date", new { date }).ExecuteCommand(); if (affected > 0) { _logger.LogInformation($"[Cleanup] Removed {affected} old records from {tableName} (older than {days} days)."); } } catch (Exception ex) { _logger.LogError(ex, $"[Cleanup] Failed to clean table {typeof(T).Name} by date"); } } } }