Class AdoJobStoreOptions
- Namespace
- Quartz
- Assembly
- Quartz.dll
Strongly typed configuration for the ADO.NET (persistent) job store.
public sealed class AdoJobStoreOptions
- Inheritance
-
AdoJobStoreOptions
- Inherited Members
Remarks
Binds from the JobStore section of the Quartz configuration, and is the typed
replacement for the quartz.jobStore.* property keys. Scheduler identity is not repeated
here — components that need it inject QuartzSchedulerOptions as well, and neither
are the clustering settings, which live once on ClusteringOptions.
Properties
AcceptEnlistedTransactions
Whether the job store may take part in a transaction the application owns, rather than always managing an ADO.NET transaction of its own.
public bool AcceptEnlistedTransactions { get; set; }
Property Value
Remarks
When enabled, the job store uses the connection the application enlisted with EnlistTransaction(IScheduler, DbTransaction) or EnlistConnection(IScheduler, DbConnection, DbTransaction?) for operations on that asynchronous flow, so scheduling either commits with the rest of the application's work or not at all.
Taking part always means handing over a connection. Operations with nothing enlisted keep using a connection of the job store's own, and on the default store — UsePersistentStore(Action<IPersistentStoreBuilder>) without more — that connection is deliberately kept out of any ambient Transaction. The store UseAmbientTransactions() selects is the exception, since running inside a container-managed transaction is that store's contract.
AcquireTriggersWithinLock
Whether trigger acquisition happens inside the database lock.
public bool AcquireTriggersWithinLock { get; set; }
Property Value
CommandTimeout
How long a statement the job store issues may run before the provider cancels it. Left unset, each statement keeps whatever default the ADO.NET provider gives a new command — 30 seconds for most of them.
public TimeSpan? CommandTimeout { get; set; }
Property Value
Remarks
This covers every statement the store issues, including the ones the lock handler takes its row
lock with, which is where a timeout matters most: a node blocked on QRTZ_LOCKS behind a
peer that has stopped without releasing it waits for the provider's default before it can fail
and retry, and the scheduling loop is stalled for all of it.
There is deliberately no per-statement override. A timeout that varies by statement is a way of saying some of the store's work is more expendable than the rest, and none of it is: every statement runs inside a lock the rest of the cluster is waiting on.
ADO.NET's CommandTimeout counts whole seconds, so a value is rounded up to the next second — a configured 1500ms is applied as 2 seconds. Rounding up rather than down keeps a sub-second value from becoming zero, which every provider reads as "wait forever".
DataSource
The name of the data source this job store reads and writes through.
public string DataSource { get; set; }
Property Value
Remarks
Resolves the matching named DataSourceOptions.
DbRetryInterval
How long to wait before retrying after a database failure.
public TimeSpan DbRetryInterval { get; set; }
Property Value
DoubleCheckLockMisfireHandler
Whether the misfire handler double-checks the lock before doing work.
public bool DoubleCheckLockMisfireHandler { get; set; }
Property Value
IsTransient
An extra answer to "is this failure worth retrying", for a driver that reports a retryable condition Quartz does not recognise.
public Func<Exception, bool>? IsTransient { get; set; }
Property Value
Remarks
Consulted first, and only additive: returning false — which is also what
leaving this unset means — falls through to the built-in classification, so a predicate cannot
make Quartz stop retrying something it already retries. That is deliberate. The built-in list is
IsTransient, a SQLSTATE in class 40, SQL Server's transient
error numbers, SQLite's busy and locked codes and TimeoutException, over the whole
chain of inner exceptions; a driver that misreports one of those is a bug to fix in
TransientErrorDetector rather than to work around here.
The exception handed over is the store's own, so the driver's exception is usually its InnerException — GetBaseException() is the short way to the one your driver threw.
It is called on the failure path of a store operation, while a lock may be held, so it must be quick and must not throw: a predicate that throws would replace the database failure the store was about to report with one from the classification of it.
LockOnInsert
Whether a lock is taken when inserting new job or trigger rows.
public bool LockOnInsert { get; set; }
Property Value
MaxMisfiresToHandleAtATime
The maximum number of misfired triggers handled in a single pass.
public int MaxMisfiresToHandleAtATime { get; set; }
Property Value
MaxTransientRetries
The number of times a transient database failure is retried.
public int MaxTransientRetries { get; set; }
Property Value
MisfireHandlerFrequency
How often the misfire handler runs. Defaults to MisfireThreshold when unset.
public TimeSpan? MisfireHandlerFrequency { get; set; }
Property Value
MisfireThreshold
How far past its scheduled fire time a trigger may be before it is considered misfired.
public TimeSpan MisfireThreshold { get; set; }
Property Value
OpenConnection
Whether the ambient-transaction store opens the connections it creates before handing them to an operation. Defaults to false, leaving the opening to the externally managed transaction.
public bool OpenConnection { get; set; }
Property Value
Remarks
Read only by that store, which is the one
UseAmbientTransactions() selects — or
quartz.jobStore.type = Quartz.Impl.AdoJobStore.ExternalTransactionJobStore, Quartz. It
says nothing on the default local-transaction store.
RetryableActionErrorLogThreshold
How many consecutive failures of a retryable action occur before they are logged as errors.
public int RetryableActionErrorLogThreshold { get; set; }
Property Value
SchemaProvisioning
What the store does about its schema at startup: nothing, verify it, or create what is missing and then verify it.
public SchemaProvisioning SchemaProvisioning { get; set; }
Property Value
Remarks
SelectWithLockSql
Overrides the SQL statement used to acquire the row lock. Defaulted for SQL Server to its
WITH (UPDLOCK,ROWLOCK) form.
public string? SelectWithLockSql { get; set; }
Property Value
Remarks
Read only when the job store builds a database-locking handler for itself, which is what it does
when UseDbLocks is on — through clustering, enlisted transactions, or the setting
itself — and no lock handler was supplied. A handler chosen with UseLockHandler takes its
statement through its own constructor, and the store logs a warning at startup if this is set as
well, since the value would silently do nothing.
The statement must select the row in {0}LOCKS matching the @schedulerName and
@lockName parameters, taking whatever lock the database needs to serialize the callers;
{0} is the table prefix.
StoreJobDataAsStrings
When true, job data maps are persisted as name/value string pairs rather than serialized objects, which keeps stored data readable and version tolerant.
public bool StoreJobDataAsStrings { get; set; }
Property Value
Remarks
This was UseProperties, which read as a verb and collided with
QuartzSchedulerBuilder.UseProperties and AddQuartz(properties) — an unrelated thing
about flat quartz.* configuration keys. The flat key that sets it is still
quartz.jobStore.useProperties.
TablePrefix
The prefix applied to every Quartz table name. Defaults to DefaultTablePrefix.
public string TablePrefix { get; set; }
Property Value
TransactionIsolationLevel
The isolation level the job store begins its own transactions at. Left unset, they are ReadCommitted.
public IsolationLevel? TransactionIsolationLevel { get; set; }
Property Value
Remarks
This replaced a TxIsolationLevelSerializable flag, which could say only "serializable" or
"the default" and so could not express Snapshot,
RepeatableRead or a deliberate
ReadUncommitted. null means Quartz's default rather
than the provider's, because those differ — MySQL's is repeatable read — and inheriting the
provider's would silently change how the store behaves depending on which database it is talking
to.
SQLite is the exception: the store forces serializable there whatever this says, because concurrent SQLite transactions at a lower level fail with "database is locked".
This applies only to connections the job store opens itself. An operation running on a connection the application enlisted uses whatever isolation level that transaction was begun at.
TransientRetryInterval
How long to wait between transient database failure retries.
public TimeSpan TransientRetryInterval { get; set; }
Property Value
UseBackgroundThreads
Whether the misfire handler and cluster manager run on background threads, which do not keep the process alive on their own.
public bool UseBackgroundThreads { get; set; }
Property Value
Remarks
These two are the only real threads Quartz creates — the scheduling loop is a
Task — so this is the whole of the "do Quartz's threads
hold my console application open" question. UseBackgroundThreads rather than
MakeThreadsDaemons: "daemon" is the Java word for what .NET calls
IsBackground.
UseDbLocks
Whether database row locks are used for synchronization. Required for clustering.
public bool UseDbLocks { get; set; }