Implemented node crud and status health check. Added daemon status health endpoint. Refactored project structure. Added sidebar items and ui views
This commit is contained in:
132
MoonlightServers.Api/Admin/Nodes/NodeService.cs
Normal file
132
MoonlightServers.Api/Admin/Nodes/NodeService.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using MoonlightServers.Api.Infrastructure.Database.Entities;
|
||||
using MoonlightServers.DaemonShared.Http;
|
||||
using MoonlightServers.DaemonShared.Http.Daemon;
|
||||
|
||||
namespace MoonlightServers.Api.Admin.Nodes;
|
||||
|
||||
public class NodeService
|
||||
{
|
||||
private readonly IHttpClientFactory ClientFactory;
|
||||
private readonly ILogger<NodeService> Logger;
|
||||
public NodeService(IHttpClientFactory clientFactory, ILogger<NodeService> logger)
|
||||
{
|
||||
ClientFactory = clientFactory;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
public async Task<NodeHealthStatus> GetHealthAsync(Node node)
|
||||
{
|
||||
var client = ClientFactory.CreateClient();
|
||||
|
||||
var request = CreateBaseRequest(node, HttpMethod.Get, "api/health");
|
||||
|
||||
try
|
||||
{
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return new NodeHealthStatus((int)response.StatusCode, null);
|
||||
|
||||
try
|
||||
{
|
||||
var health = await response
|
||||
.Content
|
||||
.ReadFromJsonAsync<HealthDto>(SerializationContext.Default.Options);
|
||||
|
||||
return new NodeHealthStatus((int)response.StatusCode, health);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogTrace(e, "An unhandled error occured while processing health response of node {id}", node.Id);
|
||||
|
||||
return new NodeHealthStatus((int)response.StatusCode, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogTrace(e, "An error occured while fetching health status of node {id}", node.Id);
|
||||
return new NodeHealthStatus(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static HttpRequestMessage CreateBaseRequest(
|
||||
Node node,
|
||||
[StringSyntax(StringSyntaxAttribute.Uri)]
|
||||
HttpMethod method,
|
||||
string endpoint
|
||||
)
|
||||
{
|
||||
var request = new HttpRequestMessage();
|
||||
|
||||
request.Headers.Add(HeaderNames.Authorization, node.Token);
|
||||
request.RequestUri = new Uri(new Uri(node.HttpEndpointUrl), endpoint);
|
||||
request.Method = method;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private async Task EnsureSuccessAsync(HttpResponseMessage message)
|
||||
{
|
||||
if (message.IsSuccessStatusCode)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var problemDetails = await message.Content.ReadFromJsonAsync<ProblemDetails>(
|
||||
SerializationContext.Default.Options
|
||||
);
|
||||
|
||||
if (problemDetails == null)
|
||||
{
|
||||
// If we cant handle problem details, we handle it natively
|
||||
message.EnsureSuccessStatusCode();
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse into exception
|
||||
throw new NodeException(
|
||||
problemDetails.Type,
|
||||
problemDetails.Title,
|
||||
problemDetails.Status,
|
||||
problemDetails.Detail,
|
||||
problemDetails.Errors
|
||||
);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// If we cant handle problem details, we handle it natively
|
||||
message.EnsureSuccessStatusCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record NodeHealthStatus(int StatusCode, HealthDto? Dto);
|
||||
|
||||
public class NodeException : Exception
|
||||
{
|
||||
public string Type { get; }
|
||||
public string Title { get; }
|
||||
public int Status { get; }
|
||||
public string? Detail { get; }
|
||||
public Dictionary<string, string[]>? Errors { get; }
|
||||
|
||||
public NodeException(
|
||||
string type,
|
||||
string title,
|
||||
int status,
|
||||
string? detail = null,
|
||||
Dictionary<string, string[]>? errors = null)
|
||||
: base(detail ?? title)
|
||||
{
|
||||
Type = type;
|
||||
Title = title;
|
||||
Status = status;
|
||||
Detail = detail;
|
||||
Errors = errors;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user