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
| Parameter | Type | Required | Description |
|---|---|---|---|
configure | Func<SchedulerConfigurationBuilder, SchedulerConfigurationBuilder> | No | Lambda 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
| Method | Description |
|---|---|
| ConfigureLocalWorkers | Customizes the built-in PostgreSQL local workers (enabled by default with Postgres) |
| UseRemoteWorkers | Routes specific trains to a remote HTTP endpoint for execution |
| UseSqsWorkers | Routes specific trains to an Amazon SQS queue for execution (Trax.Scheduler.Sqs) |
| UseRemoteRun | Offloads synchronous run execution to a remote endpoint (blocks until complete) |
OverrideSubmitter(Action<IServiceCollection>) | Registers a custom job submitter implementation |
Global Options
| Method | Parameter | Default | Description |
|---|---|---|---|
PollingInterval(TimeSpan) | interval | 5 seconds | Shorthand — sets both ManifestManagerPollingInterval and JobDispatcherPollingInterval to the same value |
ManifestManagerPollingInterval(TimeSpan) | interval | 5 seconds | How often the ManifestManager evaluates manifests and writes to the work queue |
JobDispatcherPollingInterval(TimeSpan) | interval | 2 seconds | How often the JobDispatcher reads from the work queue and dispatches to the job submitter |
MaxConcurrentDispatch(int) | maxConcurrent | 1 | Max entries dispatched concurrently per polling cycle. Increase when using UseRemoteWorkers to avoid sequential HTTP blocking. See Parallel Dispatch |
MaxDispatchAttempts(int) | maxAttempts | 5 | Max 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?) | maxJobs | 10 | Max concurrent active jobs (Pending + InProgress) globally. null = unlimited. Per-group limits can also be set from the dashboard on each ManifestGroup |
MaxQueuedJobsPerCycle(int?) | limit | 100 | Max 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) | maxRetries | 3 | Retry attempts before dead-lettering |
DefaultRetryDelay(TimeSpan) | delay | 5 minutes | Base delay between retries |
RetryBackoffMultiplier(double) | multiplier | 2.0 | Exponential backoff multiplier. Set to 1.0 for constant delay |
MaxRetryDelay(TimeSpan) | maxDelay | 1 hour | Caps retry delay to prevent unbounded growth |
DefaultJobTimeout(TimeSpan) | timeout | 20 minutes | Timeout after which a running job is considered stuck |
DefaultMisfirePolicy(MisfirePolicy) | policy | FireOnceNow | Default misfire policy for manifests that don't specify one |
DefaultMisfireThreshold(TimeSpan) | threshold | 60 seconds | Grace period before misfire policies take effect. If a manifest is overdue by less than this, it fires normally |
RecoverStuckJobsOnStartup(bool) | recover | true | Whether to auto-recover stuck jobs on startup |
StalePendingTimeout(TimeSpan) | timeout | 20 minutes | Timeout after which a Pending job that was never picked up is automatically failed |
PruneOrphanedManifests(bool) | prune | true | Whether 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) | boost | 16 | Priority 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
| Method | Description |
|---|---|
| Schedule | Schedules a single recurring train (seeded on startup) |
| ScheduleMany | Batch-schedules manifests from a collection |
| Then / ThenMany | Schedules dependent trains |
| AddMetadataCleanup | Enables automatic metadata purging |
Remarks
AddSchedulerrequiresAddEffects()andAddMediator()to be called first. This is enforced at compile time --AddScheduleris only available onTraxBuilderWithMediator, which is the return type ofAddMediator().AddSchedulerrequires a data provider (UsePostgres()orUseInMemory()). If no data provider is configured,AddSchedulerthrowsInvalidOperationExceptionat build time with a helpful error message showing the required configuration.- Internal scheduler trains (
ManifestManager,InMemoryManifestManager,JobDispatcher,JobRunner,MetadataCleanup) are automatically excluded fromMaxActiveJobs. - With
UseInMemory(),JobDispatcherPollingServiceandMetadataCleanupPollingServiceare not registered. TheManifestManagerPollingServiceruns anInMemoryManifestManagerTrainthat dispatches jobs inline viaInMemoryJobSubmitter. - Manifests declared via
Schedule/ScheduleManyare not created immediately — they are seeded on application startup by theSchedulerStartupService. - Manifests declared via
Schedule/ThenInclude/Includeget a ManifestGroup based on theirgroupIdparameter (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,
AddSchedulerthrowsInvalidOperationExceptionwith the groups involved. See Dependent Trains — Cycle Detection.