Interface IPersistentStoreBuilder
- Namespace
- Quartz
- Assembly
- Quartz.dll
Configures a database-backed job store.
public interface IPersistentStoreBuilder
- Extension Methods
Remarks
A scheduler has one job store and therefore one database, so there is no data source name to
invent: UseSqlServer(connectionString) says everything. Schedulers that need different
databases are registered under different names, and their components are keyed accordingly.
Serialization and clustering live here rather than on the scheduler because they are properties of how the schedule is stored, and mean nothing for an in-memory store.
Properties
SchedulerName
The name of the scheduler this store belongs to, or an empty string for the default scheduler.
string SchedulerName { get; }
Property Value
Services
The services this scheduler is built from.
IServiceCollection Services { get; }
Property Value
Methods
ConfigureStore(Action<AdoJobStoreOptions>)
Configures the job store itself.
IPersistentStoreBuilder ConfigureStore(Action<AdoJobStoreOptions> configure)
Parameters
configureAction<AdoJobStoreOptions>
Returns
Remarks
These are the same settings, under the same names, as the Quartz:JobStore configuration
section. The name says which of the several things in scope here is being configured — the store,
rather than the scheduler around it or the data source under it.
ProvisionSchema()
Creates whatever this store's schema is missing when the scheduler starts, instead of requiring it to be there already.
IPersistentStoreBuilder ProvisionSchema()
Returns
Remarks
Shorthand for ConfigureStore(options => options.SchemaProvisioning =
SchemaProvisioning.CreateIfMissing), spelled as the decision it is.
Only ever creates. Nothing is altered and nothing is dropped, so this cannot turn a mis-typed
TablePrefix into data loss — but it will happily create a
second, empty schema under the mis-typed one, so the prefix is still worth reading twice.
Neither is it an upgrade: a schema that has every table but is missing a column a later
release added is left as it is. database/migrations/ is what moves a schema forward.
The account the store connects with needs permission to create tables and indexes, which a production database is usually right not to grant, and which is why this is opt-in rather than the default. Several schedulers may call it against one database at once: whichever loses the race finds the schema the winner created.
UseAmbientTransactions()
Runs the schedule inside a transaction somebody else owns — an application server or another framework that manages transactions — instead of one the store begins and commits itself.
IPersistentStoreBuilder UseAmbientTransactions()
Returns
Remarks
This is how the second of the two shipped ADO.NET stores is chosen. Left uncalled,
UsePersistentStore builds the local-transaction store, which begins the transaction each
operation runs in and commits or rolls it back; the ambient store does neither, because the
connections it creates enlist in the Transaction already in
progress and its owner is what decides whether the scheduler's work is kept. It is
quartz.jobStore.type = Quartz.Impl.AdoJobStore.ExternalTransactionJobStore, Quartz
spelled in code — 3.x's JobStoreCMT.
Not the same thing as AcceptEnlistedTransactions, which leaves the local store in charge and only lets an operation join a transaction the application enlisted for that flow, managing its own whenever nothing is enlisted. This hands the whole store over.
The store requires database locking — an in-process lock would be released before its owner commits — and turns it on for itself unless UseLockHandler<T>() supplied one. OpenConnection, which nothing else reads, says whether the store opens the connections it creates or leaves that to the transaction's owner.
UseClustering(Action<ClusteringOptions>?)
Takes part in a cluster with every other scheduler sharing this database.
IPersistentStoreBuilder UseClustering(Action<ClusteringOptions>? configure = null)
Parameters
configureAction<ClusteringOptions>
Returns
Remarks
Clustering requires database locking, which this enables as well — the two have never been separable in practice.
Everything about clustering is said here, on ClusteringOptions. The job store has no clustering settings of its own to disagree with these, and reports whether it is clustered rather than offering a second place to say so.
UseConnectionProvider(Func<IServiceProvider, IDbProvider>)
Uses a connection provider the caller builds, for cases where it needs configuring first.
IPersistentStoreBuilder UseConnectionProvider(Func<IServiceProvider, IDbProvider> factory)
Parameters
factoryFunc<IServiceProvider, IDbProvider>
Returns
Remarks
This is the code spelling of 3.x's
quartz.dataSource.<name>.connectionProvider.type, and of
DBConnectionManager.AddConnectionProvider before it. Reach for it when connections have to
come from somewhere Quartz cannot describe — a pooled or credential-rotating factory, or a driver
whose connections need setting up after they are created.
Unlike the rest of this builder, this replaces rather than defers: it wins over the
provider UseSqlServer and its siblings register, in either order, so there is no call
sequence to get right. It also names this store's data source, so a store configured this way
needs no UseDataSource(Action<DataSourceOptions>) call — though one is still
useful for the driver delegate the database-specific methods select.
The provider belongs to this scheduler alone. Registering IDbProvider against
Services instead would be invisible to a named scheduler, which resolves its
provider under its own key.
UseConnectionProvider<T>()
Uses a connection provider of your own, which decides how connections and commands are made rather than leaving that to a connection string and a driver description.
IPersistentStoreBuilder UseConnectionProvider<T>() where T : class, IDbProvider
Returns
Type Parameters
T
Remarks
This is the code spelling of 3.x's
quartz.dataSource.<name>.connectionProvider.type, and of
DBConnectionManager.AddConnectionProvider before it. Reach for it when connections have to
come from somewhere Quartz cannot describe — a pooled or credential-rotating factory, or a driver
whose connections need setting up after they are created.
Unlike the rest of this builder, this replaces rather than defers: it wins over the
provider UseSqlServer and its siblings register, in either order, so there is no call
sequence to get right. It also names this store's data source, so a store configured this way
needs no UseDataSource(Action<DataSourceOptions>) call — though one is still
useful for the driver delegate the database-specific methods select.
The provider belongs to this scheduler alone. Registering IDbProvider against
Services instead would be invisible to a named scheduler, which resolves its
provider under its own key.
UseDataSource(Action<DataSourceOptions>)
Defines this store's data source: which ADO.NET driver, and how to reach the database.
IPersistentStoreBuilder UseDataSource(Action<DataSourceOptions> configure)
Parameters
configureAction<DataSourceOptions>
Returns
Remarks
Prefer the database-specific methods such as UseSqlServer, which also select the matching
driver delegate. Use this directly only for a provider Quartz does not know about.
Where the connection itself comes from is DataSourceOptions' to say: a connection
string, the name of one in IConfiguration, or
UseRegisteredDataSource for a DbDataSource the application
registered in the container.
UseDataSource(string)
Says which data source this store reads and writes through, by name.
IPersistentStoreBuilder UseDataSource(string name)
Parameters
namestring
Returns
Remarks
This refers to a data source rather than defining one:
UseDataSource(Action<DataSourceOptions>) defines it, and the two are told apart by
what they are given rather than by carrying different names. The settings it names are the
DataSourceOptions registered under this name — from a
Quartz:DataSource:<name> configuration section, say, or from another scheduler that
already configured it.
The name defaults to the scheduler's name, or quartz for the default scheduler, so it never
has to be invented or kept in step by hand. Naming one explicitly is for the cases where the name
itself matters: two stores that should read the same Quartz:DataSource:<name>
settings, or settings that live under a name the application chose.
Call this before choosing the database, since the name is fixed when the data source is configured.
UseDriverDelegate(Func<IServiceProvider, IDriverDelegate>)
Uses a driver delegate the caller builds, for cases where it needs configuring first.
IPersistentStoreBuilder UseDriverDelegate(Func<IServiceProvider, IDriverDelegate> factory)
Parameters
factoryFunc<IServiceProvider, IDriverDelegate>
Returns
Remarks
As with UseSerializer(Func<IServiceProvider, IObjectSerializer>), this registers under the scheduler's own key, which registering against Services would not.
UseDriverDelegate<T>()
Uses a specific driver delegate, which adapts Quartz's SQL to a particular database.
IPersistentStoreBuilder UseDriverDelegate<T>() where T : class, IDriverDelegate
Returns
Type Parameters
T
UseLockHandler(Func<IServiceProvider, ILockHandler>)
Uses a lock handler the caller builds, for cases where it needs configuring first.
IPersistentStoreBuilder UseLockHandler(Func<IServiceProvider, ILockHandler> factory)
Parameters
factoryFunc<IServiceProvider, ILockHandler>
Returns
Remarks
As with UseSerializer(Func<IServiceProvider, IObjectSerializer>), this registers under the scheduler's own key, which registering against Services would not.
UseLockHandler<T>()
Uses a specific lock handler, which decides how competing schedulers serialize their work.
IPersistentStoreBuilder UseLockHandler<T>() where T : class, ILockHandler
Returns
Type Parameters
T
Remarks
Left unset, the store chooses for itself once it knows which database it is talking to: database row locks when clustered, and an in-process monitor otherwise.
UseSerializer(Func<IServiceProvider, IObjectSerializer>)
Uses a serializer the caller builds, for cases where it needs configuring first.
IPersistentStoreBuilder UseSerializer(Func<IServiceProvider, IObjectSerializer> factory)
Parameters
factoryFunc<IServiceProvider, IObjectSerializer>
Returns
Remarks
The serializer belongs to this store rather than to the container, so use this rather than registering IObjectSerializer against Services: a named scheduler resolves its serializer under its own key and would never see an unkeyed registration.
UseSerializer<T>()
Uses a specific serializer for job data held in the database.
IPersistentStoreBuilder UseSerializer<T>() where T : class, IObjectSerializer
Returns
Type Parameters
T
UseTriggerPersistenceDelegate(Func<IServiceProvider, ITriggerPersistenceDelegate>)
Adds a trigger persistence delegate the caller builds, for cases where it needs configuring first.
IPersistentStoreBuilder UseTriggerPersistenceDelegate(Func<IServiceProvider, ITriggerPersistenceDelegate> factory)
Parameters
factoryFunc<IServiceProvider, ITriggerPersistenceDelegate>
Returns
Remarks
As with UseSerializer(Func<IServiceProvider, IObjectSerializer>), this registers under the scheduler's own key, which registering against Services would not.
UseTriggerPersistenceDelegate<T>()
Adds a trigger persistence delegate, which stores and rebuilds a custom trigger type's scheduling data in its own tables rather than as a serialized blob.
IPersistentStoreBuilder UseTriggerPersistenceDelegate<T>() where T : class, ITriggerPersistenceDelegate
Returns
Type Parameters
T
Remarks
The built-in delegates for the five shipped trigger types are always present; delegates added here serve additional trigger types. Call once per delegate — repeated registrations of the same type collapse to one.