AddTraxWorker
Registers a standalone worker process that polls the background_job table and executes trains. No scheduler logic, just execution.
Signature
public static IServiceCollection AddTraxWorker(
this IServiceCollection services,
Action<LocalWorkerOptions>? configure = null
)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
configure | Action<LocalWorkerOptions>? | No | Optional callback to customize worker count, polling interval, and timeouts |
LocalWorkerOptions
| Property | Type | Default | Description |
|---|---|---|---|
WorkerCount | int | Environment.ProcessorCount | Number of concurrent worker tasks polling for jobs |
PollingInterval | TimeSpan | 1 second | How often idle workers poll for new jobs |
VisibilityTimeout | TimeSpan | 30 minutes | How long a claimed job stays invisible before another worker can reclaim it (crash recovery) |
ShutdownTimeout | TimeSpan | 30 seconds | Grace period for in-flight jobs during shutdown |
These are the same options used by ConfigureLocalWorkers.
Examples
Basic Standalone Worker
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTrax(trax => trax
.AddEffects(effects => effects
.UsePostgres(connectionString)
)
.AddMediator(typeof(MyTrain).Assembly)
);
builder.Services.AddTraxWorker();
var app = builder.Build();
app.Run();
Custom Worker Configuration
builder.Services.AddTraxWorker(opts =>
{
opts.WorkerCount = 4;
opts.PollingInterval = TimeSpan.FromSeconds(2);
opts.VisibilityTimeout = TimeSpan.FromMinutes(15);
opts.ShutdownTimeout = TimeSpan.FromMinutes(1);
});
Multiple Worker Processes
You can run multiple standalone worker processes against the same database. PostgreSQL’s FOR UPDATE SKIP LOCKED guarantees each job is claimed by exactly one worker. No duplicates, no coordination needed.
┌── Worker Process A ──┐ ┌── Worker Process B ──┐
│ 4 worker tasks │ │ 4 worker tasks │
│ polling same table │ │ polling same table │
└───────────┬───────────┘ └───────────┬───────────┘
│ │
└──────────┬─────────────────┘
▼
background_job table
(SKIP LOCKED ensures
no duplicate claims)
What It Registers
AddTraxWorker() internally calls AddTraxJobRunner() and adds the worker service:
| Service | Lifetime | Description |
|---|---|---|
All services from AddTraxJobRunner() | (various) | Execution pipeline (JobRunnerTrain, CancellationRegistry, etc.) |
LocalWorkerOptions | Singleton | Worker configuration |
LocalWorkerService | Hosted Service | Background worker that polls background_job and executes trains |
Not registered: ManifestManager, JobDispatcher, polling services, startup service. This process only executes; it doesn’t schedule or dispatch.
How It Differs from the Scheduler’s Local Workers
| Aspect | Scheduler (with Postgres) | AddTraxWorker() |
|---|---|---|
| Used in | Full scheduler process | Standalone worker process |
| Scheduling | Yes (ManifestManager, JobDispatcher) | No |
| Dispatching | Yes (writes to WorkQueue, background_job) | No |
| Execution | Yes (LocalWorkerService) | Yes (LocalWorkerService) |
| Job submitter | Registers PostgresJobSubmitter | Does not register any submitter |
Shared Requirements
The standalone worker must:
- Reference the same train assemblies passed to
AddMediator(). Train types are resolved by fully-qualified name. - Connect to the same Postgres database. Metadata, manifests, and state are shared across all processes.
- Register the effect system.
AddTrax()withUsePostgres()is required.
Package
dotnet add package Trax.Scheduler
See Also
- Remote Execution: architecture overview and deployment models
- ConfigureLocalWorkers: customizing local workers within the scheduler process
- AddTraxJobRunner: push-based alternative (HTTP endpoint)