Added retry class and added it to some api calls that need it
This commit is contained in:
parent
a894707536
commit
f191533410
66
Moonlight/App/Helpers/Retry.cs
Normal file
66
Moonlight/App/Helpers/Retry.cs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
namespace Moonlight.App.Helpers;
|
||||||
|
|
||||||
|
public class Retry
|
||||||
|
{
|
||||||
|
private List<Type> RetryExceptionTypes;
|
||||||
|
private List<Func<Exception, bool>> RetryFilters;
|
||||||
|
private int RetryTimes = 1;
|
||||||
|
|
||||||
|
public Retry()
|
||||||
|
{
|
||||||
|
RetryExceptionTypes = new();
|
||||||
|
RetryFilters = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Retry Times(int times)
|
||||||
|
{
|
||||||
|
RetryTimes = times;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Retry At(Func<Exception, bool> filter)
|
||||||
|
{
|
||||||
|
RetryFilters.Add(filter);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Retry At<T>()
|
||||||
|
{
|
||||||
|
RetryExceptionTypes.Add(typeof(T));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Call(Func<Task> method)
|
||||||
|
{
|
||||||
|
int triesLeft = RetryTimes;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await method.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if(triesLeft < 1) // Throw if no tries left
|
||||||
|
throw;
|
||||||
|
|
||||||
|
if (RetryExceptionTypes.Any(x => x.FullName == e.GetType().FullName))
|
||||||
|
{
|
||||||
|
triesLeft--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RetryFilters.Any(x => x.Invoke(e)))
|
||||||
|
{
|
||||||
|
triesLeft--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throw if not filtered -> unknown/unhandled
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
} while (triesLeft >= 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,10 +79,20 @@ public class ServerService
|
||||||
{
|
{
|
||||||
Server server = EnsureNodeData(s);
|
Server server = EnsureNodeData(s);
|
||||||
|
|
||||||
return await WingsApiHelper.Get<ServerDetails>(
|
ServerDetails result = null!;
|
||||||
server.Node,
|
|
||||||
$"api/servers/{server.Uuid}"
|
await new Retry()
|
||||||
);
|
.Times(3)
|
||||||
|
.At(x => x.Message.Contains("A task was canceled"))
|
||||||
|
.Call(async () =>
|
||||||
|
{
|
||||||
|
result = await WingsApiHelper.Get<ServerDetails>(
|
||||||
|
server.Node,
|
||||||
|
$"api/servers/{server.Uuid}"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetPowerState(Server s, PowerSignal signal)
|
public async Task SetPowerState(Server s, PowerSignal signal)
|
||||||
|
@ -305,11 +315,17 @@ public class ServerService
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await WingsApiHelper.Post(node, $"api/servers", new CreateServer()
|
await new Retry()
|
||||||
{
|
.Times(3)
|
||||||
Uuid = newServerData.Uuid,
|
.At(x => x.Message.Contains("A task was canceled"))
|
||||||
StartOnCompletion = false
|
.Call(async () =>
|
||||||
});
|
{
|
||||||
|
await WingsApiHelper.Post(node, $"api/servers", new CreateServer()
|
||||||
|
{
|
||||||
|
Uuid = newServerData.Uuid,
|
||||||
|
StartOnCompletion = false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
//TODO: AuditLog
|
//TODO: AuditLog
|
||||||
|
|
||||||
|
|
|
@ -352,206 +352,4 @@
|
||||||
InvokeAsync(StateHasChanged);
|
InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@*
|
|
||||||
@if (AllServers.Any())
|
|
||||||
{
|
|
||||||
if (UseSortedServerView)
|
|
||||||
{
|
|
||||||
var groupedServers = AllServers
|
|
||||||
.OrderBy(x => x.Name)
|
|
||||||
.GroupBy(x => x.Image.Name);
|
|
||||||
|
|
||||||
foreach (var groupedServer in groupedServers)
|
|
||||||
{
|
|
||||||
<div class="separator separator-content my-15">@(groupedServer.Key)</div>
|
|
||||||
<div class="card card-body bg-secondary py-0 my-0 mx-0 px-0">
|
|
||||||
@foreach (var server in groupedServer)
|
|
||||||
{
|
|
||||||
<div class="row mx-4 my-4">
|
|
||||||
<a class="card card-body" href="/server/@(server.Uuid)">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<div class="symbol symbol-50px me-3">
|
|
||||||
<i class="bx bx-md bx-server"></i>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex justify-content-start flex-column">
|
|
||||||
<a href="/server/@(server.Uuid)" class="text-gray-800 text-hover-primary mb-1 fs-5">
|
|
||||||
@(server.Name)
|
|
||||||
</a>
|
|
||||||
<span class="text-gray-400 fw-semibold d-block fs-6">
|
|
||||||
@(Math.Round(server.Memory / 1024D, 2)) GB / @(Math.Round(server.Disk / 1024D, 2)) GB / @(server.Node.Name) <span class="text-gray-700">- @(server.Image.Name)</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="d-none d-sm-block col my-auto fs-6">
|
|
||||||
@(server.Node.Fqdn):@(server.MainAllocation.Port)
|
|
||||||
</div>
|
|
||||||
<div class="d-none d-sm-block col my-auto fs-6">
|
|
||||||
@if (StatusCache.ContainsKey(server))
|
|
||||||
{
|
|
||||||
var status = StatusCache[server];
|
|
||||||
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case "offline":
|
|
||||||
<span class="text-danger">
|
|
||||||
<TL>Offline</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "stopping":
|
|
||||||
<span class="text-warning">
|
|
||||||
<TL>Stopping</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "starting":
|
|
||||||
<span class="text-warning">
|
|
||||||
<TL>Starting</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "running":
|
|
||||||
<span class="text-success">
|
|
||||||
<TL>Running</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "failed":
|
|
||||||
<span class="text-gray-400">
|
|
||||||
<TL>Failed</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
<span class="text-danger">
|
|
||||||
<TL>Offline</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span class="text-gray-400">
|
|
||||||
<TL>Loading</TL>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var server in AllServers)
|
|
||||||
{
|
|
||||||
<div class="row px-5 mb-5">
|
|
||||||
<a class="card card-body" href="/server/@(server.Uuid)">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<div class="symbol symbol-50px me-3">
|
|
||||||
<i class="bx bx-md bx-server"></i>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex justify-content-start flex-column">
|
|
||||||
<a href="/server/@(server.Uuid)" class="text-gray-800 text-hover-primary mb-1 fs-5">
|
|
||||||
@(server.Name)
|
|
||||||
</a>
|
|
||||||
<span class="text-gray-400 fw-semibold d-block fs-6">
|
|
||||||
@(Math.Round(server.Memory / 1024D, 2)) GB / @(Math.Round(server.Disk / 1024D, 2)) GB / @(server.Node.Name) <span class="text-gray-700">- @(server.Image.Name)</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="d-none d-sm-block col my-auto fs-6">
|
|
||||||
@(server.Node.Fqdn):@(server.MainAllocation.Port)
|
|
||||||
</div>
|
|
||||||
<div class="d-none d-sm-block col my-auto fs-6">
|
|
||||||
@if (StatusCache.ContainsKey(server))
|
|
||||||
{
|
|
||||||
var status = StatusCache[server];
|
|
||||||
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case "offline":
|
|
||||||
<span class="text-danger">
|
|
||||||
<TL>Offline</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "stopping":
|
|
||||||
<span class="text-warning">
|
|
||||||
<TL>Stopping</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "starting":
|
|
||||||
<span class="text-warning">
|
|
||||||
<TL>Starting</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "running":
|
|
||||||
<span class="text-success">
|
|
||||||
<TL>Running</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
case "failed":
|
|
||||||
<span class="text-gray-400">
|
|
||||||
<TL>Failed</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
<span class="text-danger">
|
|
||||||
<TL>Offline</TL>
|
|
||||||
</span>
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span class="text-gray-400">
|
|
||||||
<TL>Loading</TL>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="alert bg-info d-flex flex-column flex-sm-row w-100 p-5">
|
|
||||||
<div class="d-flex flex-column pe-0 pe-sm-10">
|
|
||||||
<h4 class="fw-semibold">
|
|
||||||
<TL>You have no servers</TL>
|
|
||||||
</h4>
|
|
||||||
<span>
|
|
||||||
<TL>We were not able to find any servers associated with your account</TL>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="row mt-7 px-3">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<div class="card-title">
|
|
||||||
<span class="badge badge-primary badge-lg">Beta</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row">
|
|
||||||
<label class="col-lg-4 col-form-label fw-semibold fs-6">Sorted server view</label>
|
|
||||||
<div class="col-lg-8 d-flex align-items-center">
|
|
||||||
<div class="form-check form-check-solid form-switch form-check-custom fv-row">
|
|
||||||
<input class="form-check-input w-45px h-30px" type="checkbox" id="sortedServerView" @bind="UseSortedServerView">
|
|
||||||
<label class="form-check-label" for="sortedServerView"></label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
*@
|
|
Loading…
Reference in a new issue