Merge branch 'feat/ContainerHelper' into v2.1
Some checks failed
Dev Publish: Nuget / Publish Dev Packages (push) Failing after 31s

# Conflicts:
#	Moonlight.Api/Services/ApplicationService.cs
#	Moonlight.Api/Startup/Startup.Base.cs
#	Moonlight.Shared/Http/SerializationContext.cs
This commit is contained in:
2026-02-09 08:18:56 +01:00
72 changed files with 1416 additions and 606 deletions

View File

@@ -0,0 +1,117 @@
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using Moonlight.Api.Http.Services.ContainerHelper;
using Moonlight.Api.Http.Services.ContainerHelper.Requests;
using Moonlight.Api.Http.Services.ContainerHelper.Events;
namespace Moonlight.Api.Services;
public class ContainerHelperService
{
private readonly IHttpClientFactory HttpClientFactory;
public ContainerHelperService(IHttpClientFactory httpClientFactory)
{
HttpClientFactory = httpClientFactory;
}
public async Task<bool> CheckConnectionAsync()
{
var client = HttpClientFactory.CreateClient("ContainerHelper");
try
{
var response = await client.GetAsync("api/ping");
response.EnsureSuccessStatusCode();
return true;
}
catch (Exception)
{
return false;
}
}
public async IAsyncEnumerable<RebuildEventDto> RebuildAsync(bool noBuildCache)
{
var client = HttpClientFactory.CreateClient("ContainerHelper");
var request = new HttpRequestMessage(HttpMethod.Post, "api/rebuild");
request.Content = JsonContent.Create(
new RequestRebuildDto(noBuildCache),
null,
SerializationContext.TunedOptions
);
var response = await client.SendAsync(
request,
HttpCompletionOption.ResponseHeadersRead
);
if (!response.IsSuccessStatusCode)
{
var responseText = await response.Content.ReadAsStringAsync();
yield return new RebuildEventDto()
{
Type = RebuildEventType.Failed,
Data = responseText
};
yield break;
}
await using var responseStream = await response.Content.ReadAsStreamAsync();
using var streamReader = new StreamReader(responseStream);
do
{
var line = await streamReader.ReadLineAsync();
if (line == null)
break;
if (string.IsNullOrWhiteSpace(line))
continue;
var data = line.Trim("data: ");
var deserializedData = JsonSerializer.Deserialize<RebuildEventDto>(data, SerializationContext.TunedOptions);
yield return deserializedData;
// Exit if service will go down for a clean exit
if (deserializedData is { Type: RebuildEventType.Step, Data: "ServiceDown" })
yield break;
} while (true);
yield return new RebuildEventDto()
{
Type = RebuildEventType.Succeeded,
Data = string.Empty
};
}
public async Task SetVersionAsync(string version)
{
var client = HttpClientFactory.CreateClient("ContainerHelper");
var response = await client.PostAsJsonAsync(
"api/configuration/version",
new SetVersionDto(version),
SerializationContext.TunedOptions
);
if (response.IsSuccessStatusCode)
return;
var problemDetails =
await response.Content.ReadFromJsonAsync<ProblemDetails>(SerializationContext.TunedOptions);
if (problemDetails == null)
throw new HttpRequestException($"Failed to set version: {response.ReasonPhrase}");
throw new HttpRequestException($"Failed to set version: {problemDetails.Detail ?? problemDetails.Title}");
}
}