auto-restart on fatal http error
This commit is contained in:
@@ -13,7 +13,9 @@ public class ApiServer(string apiUrl) : IApiServer
|
|||||||
{
|
{
|
||||||
protected readonly List<PrivateMessageHandler> handlers = [];
|
protected readonly List<PrivateMessageHandler> handlers = [];
|
||||||
protected readonly Dictionary<Type, IApiMessageSerializer> serializers = [];
|
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 OnCheckAuthenticationEventHandler? OnCheckAuthentication;
|
||||||
public event OnCheckContextEventHandler? OnCheckContext;
|
public event OnCheckContextEventHandler? OnCheckContext;
|
||||||
@@ -37,18 +39,48 @@ public class ApiServer(string apiUrl) : IApiServer
|
|||||||
|
|
||||||
public bool AllowMultipleRequests { get; set; }
|
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()
|
public virtual void Start()
|
||||||
{
|
{
|
||||||
Log.Info("Start listening");
|
Log.Info("Starting listener");
|
||||||
httpListener.Prefixes.Add(ApiUrl + "/");
|
httpListener.Prefixes.Add(ApiUrl + "/");
|
||||||
httpListener.Start();
|
httpListener.Start();
|
||||||
|
Log.Info("Started listener");
|
||||||
Receive();
|
Receive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Stop()
|
public virtual void Stop()
|
||||||
{
|
{
|
||||||
|
Log.Info("Stopping listener");
|
||||||
httpListener.Stop();
|
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
|
public virtual void RegisterHandler<T>(T instance) where T : class
|
||||||
@@ -130,6 +162,18 @@ public class ApiServer(string apiUrl) : IApiServer
|
|||||||
{
|
{
|
||||||
context = httpListener.EndGetContext(result);
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error("Error retriving context", ex);
|
Log.Error("Error retriving context", ex);
|
||||||
@@ -251,11 +295,13 @@ public class ApiServer(string apiUrl) : IApiServer
|
|||||||
context.Response.ContentType = "application/json";
|
context.Response.ContentType = "application/json";
|
||||||
using StreamWriter output = new(context.Response.OutputStream);
|
using StreamWriter output = new(context.Response.OutputStream);
|
||||||
output.Write(resultJson);
|
output.Write(resultJson);
|
||||||
|
output.Flush();
|
||||||
}
|
}
|
||||||
else if (result.ResultContent is byte[] resultBytes)
|
else if (result.ResultContent is byte[] resultBytes)
|
||||||
{
|
{
|
||||||
Log.Info("Sending raw bytes response for " + context.Request.RawUrl);
|
Log.Info("Sending raw bytes response for " + context.Request.RawUrl);
|
||||||
context.Response.OutputStream.Write(resultBytes, 0, resultBytes.Length);
|
context.Response.OutputStream.Write(resultBytes, 0, resultBytes.Length);
|
||||||
|
context.Response.OutputStream.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Debug("Finish response");
|
Log.Debug("Finish response");
|
||||||
|
|||||||
Reference in New Issue
Block a user