Table of Contents

Interface IQuartzBuilder

Namespace
Quartz
Assembly
Quartz.dll

Configures a scheduler and the services it is built from.

public interface IQuartzBuilder
Extension Methods

Remarks

Every member configures typed options or registers a service — nothing writes configuration strings. The option names are the same words as the configuration keys, so Quartz:ThreadPool:MaxConcurrency and MaxConcurrency are the same setting said two ways, and code-first and file-based configuration describe one vocabulary rather than two.

Members return the builder so configuration can be chained.

Properties

SchedulerName

The name this scheduler was registered under, or an empty string for the default scheduler.

string SchedulerName { get; }

Property Value

string

Remarks

This is also the service key its components are registered under and the name of its options, so a named scheduler's registrations and configuration always agree.

Services

The services this scheduler is built from. Register your own implementations here to replace the defaults — anything registered wins over Quartz's own registration.

IServiceCollection Services { get; }

Property Value

IServiceCollection

Methods

AddJobListener<T>(params IReadOnlyCollection<IMatcher<JobKey>>)

IQuartzBuilder AddJobListener<T>(params IReadOnlyCollection<IMatcher<JobKey>> matchers) where T : class, IJobListener

Parameters

matchers IReadOnlyCollection<IMatcher<JobKey>>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddJobListener<T>(Func<IServiceProvider, T>, params IReadOnlyCollection<IMatcher<JobKey>>)

IQuartzBuilder AddJobListener<T>(Func<IServiceProvider, T> factory, params IReadOnlyCollection<IMatcher<JobKey>> matchers) where T : class, IJobListener

Parameters

factory Func<IServiceProvider, T>
matchers IReadOnlyCollection<IMatcher<JobKey>>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddJobListener<T>(T, params IReadOnlyCollection<IMatcher<JobKey>>)

IQuartzBuilder AddJobListener<T>(T listener, params IReadOnlyCollection<IMatcher<JobKey>> matchers) where T : class, IJobListener

Parameters

listener T
matchers IReadOnlyCollection<IMatcher<JobKey>>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddJobMiddleware<T>()

Adds a middleware the container builds, which wraps every job this scheduler executes.

IQuartzBuilder AddJobMiddleware<T>() where T : class, IJobExecutionMiddleware

Returns

IQuartzBuilder

Type Parameters

T

The middleware's type.

Remarks

Middleware is where a cross-cutting concern lives — a log scope, a tenant context, a timeout, a translation of what a library throws. A listener cannot do any of those: it is notified before and after the job rather than around it, so it can neither wrap the call, decline to make it, nor see what it threw. See IJobExecutionMiddleware for what a middleware may and may not decide.

Middleware runs in registration order, outermost first, so the first registered is the first to see a firing and the last to see its result. Each call adds a stage: registering the same type twice puts it in the chain twice, the same way registering the same job twice schedules it twice.

One instance is built per scheduler and shared by every firing, so a middleware must keep no per-firing state in a field. It is registered for this scheduler alone, like its listeners and its job store, so a named scheduler's middleware wraps only its own executions.

That instance is built from the container's root, when the scheduler's resources are, so its constructor dependencies must be singletons. A scoped one throws Cannot resolve scoped service … from root provider where scope validation is on — the Host's default in Development — and becomes a captive dependency living as long as the scheduler where it is not. Take IServiceScopeFactory and open a scope inside Invoke instead, or read the firing's own scope through IJobExecutionContextAccessor.

A middleware registered through ConfigureAllQuartzSchedulers always composes inside one registered here, whichever call was written first: a scheduler's own callback runs before what every scheduler was told, so a library's wrapper sits within the application's.

AddJobMiddleware<T>(Func<IServiceProvider, T>)

IQuartzBuilder AddJobMiddleware<T>(Func<IServiceProvider, T> factory) where T : class, IJobExecutionMiddleware

Parameters

factory Func<IServiceProvider, T>

Builds the middleware from this scheduler's view of the container.

Returns

IQuartzBuilder

Type Parameters

T

The middleware's type.

Remarks

Middleware is where a cross-cutting concern lives — a log scope, a tenant context, a timeout, a translation of what a library throws. A listener cannot do any of those: it is notified before and after the job rather than around it, so it can neither wrap the call, decline to make it, nor see what it threw. See IJobExecutionMiddleware for what a middleware may and may not decide.

Middleware runs in registration order, outermost first, so the first registered is the first to see a firing and the last to see its result. Each call adds a stage: registering the same type twice puts it in the chain twice, the same way registering the same job twice schedules it twice.

One instance is built per scheduler and shared by every firing, so a middleware must keep no per-firing state in a field. It is registered for this scheduler alone, like its listeners and its job store, so a named scheduler's middleware wraps only its own executions.

That instance is built from the container's root, when the scheduler's resources are, so its constructor dependencies must be singletons. A scoped one throws Cannot resolve scoped service … from root provider where scope validation is on — the Host's default in Development — and becomes a captive dependency living as long as the scheduler where it is not. Take IServiceScopeFactory and open a scope inside Invoke instead, or read the firing's own scope through IJobExecutionContextAccessor.

A middleware registered through ConfigureAllQuartzSchedulers always composes inside one registered here, whichever call was written first: a scheduler's own callback runs before what every scheduler was told, so a library's wrapper sits within the application's.

AddJobMiddleware<T>(T)

IQuartzBuilder AddJobMiddleware<T>(T middleware) where T : class, IJobExecutionMiddleware

Parameters

middleware T

The middleware, already built.

Returns

IQuartzBuilder

Type Parameters

T

The middleware's type.

Remarks

Middleware is where a cross-cutting concern lives — a log scope, a tenant context, a timeout, a translation of what a library throws. A listener cannot do any of those: it is notified before and after the job rather than around it, so it can neither wrap the call, decline to make it, nor see what it threw. See IJobExecutionMiddleware for what a middleware may and may not decide.

Middleware runs in registration order, outermost first, so the first registered is the first to see a firing and the last to see its result. Each call adds a stage: registering the same type twice puts it in the chain twice, the same way registering the same job twice schedules it twice.

One instance is built per scheduler and shared by every firing, so a middleware must keep no per-firing state in a field. It is registered for this scheduler alone, like its listeners and its job store, so a named scheduler's middleware wraps only its own executions.

That instance is built from the container's root, when the scheduler's resources are, so its constructor dependencies must be singletons. A scoped one throws Cannot resolve scoped service … from root provider where scope validation is on — the Host's default in Development — and becomes a captive dependency living as long as the scheduler where it is not. Take IServiceScopeFactory and open a scope inside Invoke instead, or read the firing's own scope through IJobExecutionContextAccessor.

A middleware registered through ConfigureAllQuartzSchedulers always composes inside one registered here, whichever call was written first: a scheduler's own callback runs before what every scheduler was told, so a library's wrapper sits within the application's.

AddPlugin<T>(Func<IServiceProvider, T>, string?)

Adds a plugin the caller builds and configures.

IQuartzBuilder AddPlugin<T>(Func<IServiceProvider, T> factory, string? name = null) where T : class, ISchedulerPlugin

Parameters

factory Func<IServiceProvider, T>

Builds the plugin.

name string

The name the scheduler knows the plugin by.

Returns

IQuartzBuilder

Type Parameters

T

The plugin's type.

Remarks

The three shapes match the listener trio: the container builds the plugin, the caller builds it, or the caller configures options the plugin is given. name is how the scheduler refers to the plugin, and some plugins derive persisted job and trigger keys from it — so it is part of the deployment's identity rather than a label, and it is also the name a quartz.plugin.<name>.* key configures the same plugin under. Left unset, the plugin's type name is used. Plugins shipped with Quartz use their conventional short name (xml, json) for that reason.

AddPlugin<T>(string?)

Adds a plugin, which extends the scheduler's behaviour for its whole lifetime.

IQuartzBuilder AddPlugin<T>(string? name = null) where T : class, ISchedulerPlugin

Parameters

name string

The name the scheduler knows the plugin by.

Returns

IQuartzBuilder

Type Parameters

T

The plugin's type.

Remarks

The three shapes match the listener trio: the container builds the plugin, the caller builds it, or the caller configures options the plugin is given. name is how the scheduler refers to the plugin, and some plugins derive persisted job and trigger keys from it — so it is part of the deployment's identity rather than a label, and it is also the name a quartz.plugin.<name>.* key configures the same plugin under. Left unset, the plugin's type name is used. Plugins shipped with Quartz use their conventional short name (xml, json) for that reason.

AddPlugin<T, TOptions>(Action<TOptions>?, string?)

Adds a plugin with configuration of its own.

IQuartzBuilder AddPlugin<T, TOptions>(Action<TOptions>? configure = null, string? name = null) where T : class, ISchedulerPlugin where TOptions : class

Parameters

configure Action<TOptions>

Configures the plugin's options.

name string

The name the scheduler knows the plugin by.

Returns

IQuartzBuilder

Type Parameters

T

The plugin's type.

TOptions

The plugin's options type, which it takes as a dependency. It is resolved through IOptions<TOptions>, so it must keep its public parameterless constructor when the application is trimmed.

Remarks

The three shapes match the listener trio: the container builds the plugin, the caller builds it, or the caller configures options the plugin is given. name is how the scheduler refers to the plugin, and some plugins derive persisted job and trigger keys from it — so it is part of the deployment's identity rather than a label, and it is also the name a quartz.plugin.<name>.* key configures the same plugin under. Left unset, the plugin's type name is used. Plugins shipped with Quartz use their conventional short name (xml, json) for that reason.

AddSchedulerListener<T>()

Adds a scheduler listener the container builds.

IQuartzBuilder AddSchedulerListener<T>() where T : class, ISchedulerListener

Returns

IQuartzBuilder

Type Parameters

T

The listener's type.

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddSchedulerListener<T>(Func<IServiceProvider, T>)

IQuartzBuilder AddSchedulerListener<T>(Func<IServiceProvider, T> factory) where T : class, ISchedulerListener

Parameters

factory Func<IServiceProvider, T>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddSchedulerListener<T>(T)

IQuartzBuilder AddSchedulerListener<T>(T listener) where T : class, ISchedulerListener

Parameters

listener T

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddTriggerListener<T>(params IReadOnlyCollection<IMatcher<TriggerKey>>)

IQuartzBuilder AddTriggerListener<T>(params IReadOnlyCollection<IMatcher<TriggerKey>> matchers) where T : class, ITriggerListener

Parameters

matchers IReadOnlyCollection<IMatcher<TriggerKey>>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddTriggerListener<T>(Func<IServiceProvider, T>, params IReadOnlyCollection<IMatcher<TriggerKey>>)

IQuartzBuilder AddTriggerListener<T>(Func<IServiceProvider, T> factory, params IReadOnlyCollection<IMatcher<TriggerKey>> matchers) where T : class, ITriggerListener

Parameters

factory Func<IServiceProvider, T>
matchers IReadOnlyCollection<IMatcher<TriggerKey>>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

AddTriggerListener<T>(T, params IReadOnlyCollection<IMatcher<TriggerKey>>)

IQuartzBuilder AddTriggerListener<T>(T listener, params IReadOnlyCollection<IMatcher<TriggerKey>> matchers) where T : class, ITriggerListener

Parameters

listener T
matchers IReadOnlyCollection<IMatcher<TriggerKey>>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

The listener's shape is checked here, while the application is still writing its configuration. Every member of ISchedulerListener, IJobListener and ITriggerListener has a default implementation, so a public method that carries a notification's name but not its signature still compiles — it just stops implementing anything, and the default runs in its place with nothing to say the method is dead. Such a listener is refused with a SchedulerConfigException naming the member and the signature it should have.

What is examined is T: for an instance overload that is the type the call was written with rather than the instance's own, so a listener handed over as its base type is checked as that base, and a factory overload declared as the interface has nothing to examine at all. Neither escapes — the listener's runtime type is checked again when it is attached to a scheduler, which is only a later moment to hear about it.

ConfigureOptions<TOptions>(Action<TOptions>?)

Configures an options type belonging to this scheduler, so a component of your own can have settings that follow the scheduler it was registered for.

IQuartzBuilder ConfigureOptions<TOptions>(Action<TOptions>? configure = null) where TOptions : class

Parameters

configure Action<TOptions>

Configures the options.

Returns

IQuartzBuilder

Type Parameters

TOptions

The options type. It is resolved through IOptions<TOptions>, so it must keep its public parameterless constructor when the application is trimmed.

Remarks

A component the container builds asks for IOptions<TOptions>, which by itself resolves the unnamed instance — so under AddQuartz("reporting", …) it would be handed the default scheduler's settings, or defaults. This says the type is a scheduler's own: the callback is registered under this scheduler's options name, and the type is declared so that resolving it through the scheduler hands back the named instance.

Registered whether or not a callback is given: where the options come from is not something adding one should change. Calling it repeatedly is harmless — each callback is applied in turn, and the declaration is deduplicated.

This is the mechanism AddPlugin<T, TOptions>(Action<TOptions>?, string?) is built from, available to every component: a thread pool, a job store, a lock handler, a listener, a job factory.

ConfigureScheduler(Action<QuartzSchedulerOptions>)

Configures the scheduler itself.

IQuartzBuilder ConfigureScheduler(Action<QuartzSchedulerOptions> configure)

Parameters

configure Action<QuartzSchedulerOptions>

Returns

IQuartzBuilder

UseDefaultThreadPool(Action<ThreadPoolOptions>?)

Uses the default thread pool.

IQuartzBuilder UseDefaultThreadPool(Action<ThreadPoolOptions>? configure = null)

Parameters

configure Action<ThreadPoolOptions>

Returns

IQuartzBuilder

UseDefaultThreadPool(int)

Uses the default thread pool, limited to the given number of concurrently executing jobs.

IQuartzBuilder UseDefaultThreadPool(int maxConcurrency)

Parameters

maxConcurrency int

Returns

IQuartzBuilder

UseExecutionLimits(Action<ExecutionLimitsBuilder>)

Configures execution group limits, so resource-hungry jobs cannot saturate every thread. Each limit is counted on this node or across the cluster, as its ExecutionLimitScope says.

IQuartzBuilder UseExecutionLimits(Action<ExecutionLimitsBuilder> configure)

Parameters

configure Action<ExecutionLimitsBuilder>

Returns

IQuartzBuilder

UseInMemoryStore(Action<InMemoryJobStoreOptions>?)

Uses the in-memory job store, which does not survive process restarts.

IQuartzBuilder UseInMemoryStore(Action<InMemoryJobStoreOptions>? configure = null)

Parameters

configure Action<InMemoryJobStoreOptions>

Returns

IQuartzBuilder

Remarks

Takes an options object rather than a sub-builder, unlike UsePersistentStore(Action<IPersistentStoreBuilder>): an in-memory store is one component with a couple of settings, whereas a database-backed store is a composite that also has a data source, a driver delegate, a serializer and a lock handler to choose. The shape says which kind of thing is being configured.

UseInstanceIdGenerator(IInstanceIdGenerator)

Uses an instance id generator the caller has already built.

IQuartzBuilder UseInstanceIdGenerator(IInstanceIdGenerator generator)

Parameters

generator IInstanceIdGenerator

The generator.

Returns

IQuartzBuilder

Remarks

Choosing a generator says the id is to be generated, so GenerateInstanceId is set — the counterpart of writing quartz.scheduler.instanceId = AUTO beside the generator's type name. A generator that was chosen and then never called would be the configuration equivalent of silence.

Only a clustered scheduler generates one: a scheduler that shares its database with nobody has nothing to tell itself apart from, so the generator is not called and the id stays NON_CLUSTERED.

UseInstanceIdGenerator<T>()

Uses a specific instance id generator, which names this node within a cluster.

IQuartzBuilder UseInstanceIdGenerator<T>() where T : class, IInstanceIdGenerator

Returns

IQuartzBuilder

Type Parameters

T

The generator's type.

Remarks

Choosing a generator says the id is to be generated, so GenerateInstanceId is set — the counterpart of writing quartz.scheduler.instanceId = AUTO beside the generator's type name. A generator that was chosen and then never called would be the configuration equivalent of silence.

Only a clustered scheduler generates one: a scheduler that shares its database with nobody has nothing to tell itself apart from, so the generator is not called and the id stays NON_CLUSTERED.

UseInstanceIdGenerator<T, TOptions>(Action<TOptions>?)

Uses an instance id generator with options of its own.

IQuartzBuilder UseInstanceIdGenerator<T, TOptions>(Action<TOptions>? configure = null) where T : class, IInstanceIdGenerator where TOptions : class

Parameters

configure Action<TOptions>

Configures the generator's options.

Returns

IQuartzBuilder

Type Parameters

T

The generator's type.

TOptions

The generator's options type. It is resolved through IOptions<TOptions>, so it must keep its public parameterless constructor when the application is trimmed.

Remarks

Choosing a generator says the id is to be generated, so GenerateInstanceId is set — the counterpart of writing quartz.scheduler.instanceId = AUTO beside the generator's type name. A generator that was chosen and then never called would be the configuration equivalent of silence.

Only a clustered scheduler generates one: a scheduler that shares its database with nobody has nothing to tell itself apart from, so the generator is not called and the id stays NON_CLUSTERED.

UseJobFactory(IJobFactory)

Uses a job factory the caller has already built.

IQuartzBuilder UseJobFactory(IJobFactory jobFactory)

Parameters

jobFactory IJobFactory

Returns

IQuartzBuilder

UseJobFactory<T>()

Uses a specific job factory, which decides how job instances are produced.

IQuartzBuilder UseJobFactory<T>() where T : class, IJobFactory

Returns

IQuartzBuilder

Type Parameters

T

UseJobStore(IJobStore)

Uses a job store the caller has already built.

IQuartzBuilder UseJobStore(IJobStore jobStore)

Parameters

jobStore IJobStore

Returns

IQuartzBuilder

Remarks

For a store that needs constructing with something the container cannot supply. A store the container can build is better selected with UseJobStore<T>(), UsePersistentStore<T>(Action<IPersistentStoreBuilder>) or UseInMemoryStore(Action<InMemoryJobStoreOptions>?), which let it have dependencies of its own.

UseJobStore(Func<IServiceProvider, IJobStore>)

Uses a job store built by a factory of your own.

IQuartzBuilder UseJobStore(Func<IServiceProvider, IJobStore> factory)

Parameters

factory Func<IServiceProvider, IJobStore>

Builds the job store.

Returns

IQuartzBuilder

Remarks

For a store that needs something the container cannot construct on its own — a decorator around another store, or one whose constructor takes values rather than services. The factory is given this scheduler's view of the container and runs once, when the scheduler is built.

UseJobStore<T>()

Uses a job store of your own, built by the container.

IQuartzBuilder UseJobStore<T>() where T : class, IJobStore

Returns

IQuartzBuilder

Type Parameters

T

The job store's type.

Remarks

The seam for a store that keeps scheduling data somewhere Quartz has never heard of. It is constructed with this scheduler's own collaborators — its signaler, its serializer, its type loader — so a store written against them behaves the same under a named scheduler as under the default one. UseInMemoryStore(Action<InMemoryJobStoreOptions>?) and UsePersistentStore<T>(Action<IPersistentStoreBuilder>) remain the way to select the stores Quartz ships, since they configure them as well as choose them.

UseJobStore<T, TOptions>(Action<TOptions>?)

Uses a job store of your own, with options of its own.

IQuartzBuilder UseJobStore<T, TOptions>(Action<TOptions>? configure = null) where T : class, IJobStore where TOptions : class

Parameters

configure Action<TOptions>

Configures the store's options.

Returns

IQuartzBuilder

Type Parameters

T

The job store's type.

TOptions

The store's options type. It is resolved through IOptions<TOptions>, so it must keep its public parameterless constructor when the application is trimmed.

Remarks

Sugar over UseJobStore<T>() and ConfigureOptions<TOptions>(Action<TOptions>?): the options are declared as this scheduler's, so a store that takes IOptions<TOptions> is handed what was configured for the scheduler it belongs to rather than the unnamed instance.

UsePersistentStore(Action<IPersistentStoreBuilder>)

Uses a database-backed job store, so jobs and triggers survive restarts and can be clustered.

IQuartzBuilder UsePersistentStore(Action<IPersistentStoreBuilder> configure)

Parameters

configure Action<IPersistentStoreBuilder>

Returns

IQuartzBuilder

Remarks

Takes a sub-builder rather than an options object, unlike UseInMemoryStore(Action<InMemoryJobStoreOptions>?): a database-backed store is a composite that also has a data source, a driver delegate, a serializer and a lock handler to choose.

Both stores Quartz ships are reached from here. The default begins the transaction each operation runs in and commits or rolls it back; UseAmbientTransactions() inside the callback selects the one that runs inside a transaction somebody else owns. UsePersistentStore<T>(Action<IPersistentStoreBuilder>) is for a store neither of those describes.

UsePersistentStore<T>(Action<IPersistentStoreBuilder>)

Uses a specific database-backed job store implementation.

IQuartzBuilder UsePersistentStore<T>(Action<IPersistentStoreBuilder> configure) where T : class, IJobStore

Parameters

configure Action<IPersistentStoreBuilder>

Returns

IQuartzBuilder

Type Parameters

T

Remarks

For a persistent store of your own. The two Quartz ships are both selected by UsePersistentStore(Action<IPersistentStoreBuilder>), which is why naming one of them here and also calling UseAmbientTransactions() is reported as the contradiction it is rather than silently resolved.

UseThreadPool(IThreadPool)

Uses a thread pool the caller has already built.

IQuartzBuilder UseThreadPool(IThreadPool threadPool)

Parameters

threadPool IThreadPool

Returns

IQuartzBuilder

Remarks

For a pool that needs constructing with something the container cannot supply. A pool the container can build is better selected with UseThreadPool<T>(), which lets it have dependencies of its own.

UseThreadPool<T>()

Uses a specific thread pool implementation.

IQuartzBuilder UseThreadPool<T>() where T : class, IThreadPool

Returns

IQuartzBuilder

Type Parameters

T

Remarks

A pool of your own has options of its own: declare them with ConfigureOptions<TOptions>(Action<TOptions>?) and take IOptions<TOptions> through its constructor. ThreadPoolOptions belongs to the built-in pools, so it is configured on UseDefaultThreadPool(Action<ThreadPoolOptions>?) where it is read.

UseTimeProvider(TimeProvider)

Uses a specific time provider. Useful for testing time-dependent scheduling.

IQuartzBuilder UseTimeProvider(TimeProvider timeProvider)

Parameters

timeProvider TimeProvider

Returns

IQuartzBuilder

Remarks

The clock belongs to this scheduler. Handing one to a named scheduler leaves the others on whatever they were using, which is what lets one scheduler in a container be driven by a fake clock while the rest keep real time.

A scheduler that was not given one asks the container, and falls back to System. In full, most specific first:

  1. the provider this scheduler was given here;
  2. a TimeProvider registered in the container;
  3. a quartz.timeProvider.type key, which loses to both — code beats strings here as it does everywhere else;
  4. System.

UseTypeLoader<T>()

Uses a specific type loader, which decides how type names are resolved.

IQuartzBuilder UseTypeLoader<T>() where T : class, ITypeLoader

Returns

IQuartzBuilder

Type Parameters

T