Control the retry policy
Using Golem’s retry mechanism
Golem applies retry policies to retryable host operations and agent failures. The selected policy controls delays and retry limits. Permanent errors, permission failures, stack overflows, and traps are not retried.
A trap is permanent. Return an error for a transient condition and use a retry schedule. For application-level errors, the application must handle the returned error and apply that schedule; returning an error does not automatically activate a host retry policy.
Do not predicate retry policies on is-idempotent: the host no longer supplies that property. Remote-write eligibility
does not guarantee exactly-once effects; the peer must enforce an idempotency key.
If the maximum number of retries is reached, the agent will be marked as failed and no further invocations will be possible on it.
During recovery, Golem replays the oplog and reuses results already recorded for preceding durable operations. Raising an unhandled exception does not cause those earlier operations to execute again.
Host retry policies govern retryable Golem operations and agent failures. They do not retry arbitrary application-level errors. Handle these errors in your application.
Raising a trap
Use a trap to stop an invocation on an unrecoverable condition. An explicit trap cannot be caught and is never retried.
TypeScript
Use the SDK’s trap function. It never returns:
import { trap } from "@golemcloud/golem-ts-sdk"
trap("Invalid persistent state")Customizing the retry policy
The retry policy which controls the maximum number of retries and the exponential backoff is a global configuration of the Golem servers, but it can be customized for each agent.
TypeScript
The @golemcloud/golem-ts-sdk package exports the withRetryPolicy function to temporarily install a named retry policy for a block of code:
import {withRetryPolicy, type NamedRetryPolicy} from "@golemcloud/golem-ts-sdk"
// Durations are expected as nanoseconds
const policy: NamedRetryPolicy = {
name: "temporary-policy",
priority: 1000,
predicate: {
nodes: [{tag: "pred-true"}],
},
policy: {
nodes: [
{
tag: "count-box",
val: {
maxRetries: 3,
inner: 1,
},
},
{
tag: "clamp-delay",
val: {
minDelay: 100_000_000n, // 100 milliseconds
maxDelay: 2_000_000_000n, // 2 seconds
inner: 2,
},
},
{
tag: "exponential",
val: {
baseDelay: 100_000_000n,
factor: 1.5,
},
},
],
},
}
const result: string = withRetryPolicy(policy, () => {
// this closure runs with the custom retry policy
return "hello"
})The policy passed to withRetryPolicy is a NamedRetryPolicy, which contains a name, priority, predicate, and policy tree:
export type RetryPredicate = {
nodes: PredicateNode[];
};
export type RetryPolicy = {
nodes: PolicyNode[];
};
export type NamedRetryPolicy = {
name: string;
priority: number;
predicate: RetryPredicate;
policy: RetryPolicy;
};Named retry policies in golem.yaml
Retry policies can also be defined declaratively in the application manifest (golem.yaml). These named retry policies are created in the environment during deployment, making them available to all agents without requiring code changes.
retryPolicyDefaults:
local:
default-retry:
priority: 10
predicate: true
policy:
countBox:
maxRetries: 3
inner:
exponential:
baseDelay: { secs: 1, nanos: 0 }
factor: 2.0Manifest policy types reference
The following policy types can be used to construct retry policy trees:
| Type | Fields | Description |
|---|---|---|
"immediate" | — | Retry immediately |
"never" | — | Never retry |
periodic | { secs, nanos } | Fixed delay between retries |
exponential | { baseDelay, factor } | Exponentially increasing delay |
fibonacci | { first, second } | Fibonacci-sequence delays |
countBox | { maxRetries, inner } | Limit total retry count |
timeBox | { limit, inner } | Limit total retry time |
clamp | { minDelay, maxDelay, inner } | Clamp delay range |
addDelay | { delay, inner } | Add fixed delay to inner policy |
jitter | { factor, inner } | Add random jitter |
filteredOn | { predicate, inner } | Apply only when predicate matches |
andThen | [policy1, policy2] | Sequential composition |
union | [policy1, policy2] | Union of two policies |
intersect | [policy1, policy2] | Intersection of two policies |
Manifest predicates reference
Predicates control when a retry policy is applied. The following predicate types are available:
| Type | Fields | Description |
|---|---|---|
"true" | — | Always matches |
"false" | — | Never matches |
propEq | { property, value } | Property equals value |
propNeq | { property, value } | Property not equal |
propGt / propGte | { property, value } | Greater than / greater or equal |
propLt / propLte | { property, value } | Less than / less or equal |
propExists | string | Property exists |
propIn | { property, values } | Property in set |
propMatches | { property, pattern } | Glob match |
propStartsWith | { property, prefix } | Starts with prefix |
propContains | { property, substring } | Contains substring |
and | [pred1, pred2] | Logical AND |
or | [pred1, pred2] | Logical OR |
not | predicate | Logical NOT |
Predicate values in the manifest are strings, integers, or booleans. For example:
predicate:
propEq:
property: status-code
value: 503