feat: Add Node.js worker implementation and integrate worker type selection in UI

This commit is contained in:
Holger Börchers
2026-02-24 20:21:21 +01:00
parent c09fe5fd36
commit f7b038faf9
4 changed files with 361 additions and 20 deletions

View File

@@ -7,12 +7,27 @@ using CommIpc;
namespace ParentAvalonia;
public enum WorkerType
{
CSharp,
NodeJs,
}
public sealed class MainViewModel : NotifyBase, IAsyncDisposable
{
private ChildSession? _selectedChild;
private bool _childrenStarted;
private WorkerType _selectedWorkerType = WorkerType.CSharp;
private readonly CancellationTokenSource _shutdownCts = new();
public WorkerType[] WorkerTypes { get; } = Enum.GetValues<WorkerType>();
public WorkerType SelectedWorkerType
{
get => _selectedWorkerType;
set => SetField(ref _selectedWorkerType, value);
}
public ObservableCollection<ChildSession> Children { get; } = new();
public ChildSession? SelectedChild
@@ -110,36 +125,51 @@ public sealed class MainViewModel : NotifyBase, IAsyncDisposable
_ = Task.Run(() => ReceiveLoopAsync(session), _shutdownCts.Token);
}
private static Process StartChildProcess(int childId, string pipeName)
private Process StartChildProcess(int childId, string pipeName)
{
// Cross-platform friendly: prefer running the built dll via 'dotnet'.
string? solutionRoot = TryFindSolutionRoot(AppContext.BaseDirectory);
if (solutionRoot is null)
{
throw new InvalidOperationException("Could not find solution root (CommTester.slnx).");
}
string debugDll = Path.Combine(solutionRoot, "ChildWorker", "bin", "Debug", "net10.0", "ChildWorker.dll");
string releaseDll = Path.Combine(solutionRoot, "ChildWorker", "bin", "Release", "net10.0", "ChildWorker.dll");
string childDll =
File.Exists(debugDll) ? debugDll
: File.Exists(releaseDll) ? releaseDll
: string.Empty;
string fileName;
string arguments;
if (!string.IsNullOrWhiteSpace(childDll))
switch (SelectedWorkerType)
{
fileName = "dotnet";
arguments = $"\"{childDll}\" --pipe \"{pipeName}\" --id {childId}";
}
else
{
// Last-resort: run via project (slower but robust in fresh checkouts).
string csproj = Path.Combine(solutionRoot, "ChildWorker", "ChildWorker.csproj");
fileName = "dotnet";
arguments = $"run --project \"{csproj}\" -- --pipe \"{pipeName}\" --id {childId}";
case WorkerType.NodeJs:
string nodeScript = Path.Combine(solutionRoot, "ChildWorkerNode", "child-worker.js");
if (!File.Exists(nodeScript))
{
throw new FileNotFoundException($"Node.js worker not found: {nodeScript}");
}
fileName = "node";
arguments = $"\"{nodeScript}\" --pipe \"{pipeName}\" --id {childId}";
break;
case WorkerType.CSharp:
default:
string debugDll = Path.Combine(solutionRoot, "ChildWorker", "bin", "Debug", "net10.0", "ChildWorker.dll");
string releaseDll = Path.Combine(solutionRoot, "ChildWorker", "bin", "Release", "net10.0", "ChildWorker.dll");
string childDll =
File.Exists(debugDll) ? debugDll
: File.Exists(releaseDll) ? releaseDll
: string.Empty;
if (!string.IsNullOrWhiteSpace(childDll))
{
fileName = "dotnet";
arguments = $"\"{childDll}\" --pipe \"{pipeName}\" --id {childId}";
}
else
{
string csproj = Path.Combine(solutionRoot, "ChildWorker", "ChildWorker.csproj");
fileName = "dotnet";
arguments = $"run --project \"{csproj}\" -- --pipe \"{pipeName}\" --id {childId}";
}
break;
}
var psi = new ProcessStartInfo

View File

@@ -8,6 +8,9 @@
<Grid Margin="12" RowDefinitions="Auto,12,*" ColumnDefinitions="260,12,*">
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Orientation="Horizontal" Spacing="8">
<ComboBox ItemsSource="{Binding WorkerTypes}"
SelectedItem="{Binding SelectedWorkerType}"
Width="120" VerticalAlignment="Center" />
<Button Content="Start 3 Children" Padding="12,6" Click="StartChildren_Click" />
<Button Content="Ping Selected" Padding="12,6" Click="PingSelected_Click" />
<Button Content="Start Work" Padding="12,6" Click="StartWork_Click" />