Added container rebuild flow with real-time logs and updated UI, backend implementation, config options, and container helper API integration.

This commit is contained in:
2026-01-23 16:38:42 +01:00
parent 76a8a72e83
commit e2f344ab4e
11 changed files with 300 additions and 37 deletions

View File

@@ -1,37 +1,31 @@
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase
@using System.Text.Json
@using LucideBlazor
@using Moonlight.Shared.Http
@using Moonlight.Shared.Http.Events
@using ShadcnBlazor.Dialogs
@using ShadcnBlazor.Extras.AlertDialogs
@using ShadcnBlazor.Progresses
@using ShadcnBlazor.Spinners
@inject AlertDialogService AlertService
@inject HttpClient HttpClient
<DialogHeader>
<DialogTitle>
Updating...
Updating instance...
</DialogTitle>
</DialogHeader>
<div class="text-base flex flex-col p-2 gap-y-0.5">
@for (var i = 0; i < Steps.Length; i++)
{
if (CurrentStep == i)
<div class="grid grid-cols-1 xl:grid-cols-2 w-full gap-5">
<div class="text-base flex flex-col p-2 gap-y-0.5">
@for (var i = 0; i < Steps.Length; i++)
{
<div class="flex flex-row items-center gap-x-2">
<Spinner ClassName="size-4" />
<span>
@Steps[i]
</span>
</div>
}
else
{
if (i < CurrentStep)
if (CurrentStep == i)
{
<div class="flex flex-row items-center gap-x-2">
<CheckIcon ClassName="text-green-500 size-4" />
<Spinner ClassName="size-4"/>
<span>
@Steps[i]
</span>
@@ -39,13 +33,33 @@
}
else
{
<div class="text-muted-foreground flex flex-row items-center gap-x-2">
<span class="size-4"></span>
@Steps[i]
</div>
if (i < CurrentStep)
{
<div class="flex flex-row items-center gap-x-2">
<CheckIcon ClassName="text-green-500 size-4"/>
<span>
@Steps[i]
</span>
</div>
}
else
{
<div class="text-muted-foreground flex flex-row items-center gap-x-2">
<span class="size-4"></span>
@Steps[i]
</div>
}
}
}
}
</div>
<div class="bg-black text-white rounded-lg font-mono h-96 flex flex-col-reverse overflow-auto p-3 scrollbar-thin">
@for (var i = LogLines.Count - 1; i >= 0; i--)
{
<div>
@LogLines[i]
</div>
}
</div>
</div>
<DialogFooter>
@@ -62,12 +76,15 @@
[
"Preparing",
"Updating configuration files",
"Starting rebuild task",
"Building docker image",
"Redeploying container instance",
"Waiting for container instance to start up",
"Update complete"
];
private List<string?> LogLines = new();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
@@ -83,30 +100,100 @@
Progress = 20;
await InvokeAsync(StateHasChanged);
await Task.Delay(6000);
CurrentStep = 2;
Progress = 40;
await InvokeAsync(StateHasChanged);
await Task.Delay(2000);
CurrentStep = 3;
Progress = 60;
CurrentStep = 2;
Progress = 30;
await InvokeAsync(StateHasChanged);
await Task.Delay(4000);
var response = await HttpClient.SendAsync(
new HttpRequestMessage(HttpMethod.Post, "api/admin/ch/rebuild"),
HttpCompletionOption.ResponseHeadersRead
);
CurrentStep = 4;
Progress = 80;
await InvokeAsync(StateHasChanged);
await using var responseStream = await response.Content.ReadAsStreamAsync();
using var streamReader = new StreamReader(responseStream);
await Task.Delay(4000);
do
{
try
{
var line = await streamReader.ReadLineAsync();
if (line == null)
break;
if (string.IsNullOrWhiteSpace(line))
continue;
var data = line.Trim("data: ");
var deserializedData = JsonSerializer.Deserialize<RebuildEvent>(data, Constants.SerializerOptions);
switch (deserializedData.Type)
{
case RebuildEventType.Log:
LogLines.Add(deserializedData.Data);
break;
case RebuildEventType.Step:
switch (deserializedData.Data)
{
case "BuildImage":
CurrentStep = 3;
Progress = 40;
await InvokeAsync(StateHasChanged);
break;
case "ServiceDown":
CurrentStep = 4;
Progress = 60;
await InvokeAsync(StateHasChanged);
break;
case "ServiceUp":
CurrentStep = 4;
Progress = 80;
await InvokeAsync(StateHasChanged);
break;
}
break;
}
await InvokeAsync(StateHasChanged);
}
catch (Exception e)
{
// TODO: Log
break;
}
} while (true);
CurrentStep = 5;
Progress = 90;
await InvokeAsync(StateHasChanged);
// Ping instance until its reachable again
while (true)
{
try
{
await HttpClient.GetStringAsync("api/ping");
break;
}
catch (Exception)
{
// Ignored
}
await Task.Delay(3000);
}
CurrentStep = 6;
Progress = 100;
await InvokeAsync(StateHasChanged);
await Task.Delay(1000);
await AlertService.SuccessAsync(