Interface ILockHandler
- Namespace
- Quartz.Impl.AdoJobStore
- Assembly
- Quartz.dll
An interface for providing thread/resource locking in order to protect resources from being altered by multiple threads at the same time.
public interface ILockHandler
Properties
RequiresConnection
Whether this lock handler requires a database connection for its lock management operations.
bool RequiresConnection { get; }
Property Value
- See Also
Methods
AcquireLock(Guid, ConnectionAndTransactionHolder?, SchedulerLock, CancellationToken)
Grants a lock on the identified resource to the calling context, waiting until it is available.
ValueTask<bool> AcquireLock(Guid requestorId, ConnectionAndTransactionHolder? conn, SchedulerLock lockKind, CancellationToken cancellationToken = default)
Parameters
requestorIdGuidIdentifies the calling context, so that a re-entrant acquire can be told from a competing one.
connConnectionAndTransactionHolderThe unit of work to take the lock on. It is null when the store has not opened a connection yet, which it delays for a handler whose RequiresConnection is false.
lockKindSchedulerLockWhich of the two locks to take.
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
- ValueTask<bool>
true if this call took the lock and its caller must release it; false if
requestorIdalready held it and must not.
Remarks
The answer is a release obligation rather than a report of success. true
says this call took the lock and its caller is the one that has to give it back;
false says requestorId already held it — a re-entrant
acquire — so the outer caller's single release is what frees it, and releasing here would
drop a lock that operation is still relying on. A handler that instead counts its holds may
answer true to a re-entrant acquire, because there the inner release is
the one that decrements; either way the caller releases exactly when it was told
true.
Re-entry is the only thing false may mean. A handler that could not
take the lock says so by throwing: LockException when the lock was refused,
and OperationCanceledException when
cancellationToken fired. Answering false on
cancellation is not a harmless approximation — the job store reads it as "already held, do
not release" and goes on to run the guarded operation with no lock at all, which is the whole
point of taking one.
The store's own ordering must not be relied on to cover for a handler that gets this wrong. A handler answering false to RequiresConnection is followed immediately by a connection open on the same token, so a mistake here is masked today by that open throwing first. That is an accident of statement order rather than a guarantee, and it does not hold wherever the store reaches the lock in a different sequence.
A handler that gives up leaves nothing behind: an abandoned wait must not consume a handover meant for the next waiter, and a partially taken lock is released before the exception escapes, so that the next caller can still be served.
Exceptions
- OperationCanceledException
cancellationTokenfired before the lock was taken.- LockException
The lock could not be obtained.
Initialize(LockHandlerContext)
Called once by the job store before the lock handler is used, telling the handler which scheduler it locks for. The default implementation does nothing, which suits a handler that does not key its locks by scheduler identity.
void Initialize(LockHandlerContext context)
Parameters
contextLockHandlerContext
ReleaseLock(Guid, SchedulerLock, CancellationToken)
Release the lock on the identified resource if it is held by the calling thread.
ValueTask ReleaseLock(Guid requestorId, SchedulerLock lockKind, CancellationToken cancellationToken = default)
Parameters
requestorIdGuidlockKindSchedulerLockcancellationTokenCancellationToken
Returns
Shutdown(CancellationToken)
Called once by the job store, after the store has released its own resources, telling the handler to release whatever it opened. The default implementation does nothing, which suits a handler that holds nothing of its own.
ValueTask Shutdown(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
Remarks
Named for Shutdown(CancellationToken) rather than for IAsyncDisposable, because it is the store's shutdown that reaches it and a handler is never used again afterwards. It is a default interface member, so a handler written against 4.0's first shape need not implement it — one that holds nothing has nothing to say here.
It runs after the lock this handler guards has stopped being asked for, so an implementation may assume no acquire is in flight. Throwing is not fatal: the store logs it and finishes shutting down, because a scheduler that cannot complete its shutdown is worse than a connection that outlives it.