auto-restart on fatal http error

This commit is contained in:
Pilzinsel64
2025-01-22 15:20:39 +01:00
parent 2018969009
commit d948ba4135

View File

@@ -13,7 +13,9 @@ public class ApiServer(string apiUrl) : IApiServer
{
protected readonly List<PrivateMessageHandler> handlers = [];
protected readonly Dictionary<Type, IApiMessageSerializer> serializers = [];
protected readonly HttpListener httpListener = new();
protected HttpListener httpListener = new();
protected int restartAttempts = 0;
protected DateTime lastRestartAttempt;
public event OnCheckAuthenticationEventHandler? OnCheckAuthentication;
public event OnCheckContextEventHandler? OnCheckContext;
@@ -37,18 +39,48 @@ public class ApiServer(string apiUrl) : IApiServer
public bool AllowMultipleRequests { get; set; }
public int StopDelay { get; set; } = 5000;
public int AutoRestartOnError { get; set; } = 5000;
public int MaxAutoRestartsPerMinute { get; set; } = 10;
public virtual void Start()
{
Log.Info("Start listening");
Log.Info("Starting listener");
httpListener.Prefixes.Add(ApiUrl + "/");
httpListener.Start();
Log.Info("Started listener");
Receive();
}
public virtual void Stop()
{
Log.Info("Stopping listener");
httpListener.Stop();
Log.Info("Stopped listening");
Thread.Sleep(StopDelay);
httpListener.Close();
Log.Info("Stopped listener");
}
public virtual bool Restart()
{
if (restartAttempts > MaxAutoRestartsPerMinute)
return false;
var now = DateTime.Now;
if (now - lastRestartAttempt > TimeSpan.FromMinutes(1))
lastRestartAttempt = now;
restartAttempts += 1;
Log.Info("Restarting listener");
Stop();
httpListener = new();
Start();
Log.Info("Restarted listener");
return true;
}
public virtual void RegisterHandler<T>(T instance) where T : class
@@ -130,6 +162,18 @@ public class ApiServer(string apiUrl) : IApiServer
{
context = httpListener.EndGetContext(result);
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode == 995 || ex.ErrorCode == 64)
{
Log.Fatal($"Fatal http error retriving context with code {ex.ErrorCode}", ex);
if (Restart()) // Try restart the server and skip this context
return;
}
else
Log.Error($"Http error retriving context with code {ex.ErrorCode}", ex);
context = null;
}
catch (Exception ex)
{
Log.Error("Error retriving context", ex);
@@ -251,11 +295,13 @@ public class ApiServer(string apiUrl) : IApiServer
context.Response.ContentType = "application/json";
using StreamWriter output = new(context.Response.OutputStream);
output.Write(resultJson);
output.Flush();
}
else if (result.ResultContent is byte[] resultBytes)
{
Log.Info("Sending raw bytes response for " + context.Request.RawUrl);
context.Response.OutputStream.Write(resultBytes, 0, resultBytes.Length);
context.Response.OutputStream.Flush();
}
Log.Debug("Finish response");