mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-04 02:21:35 -05:00
Large nests tie up the workstation that runs them. In Database mode, Auto Nest can now queue the job on the nest server, where a worker container solves one job at a time under its own CPU and memory limits. The job has no time limit, so a throttled worker finds the same nest a fast one does, only later. - Server: /api/nest-jobs queue (schema v15). The worker holds a job on a heartbeat lease. When the lease lapses, the job goes back to the queue, or fails after three attempts. Only one job runs at a time. Packages and results are opaque to the HTTP server, which stays off Engine and IO. - Worker: OpenNest.Server.Worker in the same image (OPENNEST_ROLE=worker), reaching the server over HTTP only. It records each engine answer with RecordingNestingEngine and gives its job back on shutdown. - Desktop: "Nest on the server" in the Auto Nest dialog, for built-in engines only. The client replays the recorded answers with RemoteNestSubmission, so validation, the review and Keep run locally against the client's own drawings, exactly as after a local run. A drawing edited after sending refuses the result. If the server cannot take the job, the user may nest locally instead. - compose.server.yaml adds the throttled worker service. The Dockerfile, .dockerignore, CI paths and the deploy script now include the worker's projects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.7 KiB
C#
39 lines
1.7 KiB
C#
namespace OpenNest.Server.Worker;
|
|
|
|
/// <summary>Worker settings read from the environment.</summary>
|
|
public sealed class WorkerOptions
|
|
{
|
|
public const string ServerVariable = "OPENNEST_SERVER_URL";
|
|
public const string PollVariable = "OPENNEST_WORKER_POLL_SECONDS";
|
|
public const string AliveVariable = "OPENNEST_WORKER_ALIVE_FILE";
|
|
|
|
/// <summary>The nest server the worker takes jobs from.</summary>
|
|
public required string ServerUrl { get; init; }
|
|
|
|
/// <summary>How long to wait before asking again when no job was queued.</summary>
|
|
public TimeSpan PollInterval { get; init; } = TimeSpan.FromSeconds(5);
|
|
|
|
/// <summary>Touched every round; the container health check fails when it goes stale.</summary>
|
|
public string AliveFile { get; init; } = Path.Combine(Path.GetTempPath(), "opennest-worker.alive");
|
|
|
|
public static WorkerOptions FromEnvironment(Func<string, string?> read)
|
|
{
|
|
var server = read(ServerVariable);
|
|
if (string.IsNullOrWhiteSpace(server))
|
|
throw new InvalidOperationException($"{ServerVariable} must name the nest server, for example http://opennest-server:8090/.");
|
|
var poll = TimeSpan.FromSeconds(5);
|
|
if (read(PollVariable) is { Length: > 0 } text)
|
|
{
|
|
if (!int.TryParse(text, out var seconds) || seconds is < 1 or > 3600)
|
|
throw new InvalidOperationException($"{PollVariable} must be whole seconds from 1 to 3600.");
|
|
poll = TimeSpan.FromSeconds(seconds);
|
|
}
|
|
return new WorkerOptions
|
|
{
|
|
ServerUrl = server.Trim(),
|
|
PollInterval = poll,
|
|
AliveFile = read(AliveVariable) is { Length: > 0 } alive ? alive : Path.Combine(Path.GetTempPath(), "opennest-worker.alive"),
|
|
};
|
|
}
|
|
}
|