AddScheduler

Adds the Trax.Core scheduler subsystem. Registers ITraxScheduler, the background polling service, and all scheduler infrastructure. Provides a SchedulerConfigurationBuilder lambda for configuring global options, execution backends, and startup schedules.

Signature

// With configuration
public static TraxBuilderWithMediator AddScheduler(
    this TraxBuilderWithMediator builder,
    Func<SchedulerConfigurationBuilder, SchedulerConfigurationBuilder> configure
)
 
// Parameterless defaults
public static TraxBuilderWithMediator AddScheduler(
    this TraxBuilderWithMediator builder
)

AddScheduler is called on TraxBuilderWithMediator (the return type of AddMediator()), which enforces at compile time that effects and the mediator are configured before the scheduler.

The parameterless overload registers the scheduler with default settings, equivalent to AddScheduler(scheduler => scheduler).

Parameters

ParameterTypeRequiredDescription
configureFunc<SchedulerConfigurationBuilder, SchedulerConfigurationBuilder>NoLambda that receives the scheduler builder and returns it after configuring options, execution backends, and schedules. Omit for defaults.

Returns

TraxBuilderWithMediator — for continued fluent chaining (e.g., adding another AddScheduler() call is not typical, but the type allows further configuration).

Example

services.AddTrax(trax => trax
    .AddEffects(effects => effects
        .UsePostgres(connectionString)
    )
    .AddMediator(typeof(Program).Assembly)
    .AddScheduler(scheduler => scheduler
        .ManifestManagerPollingInterval(TimeSpan.FromSeconds(5))
        .JobDispatcherPollingInterval(TimeSpan.FromSeconds(5))
        .MaxActiveJobs(50)
        .DefaultMaxRetries(5)
        .DefaultRetryDelay(TimeSpan.FromMinutes(2))
        .RetryBackoffMultiplier(2.0)
        .MaxRetryDelay(TimeSpan.FromHours(1))
        .DefaultJobTimeout(TimeSpan.FromMinutes(20))
        .DefaultMisfirePolicy(MisfirePolicy.FireOnceNow)
        .DefaultMisfireThreshold(TimeSpan.FromSeconds(60))
        .RecoverStuckJobsOnStartup()
        .DependentPriorityBoost(16)
        .AddMetadataCleanup()
        .Schedule<MyTrain>(
            "my-job",
            new MyInput(),
            Every.Minutes(5),
            options => options
                .Priority(10)
                .Group("my-group"))
    )
);

SchedulerConfigurationBuilder Options

These methods are available on the SchedulerConfigurationBuilder passed to the configure lambda:

Execution Backend

MethodDescription
ConfigureLocalWorkersCustomizes the built-in PostgreSQL local workers (enabled by default with Postgres)
UseRemoteWorkersRoutes specific trains to a remote HTTP endpoint for execution
UseSqsWorkersRoutes specific trains to an Amazon SQS queue for execution (Trax.Scheduler.Sqs)
UseRemoteRunOffloads synchronous run execution to a remote endpoint (blocks until complete)
OverrideSubmitter(Action<IServiceCollection>)Registers a custom job submitter implementation

Global Options

MethodParameterDefaultDescription
PollingInterval(TimeSpan)interval5 secondsShorthand — sets both ManifestManagerPollingInterval and JobDispatcherPollingInterval to the same value
ManifestManagerPollingInterval(TimeSpan)interval5 secondsHow often the ManifestManager evaluates manifests and writes to the work queue
JobDispatcherPollingInterval(TimeSpan)interval2 secondsHow often the JobDispatcher reads from the work queue and dispatches to the job submitter
MaxConcurrentDispatch(int)maxConcurrent1Max entries dispatched concurrently per polling cycle. Increase when using UseRemoteWorkers to avoid sequential HTTP blocking. See Parallel Dispatch
MaxDispatchAttempts(int)maxAttempts5Max dispatch attempts before permanently failing a work queue entry. When dispatch fails, the entry is requeued for the next cycle. Set to 0 to disable requeuing (fail immediately). See Failure Handling
MaxActiveJobs(int?)maxJobs10Max concurrent active jobs (Pending + InProgress) globally. null = unlimited. Per-group limits can also be set from the dashboard on each ManifestGroup
MaxQueuedJobsPerCycle(int?)limit100Max queued work queue entries loaded per JobDispatcher cycle. Prevents unbounded memory usage when the queue is large. null = unlimited. Provides headroom beyond MaxActiveJobs for per-group limit skipping
ExcludeFromMaxActiveJobs<TTrain>()Excludes a train type from the MaxActiveJobs count
DefaultMaxRetries(int)maxRetries3Retry attempts before dead-lettering
DefaultRetryDelay(TimeSpan)delay5 minutesBase delay between retries
RetryBackoffMultiplier(double)multiplier2.0Exponential backoff multiplier. Set to 1.0 for constant delay
MaxRetryDelay(TimeSpan)maxDelay1 hourCaps retry delay to prevent unbounded growth
DefaultJobTimeout(TimeSpan)timeout20 minutesTimeout after which a running job is considered stuck
DefaultMisfirePolicy(MisfirePolicy)policyFireOnceNowDefault misfire policy for manifests that don't specify one
DefaultMisfireThreshold(TimeSpan)threshold60 secondsGrace period before misfire policies take effect. If a manifest is overdue by less than this, it fires normally
RecoverStuckJobsOnStartup(bool)recovertrueWhether to auto-recover stuck jobs on startup
StalePendingTimeout(TimeSpan)timeout20 minutesTimeout after which a Pending job that was never picked up is automatically failed
PruneOrphanedManifests(bool)prunetrueWhether to delete manifests from the database that are no longer defined in the startup configuration. Disable if you create manifests dynamically at runtime via ITraxScheduler
DependentPriorityBoost(int)boost16Priority boost added to dependent train work queue entries at dispatch time. Range: 0-31. Ensures dependent trains are dispatched before non-dependent ones by default

Startup Schedules

MethodDescription
ScheduleSchedules a single recurring train (seeded on startup)
ScheduleManyBatch-schedules manifests from a collection
Then / ThenManySchedules dependent trains
AddMetadataCleanupEnables automatic metadata purging

Remarks

  • AddScheduler requires AddEffects() and AddMediator() to be called first. This is enforced at compile time -- AddScheduler is only available on TraxBuilderWithMediator, which is the return type of AddMediator().
  • AddScheduler requires a data provider (UsePostgres() or UseInMemory()). If no data provider is configured, AddScheduler throws InvalidOperationException at build time with a helpful error message showing the required configuration.
  • Internal scheduler trains (ManifestManager, InMemoryManifestManager, JobDispatcher, JobRunner, MetadataCleanup) are automatically excluded from MaxActiveJobs.
  • With UseInMemory(), JobDispatcherPollingService and MetadataCleanupPollingService are not registered. The ManifestManagerPollingService runs an InMemoryManifestManagerTrain that dispatches jobs inline via InMemoryJobSubmitter.
  • Manifests declared via Schedule/ScheduleMany are not created immediately — they are seeded on application startup by the SchedulerStartupService.
  • Manifests declared via Schedule/ThenInclude/Include get a ManifestGroup based on their groupId parameter (defaults to externalId). Per-group dispatch controls (MaxActiveJobs, Priority, IsEnabled) are configured from the dashboard.
  • At build time, the scheduler validates that ManifestGroup dependencies form a DAG (no circular dependencies). If a cycle is detected, AddScheduler throws InvalidOperationException with the groups involved. See Dependent Trains — Cycle Detection.