164 lines
4.4 KiB
C#
Raw Permalink Normal View History

2025-04-03 14:18:27 +02:00
using Logging;
namespace AutoClient
2025-04-03 13:10:01 +02:00
{
public class LoadBalancer
{
private readonly List<Cdx> instances;
private readonly object instanceLock = new object();
2025-06-03 14:51:47 +02:00
private readonly App app;
private int printDelay = 10;
2025-04-03 13:10:01 +02:00
private class Cdx
{
2025-04-03 14:18:27 +02:00
private readonly ILog log;
private readonly CodexWrapper instance;
private readonly List<Action<CodexWrapper>> queue = new List<Action<CodexWrapper>>();
private readonly object queueLock = new object();
private bool running = true;
private Task worker = Task.CompletedTask;
public Cdx(App app, CodexWrapper instance)
2025-04-03 13:10:01 +02:00
{
2025-04-03 14:18:27 +02:00
Id = instance.Node.GetName();
log = new LogPrefixer(app.Log, $"[Queue-{Id}]");
this.instance = instance;
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
public string Id { get; }
2025-06-03 14:51:47 +02:00
public int QueueSize => queue.Count;
2025-04-03 13:10:01 +02:00
2025-04-03 14:18:27 +02:00
public void Start()
{
worker = Task.Run(Worker);
}
2025-04-03 13:10:01 +02:00
2025-04-03 14:18:27 +02:00
public void Stop()
2025-04-03 13:10:01 +02:00
{
2025-04-03 14:18:27 +02:00
running = false;
worker.Wait();
}
2025-04-03 13:10:01 +02:00
2025-04-03 14:18:27 +02:00
public void CheckErrors()
{
if (worker.IsFaulted) throw worker.Exception;
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
public void Queue(Action<CodexWrapper> action)
2025-04-03 13:10:01 +02:00
{
2025-06-03 14:35:01 +02:00
if (queue.Count > 3) Thread.Sleep(TimeSpan.FromSeconds(5.0));
if (queue.Count > 5) log.Log("Queue full. Waiting...");
while (queue.Count > 5)
2025-04-03 13:10:01 +02:00
{
2025-06-03 14:35:01 +02:00
Thread.Sleep(TimeSpan.FromSeconds(1.0));
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
lock (queueLock)
{
queue.Add(action);
}
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
private void Worker()
2025-04-03 13:10:01 +02:00
{
2025-04-03 14:28:23 +02:00
try
2025-04-03 14:18:27 +02:00
{
2025-04-03 14:28:23 +02:00
while (running)
2025-04-03 14:18:27 +02:00
{
while (running && queue.Count == 0) Thread.Sleep(TimeSpan.FromSeconds(1.0));
if (!running) return;
2025-04-03 14:28:23 +02:00
Action<CodexWrapper> action = w => { };
lock (queueLock)
{
action = queue[0];
queue.RemoveAt(0);
}
2025-04-03 14:18:27 +02:00
2025-04-03 14:28:23 +02:00
action(instance);
}
}
catch (Exception ex)
{
log.Error("Exception in worker: " + ex);
throw;
2025-04-03 14:18:27 +02:00
}
2025-04-03 13:10:01 +02:00
}
}
2025-06-03 14:51:47 +02:00
private class CdxComparer : IComparer<Cdx>
{
public int Compare(Cdx? x, Cdx? y)
{
if (x == null || y == null) return 0;
return x.QueueSize - y.QueueSize;
}
}
2025-04-03 14:18:27 +02:00
public LoadBalancer(App app, CodexWrapper[] instances)
2025-04-03 13:10:01 +02:00
{
2025-04-03 14:18:27 +02:00
this.instances = instances.Select(i => new Cdx(app, i)).ToList();
2025-06-03 14:51:47 +02:00
this.app = app;
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
public void Start()
2025-04-03 13:10:01 +02:00
{
2025-06-03 14:59:10 +02:00
app.Log.Log("LoadBalancer starting...");
2025-04-03 14:18:27 +02:00
foreach (var i in instances) i.Start();
}
2025-04-03 13:10:01 +02:00
2025-04-03 14:18:27 +02:00
public void Stop()
{
2025-06-03 14:59:10 +02:00
app.Log.Log("LoadBalancer stopping...");
2025-04-03 14:18:27 +02:00
foreach (var i in instances) i.Stop();
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
public void DispatchOnCodex(Action<CodexWrapper> action)
2025-04-03 13:10:01 +02:00
{
lock (instanceLock)
{
2025-06-03 14:51:47 +02:00
instances.Sort(new CdxComparer());
2025-04-03 14:18:27 +02:00
var i = instances.First();
i.Queue(action);
2025-04-03 13:10:01 +02:00
}
2025-06-03 14:51:47 +02:00
PrintQueue();
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
public void DispatchOnSpecificCodex(Action<CodexWrapper> action, string id)
2025-04-03 13:10:01 +02:00
{
2025-04-03 14:18:27 +02:00
lock (instanceLock)
2025-04-03 13:10:01 +02:00
{
2025-06-03 14:51:47 +02:00
instances.Sort(new CdxComparer());
2025-04-03 14:18:27 +02:00
var i = instances.Single(a => a.Id == id);
i.Queue(action);
2025-04-03 13:10:01 +02:00
}
2025-06-03 14:51:47 +02:00
PrintQueue();
}
private void PrintQueue()
{
printDelay--;
if (printDelay > 0) return;
printDelay = 10;
lock (instanceLock)
{
foreach (var i in instances)
{
app.Log.Log($"Queue[{i.Id}] = {i.QueueSize} entries");
}
}
2025-04-03 13:10:01 +02:00
}
2025-04-03 14:18:27 +02:00
public void CheckErrors()
2025-04-03 13:10:01 +02:00
{
lock (instanceLock)
{
2025-04-03 14:18:27 +02:00
foreach (var i in instances) i.CheckErrors();
2025-04-03 13:10:01 +02:00
}
}
}
}