Retry and cache¶
Each step reference in a use case can carry settings. Settings apply only to that use case, so the same step
can be retried in one use case and not in another.
steps:
- step: saveOrder
settings:
retry:
max-retries: 3
delay: 100ms
cache:
name: orders
key: "#input.id"
When both are set, the cache is checked first. A cache hit skips the step and its retries.
flowchart LR
input([input]) --> hit{cache hit?}
hit -- yes --> out([cached output])
hit -- no --> step[run step]
step -- fails --> retry{retries left?}
retry -- yes --> step
retry -- no --> err([exception])
step -- succeeds --> store[store in cache] --> result([output])
Retry¶
Retry uses Spring Framework's core retry support (RetryTemplate).
| Property | Default | Description |
|---|---|---|
max-retries |
3 |
Retries after the first attempt |
delay |
1s |
Delay before the first retry |
multiplier |
1.0 |
Factor applied to the delay after each retry |
max-delay |
unlimited | Upper bound for the delay |
jitter |
0 |
Random jitter added to each delay |
timeout |
0 (none) |
Maximum total time spent retrying |
includes |
all | Exception classes that trigger a retry |
excludes |
none | Exception classes that never trigger a retry |
When all retries fail, the last exception thrown by the step reaches the caller as it is.
Retry can also be declared on the step itself. YAML settings take precedence:
Cache¶
Cache uses Spring's cache abstraction, so any CacheManager works (Caffeine, Redis, ...).
| Property | Required | Description |
|---|---|---|
name |
yes | Cache name in the application's CacheManager |
key |
no | SpEL expression over the step's inputs. Defaults to the inputs themselves (which then need proper equals/hashCode). |
Each input is readable by its parameter name, and #input names the only one of a step taking a single
parameter:
- step: saveOrder
settings:
cache: { name: orders, key: "#input.id" } # (1)!
- step: quoteShipping
in: { order: $saveOrder, country: $input }
settings:
cache: { name: quotes, key: "#order.weight + '-' + #country" } # (2)!
saveOrder(request: OrderRequest)takes one parameter, so#inputis that request.quoteShipping(order: OrderEntity, country: String)takes two, so each is named.#inputdoes not exist here.
Without a key, a step taking one input is keyed by it, and a step taking several by all of its arguments
together.
Cache can also be declared on the step itself. YAML settings take precedence:
Warning
Don't combine this with Spring's @Cacheable on the same method. Both would cache the result, each with its own key.
The application needs a CacheManager bean. With Spring Boot, add spring-boot-starter-cache and @EnableCaching.
If a step uses a cache and no CacheManager exists, or the cache name is unknown, startup fails.
Note
Enact reads from and writes to the cache but never evicts entries. Configure expiry in your cache
provider, or evict entries yourself through the CacheManager when the underlying data changes.
The demo's cancelOrder step does this: