using FileShare_Services.Services.FileLibrary;
using Microsoft.Extensions.Options;
namespace FileShare_API.Services
{
///
/// 文件库定时扫描后台服务,按配置间隔检查是否有需要扫描的文件库目录。
///
public sealed class FileLibraryScanHostedService(
IServiceScopeFactory scopeFactory,
IOptions options,
ILogger logger)
: BackgroundService
{
/// 后台服务检查到期扫描任务的轮询间隔。
private readonly TimeSpan _interval = TimeSpan.FromMinutes(Math.Max(1, options.Value.PollingIntervalMinutes));
///
/// 启动扫描循环,首次立即执行,之后按配置的轮询间隔重复执行。
///
/// 应用关闭时触发的取消令牌。
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
logger.LogInformation("文件库定时扫描服务已启动,轮询间隔 {IntervalMinutes} 分钟。", _interval.TotalMinutes);
await ScanAsync(stoppingToken);
using var timer = new PeriodicTimer(_interval);
while (await timer.WaitForNextTickAsync(stoppingToken))
{
await ScanAsync(stoppingToken);
}
}
///
/// 创建临时作用域并调用 执行一次到期扫描。
///
/// 取消令牌。
private async Task ScanAsync(CancellationToken cancellationToken)
{
var startedAt = DateTime.UtcNow;
logger.LogInformation("文件库定时扫描轮询开始。");
try
{
await using var scope = scopeFactory.CreateAsyncScope();
var scanner = scope.ServiceProvider.GetRequiredService();
await scanner.ScanDueRootsAsync(cancellationToken);
logger.LogInformation(
"文件库定时扫描轮询完成,耗时 {ElapsedMilliseconds} ms。",
(DateTime.UtcNow - startedAt).TotalMilliseconds);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
logger.LogInformation("文件库定时扫描轮询已取消。");
}
catch (Exception ex)
{
logger.LogWarning(ex, "文件库定时扫描失败。");
}
}
}
}