mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Fix: PaymentRequests created via API never expires (#6657)
This commit is contained in:
84
BTCPayServer/Services/DelayedTaskScheduler.cs
Normal file
84
BTCPayServer/Services/DelayedTaskScheduler.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BTCPayServer.Services
|
||||
{
|
||||
public class DelayedTaskScheduler : IDisposable
|
||||
{
|
||||
public DelayedTaskScheduler(ILogger<DelayedTaskScheduler> logger)
|
||||
{
|
||||
Logger = logger;
|
||||
}
|
||||
record class TimerState(string Key, Func<Task> Act);
|
||||
private readonly Dictionary<string, Timer> _timers = new();
|
||||
bool disposed = false;
|
||||
|
||||
public ILogger<DelayedTaskScheduler> Logger { get; }
|
||||
|
||||
public void Schedule(string key, DateTimeOffset executeAt, Func<Task> act)
|
||||
{
|
||||
lock (_timers)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
_timers.TryGetValue(key, out var existing);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Dispose();
|
||||
_timers.Remove(key);
|
||||
}
|
||||
var due = executeAt - DateTimeOffset.UtcNow;
|
||||
if (due < TimeSpan.Zero)
|
||||
due = TimeSpan.Zero;
|
||||
var timer = new Timer(TimerCallback, new TimerState(key, act), Timeout.Infinite, Timeout.Infinite);
|
||||
_timers.Add(key, timer);
|
||||
timer.Change((long)due.TotalMilliseconds, (long)Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
void TimerCallback(object? state)
|
||||
{
|
||||
var s = (TimerState)state!;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await s.Act();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error executing delayed task for key {s.Key}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Timer? timer = null;
|
||||
lock (_timers)
|
||||
{
|
||||
if (_timers.TryGetValue(s.Key, out timer))
|
||||
{
|
||||
_timers.Remove(s.Key);
|
||||
}
|
||||
}
|
||||
timer?.Dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_timers)
|
||||
{
|
||||
disposed = true;
|
||||
foreach (var t in _timers.Values)
|
||||
t.Dispose();
|
||||
_timers.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user