Cache warmer workshop
Latest stable Based on Leader release 0.4.0
Runnable release workshop · Hazelcast · source pinned to
0.4.0
Problem
Section titled “Problem”A cache warm-up should run once per partition, not once for the whole cluster. The example gives every partition its own lock name, so different nodes may warm different partitions while each partition still has one owner.
This is a coordination boundary, not a replacement for business idempotency. The exercise separates who may start the body from how the body records durable progress, so the result remains explainable after contention, timeout, or process loss.
When to use it
Section titled “When to use it”Use this workshop when a cache warm-up should run once per partition, not once for the whole cluster. The example gives every partition its own lock name, so different nodes may warm different partitions while each partition still has one owner. Start with the example unchanged, then replace only the workload while preserving the lock identity, bounded execution, and observable skip path.
Choose another pattern when every replica should perform the work, when a queue already assigns exclusive ownership, or when the operation cannot tolerate retry after a leader failure.
Coordinates
Section titled “Coordinates”This example is not published as a library. Run it from the repository. In an application, choose one bluetape4k-dependencies version and declare the required leader backend without a second version:
dependencies { implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:<version>")) // Add the backend used by this workshop without a version.}Core concepts
Section titled “Core concepts”- Coordination backend: Hazelcast stores or enforces the leadership decision.
- Shared identity: all contenders must derive the same lock name for the same logical work.
- Skip-on-contention: losing leadership is an expected result, not an exceptional failure.
- Bounded ownership: timeout, lease/session rules, and shutdown handling determine when another node may continue.
- Workload safety: retries, checkpoints, and idempotency belong to the application body.
Do not stop at a green build. Check this observable result: every partition appears once in WarmResult.warmed; isolated failures appear in failed without stopping later partitions.
Quick start
Section titled “Quick start”Prerequisites: JDK 21+ and Docker when the backend test uses Testcontainers.
./gradlew :examples:cache-warmer:runRun two or more contenders when the demo supports it. Check this result: every partition appears once in WarmResult.warmed; isolated failures appear in failed without stopping later partitions. Then stop or release the current owner and run the next cycle to verify takeover.
API by task
Section titled “API by task”- Read
CachePartitionWarmerfirst; it defines the application-facing coordination boundary. - Follow
CachePartitionWarmerDemoto see client construction, contender setup, and result reporting. - Read
CachePartitionWarmerTestto learn which ownership transitions the release promises. - Replace the demo workload with a small idempotent action before adapting a real job.
Treat the return value as part of the API. An executed, skipped, failed, or partially completed result should be logged and measured separately.
Recommended patterns
Section titled “Recommended patterns”- Namespace lock names by environment and workload, for example
prod:billing:nightly. - Keep the elected body small; move preparation before the lock and durable result recording inside the correct transaction boundary.
- Size wait time for fast contention feedback and ownership duration for the actual failure model.
- Preserve cancellation and interruption signals instead of converting them into a normal skip.
- Make takeover safe with an idempotency key, marker, claim token, or resumable checkpoint.
Integrations
Section titled “Integrations”The workshop integrates Hazelcast with a runnable Gradle application. The example owns its local fixture for learning, but production code should inject the backend client and let the application lifecycle close it.
Scheduler, HTTP, operator, and coroutine frameworks should call the coordination boundary; they should not hide lock acquisition inside unrelated business services. That separation keeps contention and takeover visible in tests and metrics.
Configuration
Section titled “Configuration”Review partitions, lockNamePrefix, partition-level waitTime, leaseTime, and a pluggable electorFactory. Use the same logical lock identity on every replica and different identities for unrelated jobs or environments.
Start with short local values so contention and takeover are visible. Production values must come from measured body duration, backend latency, shutdown budget, and the cost of duplicate work—not from the demo defaults.
Failure modes
Section titled “Failure modes”- Every node executes: lock names or namespaces differ. Log the final lock identity at startup.
- No node executes: backend reachability, credentials, RBAC, or an existing owner is blocking acquisition.
- Takeover is late: the lease/session or client timeout exceeds the service recovery budget.
- Work repeats after failure: leadership ended before durable progress was recorded; add an idempotency key or checkpoint.
- Shutdown hangs: the workload ignores cancellation or owns a client/executor that is not closed.
Diagnose in that order: backend health, resolved lock identity, acquisition result, body result, then release/takeover evidence.
Operations
Section titled “Operations”Record attempts, acquired executions, skips, failures, body duration, and takeover latency by a bounded lock-name tag. Alert on sustained no-acquisition, growing body duration, or repeated ownership churn rather than on a normal isolated skip.
Document who owns backend provisioning, credentials, schema/keys, cleanup, and client shutdown. A successful demo does not transfer those responsibilities to the library.
Testing
Section titled “Testing”./gradlew :examples:cache-warmer:testThe important assertions are behavioral: exactly one owner during contention, a non-exceptional skip for contenders, release on normal and failed exits, and reacquisition by another node. If Docker or a privileged runtime is required, keep that integration test separate from fast unit tests but do not replace it with mocks.
Workshops and learning path
Section titled “Workshops and learning path”This page is a guided workshop, not just a command reference. Work through it in five passes:
- Baseline: run one contender and identify the workload boundary.
- Contention: run multiple contenders and explain the executed and skipped results.
- Failure: terminate or fail the owner and observe release or expiry.
- Takeover: verify that another node continues without corrupting durable state.
- Adaptation: change the lock namespace and workload, add metrics, and write one failure-focused test.
After this workshop, compare the backend manual with the core execution-model and failure-semantics chapters before moving the pattern into a service.
Limitations
Section titled “Limitations”A group election does not guarantee a stable slot-to-partition mapping. Keep independent lock names when partition ownership is part of the contract.
The demo favors a compact, observable scenario. It does not define production topology, credential rotation, capacity planning, disaster recovery, or a universal exactly-once guarantee.
Release diagrams
Section titled “Release diagrams”These diagrams are loaded directly from README assets published with the 0.4.0 release and pinned to its immutable commit. They describe this manual’s released structure and runtime flows, not later Snapshot changes. Select a preview to open the SVG at the same release commit.
Cache warmer architecture diagram
Section titled “Cache warmer architecture diagram”Release README: examples/cache-warmer/README.md
Cache warmer flow diagram
Section titled “Cache warmer flow diagram”Release README: examples/cache-warmer/README.md
Cache warmer scenario diagram
Section titled “Cache warmer scenario diagram”Release README: examples/cache-warmer/README.md
Cache warmer sequence diagram
Section titled “Cache warmer sequence diagram”Release README: examples/cache-warmer/README.md



