初级的功能
This commit is contained in:
142
FATrace.OEMApp/Services/TimeClearDataService.cs
Normal file
142
FATrace.OEMApp/Services/TimeClearDataService.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FATrace.Com;
|
||||
using FATrace.Model;
|
||||
using NLog;
|
||||
|
||||
namespace FATrace.OEMApp.Services
|
||||
{
|
||||
public sealed class TimeClearDataService
|
||||
{
|
||||
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
private CancellationTokenSource? _cts;
|
||||
private Task? _loopTask;
|
||||
private TimeSpan _runAt = new TimeSpan(2, 0, 0);
|
||||
private int _retentionDays = 365;
|
||||
private bool _enabled = true;
|
||||
|
||||
public event Action<string>? Info;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_cts != null) return;
|
||||
|
||||
try
|
||||
{
|
||||
_enabled = ConfigHelper.GetBoolOrDefault("DataCleanupEnabled", true);
|
||||
var tod = ConfigHelper.GetStringOrDefault("DataCleanupTimeOfDay", "02:00:00");
|
||||
if (!TimeSpan.TryParse(tod, out _runAt))
|
||||
{
|
||||
_runAt = new TimeSpan(2, 0, 0);
|
||||
}
|
||||
_retentionDays = Math.Max(1, ConfigHelper.GetIntOrDefault("DataRetentionDays", 365));
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!_enabled)
|
||||
{
|
||||
_logger.Warn("[TimeClear] 已禁用,未启动");
|
||||
return;
|
||||
}
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
_loopTask = Task.Run(() => RunAsync(_cts.Token));
|
||||
_logger.Info("[TimeClear] 服务已启动,时间点={RunAt}, 保留天数={Days}", _runAt, _retentionDays);
|
||||
SafeInfo($"定时清理服务启动,时间点={_runAt}, 保留天数={_retentionDays}");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
try { _cts?.Cancel(); } catch { }
|
||||
_cts = null;
|
||||
_logger.Info("[TimeClear] 服务已停止");
|
||||
}
|
||||
|
||||
private async Task RunAsync(CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
var next = GetNextRunTime(now);
|
||||
var delay = next - now;
|
||||
SafeInfo($"距离下一次清理还有 {delay:hh\\:mm\\:ss},计划时间 {next:yyyy-MM-dd HH:mm:ss}");
|
||||
await Task.Delay(delay, token);
|
||||
await CleanupOnceAsync(token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "[TimeClear] 后台循环异常");
|
||||
try { await Task.Delay(TimeSpan.FromMinutes(1), token); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime GetNextRunTime(DateTime now)
|
||||
{
|
||||
var next = now.Date + _runAt;
|
||||
if (next <= now.AddSeconds(1)) next = next.AddDays(1);
|
||||
return next;
|
||||
}
|
||||
|
||||
private async Task CleanupOnceAsync(CancellationToken token)
|
||||
{
|
||||
var cutoff = DateTime.Now.AddDays(-_retentionDays);
|
||||
_logger.Info("[TimeClear] 开始清理,截止时间: {Cutoff}", cutoff);
|
||||
SafeInfo($"开始清理,截止时间: {cutoff:yyyy-MM-dd HH:mm:ss}");
|
||||
|
||||
long delJf = 0, delDl = 0, delRaw = 0, delAct = 0;
|
||||
try
|
||||
{
|
||||
delJf = FSqlContext.FDb.Delete<JellyfinMonitorTask>().Where(a => a.CreateTime < cutoff).ExecuteAffrows();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "[TimeClear] 清理 JellyfinMonitorTask 失败");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
delDl = FSqlContext.FDb.Delete<DownloadTask>().Where(a => a.CreateTime < cutoff).ExecuteAffrows();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "[TimeClear] 清理 DownloadTask 失败");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
delRaw = FSqlContext.FDb.Delete<OEMRawUse>().Where(a => a.CreateTime < cutoff).ExecuteAffrows();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "[TimeClear] 清理 OEMRawUse 失败");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
delAct = FSqlContext.FDb.Delete<VideoAction>().Where(a => a.CreateTime < cutoff).ExecuteAffrows();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "[TimeClear] 清理 VideoAction 失败");
|
||||
}
|
||||
|
||||
_logger.Info("[TimeClear] 清理完成: JellyfinMonitorTask={Jf}, DownloadTask={Dl}, OEMRawUse={Raw}, VideoAction={Act}", delJf, delDl, delRaw, delAct);
|
||||
SafeInfo($"清理完成: Jf={delJf}, Dl={delDl}, Raw={delRaw}, Act={delAct}");
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void SafeInfo(string msg)
|
||||
{
|
||||
try { Info?.Invoke(msg); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user