Job Policies
Control how Priostack handles job deadlines, retries, and timeout boundary events to make your service tasks resilient.
Job deadlines
Job deadline field
The deadline is the absolute UTC timestamp by which a job lock must be released (via complete or fail). It is derived from the timeout you pass when activating a job:
deadline = activatedAt + timeout_ms
If a worker holds a job past its deadline without completing or failing it, Priostack releases the lock and the job becomes available for re-polling. This protects against worker crashes and network partitions.
| Field (activate request) | Type | Default | Description |
|---|---|---|---|
timeout | integer (ms) | 30 000 | Lock duration in milliseconds. Deadline = activation time + timeout. |
The deadline is returned in every activated job object. Workers should check it and fail the job gracefully before it expires rather than letting the lock silently release:
// Example: fail job 5 seconds before deadline to leave retry headroom
const msRemaining = new Date(job.deadline) - Date.now();
if (msRemaining < 5000) {
await failJob(job.key, { retries: job.retries - 1, errorMessage: "Deadline approaching" });
return;
}
// ... do work ...
await completeJob(job.key, { variables: result });
Retry policy
Job retry configuration
Each job has a retry counter. You set the initial retry count in the BPMN task definition extension or at job completion/failure time. When a worker calls fail, it passes the remaining retries value.
When retries reach 0, Priostack raises an incident and the process pauses at that task. A human or automated runbook must resolve the incident (typically by calling update-retries then resolve).
| Scenario | Worker action | Result |
|---|---|---|
| Transient error, more retries left | fail with retries: N-1 | Job re-queued after retryBackoff ms |
| Permanent error | fail with retries: 0 | Incident raised immediately |
| Success | complete | Process advances to next element |
Setting retries in BPMN (extension element)
<bpmn:serviceTask id="task_charge" name="Charge payment">
<bpmn:extensionElements>
<zeebe:taskDefinition type="payment:charge" retries="3" />
</bpmn:extensionElements>
</bpmn:serviceTask>
Retry backoff
Pass retryBackoff (milliseconds) in the fail request to delay the next attempt. Use exponential backoff for external API calls to avoid thundering herds:
// Attempt 1: fail with retryBackoff: 2000
// Attempt 2: fail with retryBackoff: 4000
// Attempt 3: fail with retries: 0 → incident
const backoff = Math.pow(2, attemptNumber) * 1000;
await failJob(job.key, {
retries: job.retries - 1,
errorMessage: "Stripe rate limit",
retryBackoff: backoff
});
Timeout boundary events
BPMN timeout boundary events
A non-interrupting or interrupting timer boundary event on a service task lets you react to long-running jobs in the process model itself, without relying solely on job-level retries.
Common patterns:
| Pattern | Configuration | Use case |
|---|---|---|
| Escalation after SLA | Non-interrupting timer → notification task | Notify a manager if payment hasn't completed in 30 min |
| Hard deadline cancel | Interrupting timer → error end event | Cancel order if fulfilment doesn't start within 2 hours |
| Fallback path | Interrupting timer → alternative service task | Switch to backup payment provider after 10 seconds |
BPMN snippet — interrupting timer
<bpmn:boundaryEvent id="timeout_charge" attachedToRef="task_charge"
cancelActivity="true">
<bpmn:timerEventDefinition>
<bpmn:timeDuration>PT30S</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:boundaryEvent>
When the timer fires, Priostack cancels the job lock, raises an incident for the timed-out job (if configured), and follows the sequence flow from the boundary event to your error-handling path.