Core Concepts
Priority ordering, wait-time promotion, timeout derivation, retries, and the atomic queue state machine.
Priority levels
Lower numeric value runs first. Heap order is priority, then earlier startAt.
| Constant | Value | Description |
|---|---|---|
PriorityImmediate |
0 | Highest; run first |
PriorityHigh |
1 | High priority |
PriorityRetry |
2 | Failed tasks re-enqueued for retry |
PriorityNormal |
3 | Default when preset is missing or zero-value semantics apply via lookup |
PriorityLow |
4 | Lowest; eligible for promotion after wait |
PresetConfig.Priority uses Go's zero value PriorityImmediate (iota 0) when unset on a defined preset entry.
Priority promotion
On each Pop, pending scans the heap and may raise long-waiting tasks:
| From | Wait | To |
|---|---|---|
| Low | clamp(Timeout, 30s, 120s) |
Normal |
| Normal | clamp(Timeout*2, 30s, 120s) |
High |
Promotion only moves to a higher priority (smaller value). Immediate, High, and Retry are not auto-promoted by these rules.
Timeout derivation
Base timeout is Config.Timeout (default 30s), optionally overridden by a preset's Timeout when > 0. Then adjusted by priority and clamped to 15s–120s:
| Priority | Formula |
|---|---|
| Immediate | timeout / 4 |
| High / Retry | timeout / 2 |
| Normal | timeout |
| Low | timeout * 2 |
Per-enqueue WithTimeout overrides the derived value for that task.
Execution, panic, and retry
Each worker runs action in a child goroutine under context.WithTimeout:
- Success — logs completion; optional
callback(id)runs asynchronously. - Timeout / cancel / error — if
WithRetryis enabled andretryTimes < retryMax, the task is re-pushed atPriorityRetrywithstartAtreset. - Panic — recovered inside the action goroutine and treated as an error (
panic: ...). - Exhausted retries — logged as
task.exhausted; no further re-enqueue.
Default retryMax is 3 when WithRetry() is called without an argument.
State machine
| State | Meaning |
|---|---|
| Created | After New; not accepting worker loops until Start |
| Running | Workers active |
| Closed | No new pushes; drain then exit |
Transitions use atomic.Uint32 CAS — no mutex on the public state field. Enqueue fails if the staging queue is closed or full. Shutdown from any non-closed state is safe and idempotent.
Related
- Architecture — modules and flow
- Configuration — defaults and options
- API Reference — types and functions