Reference

ConfigureLocalWorkers

Package Trax.SchedulerNamespace Trax.Scheduler.ConfigurationSource SchedulerConfigurationBuilder.Settings.cs, LocalWorkerOptions.cs

Configures the built-in local worker pool, which runs queued jobs in the scheduler's own process. The pool is registered whenever the scheduler has a database provider, UsePostgres() or UseSqlite(), whether or not this is called.

Signature

public SchedulerConfigurationBuilder ConfigureLocalWorkers(
    Action<LocalWorkerOptions> configure
)

Parameters

ParameterTypeDescription
configureAction<LocalWorkerOptions>Sets the worker count, polling interval and timeouts

LocalWorkerOptions

PropertyTypeDefaultDescription
WorkerCountintEnvironment.ProcessorCount, or 1 on SQLiteNumber of concurrent worker tasks polling for jobs. 1 to 256. A value you set is used on either provider
PollingIntervalTimeSpan1 secondHow often idle workers poll for new jobs. Greater than zero, up to 30 days
VisibilityTimeoutTimeSpan30 minutesHow long a claimed job stays invisible after its worker last refreshed its claim before another worker can reclaim it (crash recovery). A running job's claim is refreshed every third of this, so a long job is not reclaimed while it runs
BatchSizeint1Number of jobs each worker claims per poll cycle. At least 1. Every job in the batch keeps its claim until the worker runs it, however long the jobs ahead of it take
ShutdownTimeoutTimeSpan30 secondsGrace period for in-flight jobs during shutdown. 0 to 30 days

Returns

SchedulerConfigurationBuilder, for chaining.

Behavior

  • Local workers use the IDataContext the database provider registers.
  • Jobs are queued to the trax.background_job table. On Postgres they are dequeued with FOR UPDATE SKIP LOCKED, so workers in any number of processes claim without blocking each other.
  • On SQLite each claim runs under BEGIN IMMEDIATE, which takes the file's write lock. Workers queue on that lock rather than running side by side, so the pool starts one worker unless you set WorkerCount, and more do not help.
  • Workers delete job rows after execution (both success and failure), including a job that finishes during shutdown: the delete does not take the host's stopping token. Trax.Core's Metadata and DeadLetter tables handle the audit trail.
  • AddScheduler refuses options outside their ranges when it is built (see Value Ranges); VisibilityTimeout must be between one second and ten years.
  • While a worker holds jobs, it refreshes the fetched_at of every job it has claimed and not yet finished, the running one and any waiting behind it in a batch, every third of VisibilityTimeout. If a worker crashes mid-execution, the refreshes stop, the timestamp becomes stale, and the job is reclaimed after VisibilityTimeout.
  • A job waiting in trax.background_job for a free worker is not failed by the stale-pending reaper, however long it waits.
  • A job that fails before its run starts (its input cannot be read, or the run's start cannot be written) is deleted like any other, and the worker fails the run itself, still Pending, with the reason "The job failed before its run started". The failure goes through the lifecycle hooks at once, so a machine that invoked the run reaches its OnFailed target without waiting for the stale-pending reaper. The worker's log has the error. A run that started records its own outcome.
  • With UseRemoteWorkers(), UseSqsWorkers() or UseLambdaWorkers() also configured, local workers still run every train those calls do not route.

Registered services

With a database provider, the scheduler registers:

ServiceLifetimeDescription
LocalWorkerOptionsSingletonConfiguration options
IJobRunnerTrain → JobRunnerTrainScopedThe train that workers use to execute each job
IJobSubmitter → PostgresJobSubmitterScopedEnqueue implementation (INSERT into background_job)
LocalWorkerServiceHosted ServiceBackground worker that polls and executes jobs

Example

services.AddTrax(trax => trax
    .AddEffects(effects => effects.UsePostgres(connectionString))
    .AddMediator(assembly)
    .AddScheduler(scheduler => scheduler
        .ConfigureLocalWorkers(options =>
        {
            options.WorkerCount = 4;
            options.PollingInterval = TimeSpan.FromSeconds(2);
            options.VisibilityTimeout = TimeSpan.FromMinutes(15);
            options.ShutdownTimeout = TimeSpan.FromMinutes(1);
        })
        .UseRemoteWorkers(
            remote => remote.BaseUrl = "https://gpu-workers/trax/execute",
            routing => routing.ForTrain<IReviewContentTrain>())
        .Schedule<ISyncTrain>("sync", new SyncInput(), Every.Minutes(5))));

IReviewContentTrain is sent to the remote endpoint; ISyncTrain runs on the four local workers.

See also