feat: complete TASK-WP0-07 supervisor
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Dada.Supervisor;
|
||||
|
||||
internal sealed class SupervisorRuntime : IAsyncDisposable
|
||||
{
|
||||
private readonly ICredentialStore credentials;
|
||||
private ManagedComponentSupervisor? api;
|
||||
private ManagedComponentSupervisor? worker;
|
||||
|
||||
internal SupervisorRuntime(ICredentialStore credentials)
|
||||
{
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
internal event Action<SupervisorState>? StateChanged;
|
||||
|
||||
internal async Task<SupervisorState> StartAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (LoopbackPortGuard.Check() == SupervisorState.PortInUse) return SupervisorState.PortInUse;
|
||||
var configuration = new InstanceConfigurationStore().Load();
|
||||
if (configuration.LocalDataRoot is null || configuration.AssetRoot is null ||
|
||||
!Directory.Exists(configuration.LocalDataRoot) || !Directory.Exists(configuration.AssetRoot))
|
||||
{
|
||||
return SupervisorState.StartupFailed;
|
||||
}
|
||||
if (CredentialCatalog.RequiredFor(ChildRole.Api).Concat(CredentialCatalog.RequiredFor(ChildRole.Worker)).Any(target => !credentials.IsConfigured(target)))
|
||||
{
|
||||
return SupervisorState.StartupFailed;
|
||||
}
|
||||
|
||||
var node = Path.Combine(AppContext.BaseDirectory, "runtime", "node.exe");
|
||||
var apiEntry = Path.Combine(AppContext.BaseDirectory, "apps", "api", "dist", "main.js");
|
||||
var workerEntry = Path.Combine(AppContext.BaseDirectory, "apps", "worker", "dist", "worker.js");
|
||||
if (!File.Exists(node) || !File.Exists(apiEntry) || !File.Exists(workerEntry)) return SupervisorState.StartupFailed;
|
||||
|
||||
api = CreateComponent(node, apiEntry, ChildRole.Api, SupervisorState.ApiDegraded);
|
||||
api.StateChanged += state => StateChanged?.Invoke(state);
|
||||
await api.StartAsync(cancellationToken);
|
||||
|
||||
worker = CreateComponent(node, workerEntry, ChildRole.Worker, SupervisorState.WorkerDegraded);
|
||||
worker.StateChanged += state => StateChanged?.Invoke(state);
|
||||
await worker.StartAsync(cancellationToken);
|
||||
return SupervisorState.Ready;
|
||||
}
|
||||
|
||||
private ManagedComponentSupervisor CreateComponent(string node, string entry, ChildRole role, SupervisorState degradedState) =>
|
||||
new(async cancellationToken =>
|
||||
{
|
||||
var startInfo = new ProcessStartInfo(node);
|
||||
startInfo.ArgumentList.Add(entry);
|
||||
return await ManagedChildProcess.StartAsync(startInfo, role, credentials, cancellationToken);
|
||||
}, degradedState);
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
var stops = new List<Task>();
|
||||
if (worker is not null) stops.Add(worker.DisposeAsync().AsTask());
|
||||
if (api is not null) stops.Add(api.DisposeAsync().AsTask());
|
||||
await Task.WhenAll(stops);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user