Files
caliverse_server/UGQApiServer/BackGroundService/OnTimeBackGroundService.cs
2025-05-01 07:20:41 +09:00

97 lines
2.7 KiB
C#

using Amazon.DynamoDBv2.Model;
using ServerCore; using ServerBase;
namespace UGQApiServer.BackGroundService;
public static class BackgroundServiceExtensions
{
public static IServiceCollection AddOnTimeBackgroundService(this IServiceCollection services)
{
services.AddSingleton<OnTimeBackGroundService>();
services.AddHostedService(provider => provider.GetRequiredService<OnTimeBackGroundService>());
return services;
}
public static IServiceCollection AddOnTimeTask(this IServiceCollection services, string taskName, DateTime onTime, Task task)
{
var provider = services.BuildServiceProvider();
var service = provider.GetRequiredService<OnTimeBackGroundService>();
service.addOnTimeTask(taskName, onTime, task);
return services;
}
}
public class OnTimeBackGroundService : BackgroundService
{
private const int BaseDelayMs = 1_000;
private PeriodicTimer? m_timer { get; set; }
private Dictionary<string, (Task task, DateTime time)> m_onTime_tasks { get; set; } = new();
public OnTimeBackGroundService() {}
public override void Dispose()
{
base.Dispose();
m_timer?.Dispose();
GC.SuppressFinalize(this);
}
public bool addOnTimeTask(string taskName, DateTime onTime, Task action)
{
return m_onTime_tasks.TryAdd(taskName, (action, onTime));
}
public bool deleteOnTimeTask(string taskName)
{
return m_onTime_tasks.Remove(taskName);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
CreateTimer();
try
{
if (!await m_timer!.WaitForNextTickAsync(stoppingToken).ConfigureAwait(false))
{
return;
}
while (!stoppingToken.IsCancellationRequested)
{
await RunAsync().ConfigureAwait(false);
if (!await m_timer!.WaitForNextTickAsync(stoppingToken).ConfigureAwait(false))
{
break;
}
}
}
catch (Exception e)
{
Log.getLogger().error($"Background Exception : {e.Message}");
}
}
private async Task RunAsync()
{
var current = DateTime.UtcNow;
foreach (var task in m_onTime_tasks)
{
var on_time = task.Value.time;
if (current.Hour != on_time.Hour || current.Minute != on_time.Minute || current.Second != on_time.Second) continue;
// Fire and Forget
_ = Task.Run(() => task.Value.task);
}
await Task.CompletedTask;
}
private void CreateTimer() => m_timer = new PeriodicTimer(TimeSpan.FromMilliseconds(BaseDelayMs));
}