using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Threading;
using Netch.Models;
using Timer = System.Timers.Timer;
namespace Netch.Utils
{
public static class DelayTestHelper
{
private static readonly Timer Timer;
private static readonly SemaphoreSlim Lock = new(1, 1);
private static readonly SemaphoreSlim PoolLock = new(16, 16);
public static readonly NumberRange Range = new(0, int.MaxValue / 1000);
private static bool _enabled = true;
static DelayTestHelper()
{
Timer = new Timer
{
Interval = 10000,
AutoReset = true
};
Timer.Elapsed += (_, _) => PerformTestAsync().Forget();
}
public static bool Enabled
{
get => _enabled;
set
{
_enabled = value;
UpdateTick();
}
}
/// if does not get lock, block until last release
public static async Task PerformTestAsync(bool waitFinish = false)
{
if (Lock.CurrentCount == 0)
{
if (waitFinish)
{
await Lock.WaitAsync();
Lock.Release();
}
return;
}
await Lock.WaitAsync();
try
{
var tasks = Global.Settings.Server.Select(async s =>
{
await PoolLock.WaitAsync();
try
{
await s.PingAsync();
}
finally
{
PoolLock.Release();
}
});
await Task.WhenAll(tasks);
}
catch (Exception)
{
// ignored
}
finally
{
Lock.Release();
}
}
public static void UpdateTick(bool performTestAtOnce = false)
{
UpdateTick(Global.Settings.DetectionTick, performTestAtOnce);
}
/// interval(seconds), 0 disable, MaxValue int.MaxValue/1000
///
private static void UpdateTick(int interval, bool performTestAtOnce = false)
{
Timer.Stop();
var enable = Enabled && interval > 0 && Range.InRange(interval);
if (enable)
{
Timer.Interval = interval * 1000;
Timer.Start();
if (performTestAtOnce)
PerformTestAsync().Forget();
}
}
}
}