use SemaphoreSlim to limit the amount of parallel http requests

This commit is contained in:
Pilzinsel64
2025-01-24 06:10:43 +01:00
parent fcd23152e2
commit 232c94c61f

View File

@@ -16,6 +16,7 @@ public class ApiServer(string apiUrl) : IApiServer
protected HttpListener httpListener = new();
protected int restartAttempts = 0;
protected DateTime lastRestartAttempt;
protected SemaphoreSlim? semaphore;
public event OnCheckAuthenticationEventHandler? OnCheckAuthentication;
public event OnCheckContextEventHandler? OnCheckContext;
@@ -45,6 +46,8 @@ public class ApiServer(string apiUrl) : IApiServer
public int MaxAutoRestartsPerMinute { get; set; } = 10;
public int MaxConcurentConnections { get; set; } = 5;
public virtual void Start()
{
Log.Info("Starting listener");
@@ -68,6 +71,7 @@ public class ApiServer(string apiUrl) : IApiServer
Log.Info("Restarting listener");
Stop();
httpListener = new();
semaphore?.Release(int.MaxValue);
Start();
Log.Info("Restarted listener");
}
@@ -92,6 +96,17 @@ public class ApiServer(string apiUrl) : IApiServer
return true;
}
protected virtual void WaitForSlot()
{
semaphore ??= new(MaxConcurentConnections);
semaphore.Wait();
}
protected virtual void FreeSlot()
{
semaphore?.Release();
}
public virtual void RegisterHandler<T>(T instance) where T : class
{
// Get all public instance methods
@@ -166,6 +181,18 @@ public class ApiServer(string apiUrl) : IApiServer
if (!httpListener.IsListening)
return;
// Wait for a free slot
try
{
WaitForSlot();
}
catch (Exception ex)
{
Log.Fatal($"Too many concurent connections", ex);
Thread.Sleep(1000);
return;
}
// Get context
try
{
@@ -195,7 +222,10 @@ public class ApiServer(string apiUrl) : IApiServer
// Cancel if we don't have a context
if (context is null)
{
FreeSlot();
return;
}
// Check context
Log.Info("Request retrived for " + context.Request.RawUrl);
@@ -215,6 +245,9 @@ public class ApiServer(string apiUrl) : IApiServer
OnCheckContextCompleted?.Invoke(this, new(context));
}
// Release slot
FreeSlot();
// Listen for new request
if (!AllowMultipleRequests)
Receive();