Class ExecutionLimits
- Namespace
- Quartz
- Assembly
- Quartz.dll
An immutable set of concurrency limits for execution groups. Execution groups are optional tags on triggers that characterize the resource requirements of the associated job (e.g. "batch-jobs", "high-cpu", "large-ram").
public sealed class ExecutionLimits
- Inheritance
-
ExecutionLimits
- Inherited Members
Remarks
Every limit says how many concurrent executions its group may have:
- A positive value limits how many threads the group may consume concurrently.
- A value of
0forbids the group from running. - null means unlimited (no restriction).
Every limit also says what it is counted against — see ExecutionLimitScope. A Node limit, the default, is what this node may run; a Cluster limit is what every node sharing the job store may run between them. The two coexist: a heterogeneous cluster caps heavy work per node, a multi-tenant one caps a tenant across the cluster, and one deployment can want both.
Use OtherGroups as a catch-all default for groups not explicitly listed.
Build one with ExecutionLimitsBuilder, either directly or through UseExecutionLimits(Action<ExecutionLimitsBuilder>); hand it to SetExecutionLimits(ExecutionLimits?, CancellationToken) to apply it.
Fields
OtherGroups
The group name that carries the default limit for execution groups not explicitly configured.
public const string OtherGroups = "*"
Field Value
Properties
Groups
Every configured group and its limit.
public IReadOnlyList<ExecutionGroupLimit> Groups { get; }
Property Value
HasClusterScopedLimits
Whether any group is limited across the cluster rather than on this node alone.
public bool HasClusterScopedLimits { get; }
Property Value
Remarks
A job store reads this to decide whether a cluster-wide in-flight count is worth fetching:
with no cluster-scoped limit there is nothing such a count could constrain, so the round trip
is skipped. A group that is explicitly unlimited, or forbidden outright with 0, does not
make this true whatever scope it was declared in — neither answer depends on
what is in flight.
IsEmpty
true when nothing is limited, in which case every trigger is free to fire.
public bool IsEmpty { get; }
Property Value
UsesTriggerGroupWhenUnset
Whether a trigger that carries no execution group of its own is limited as though it belonged to a group named after its own Group. Off unless UseTriggerGroupWhenUnset() asked for it.
public bool UsesTriggerGroupWhenUnset { get; }
Property Value
Remarks
The derivation is an evaluation-time rule and nothing else: what a trigger carries and what the store persists in EXECUTION_GROUP are unchanged, and ExecutionGroup still reads null. It exists for schedules that already partition work by trigger group — a tenant per group, a subsystem per group — where restating every group as an execution group would be a second copy of the same fact.
An explicit execution group always wins. Turning this on also moves the ungrouped triggers out of ForDefaultGroup(int, ExecutionLimitScope)'s bucket and under OtherGroups's catch-all, because they are no longer ungrouped as far as the limits are concerned.
Methods
CreateSlots(IReadOnlyCollection<ExecutionGroupInFlight>?)
Creates a ledger of the slots these limits allow, for one trigger acquisition to count down as it takes triggers. The snapshot itself is unaffected, so a retried acquisition starts from the limits again by creating another ledger.
public ExecutionSlots CreateSlots(IReadOnlyCollection<ExecutionGroupInFlight>? clusterInFlight = null)
Parameters
clusterInFlightIReadOnlyCollection<ExecutionGroupInFlight>What the whole cluster already holds in flight, one entry per distinct (execution group, trigger group) pair, or null when the caller has no such count. Only Cluster limits are lowered by it: a Node limit has already had this node's running work subtracted by the scheduler thread, and subtracting a count that includes the same firings again would halve the limit on a busy node.
Returns
TryGetLimit(ExecutionGroupScope, out int?)
Reads the limit configured for one group.
public bool TryGetLimit(ExecutionGroupScope group, out int? maxConcurrent)
Parameters
groupExecutionGroupScopeThe bucket to read: Default, OtherGroups, or a named group via Named(string).
maxConcurrentint?The limit: a positive count,
0when the group is forbidden, or null when it is explicitly unlimited.
Returns
- bool
true when the group has a limit of its own. false does not mean unlimited — OtherGroups may still apply to a named group.
Remarks
Only the number; whether it is counted per node or per cluster is on the entries Groups hands out.