Register backups caches with ClusterCaches (multi-node) #30

Merged
KofTwentyTwo merged 2 commits from feature/cluster-caches into develop 2026-10-15 19:11:22 +00:00
KofTwentyTwo commented 2026-10-15 17:11:21 +00:00 (Migrated from github.com)

What

Makes qbit-backups correct on multi-node deployments (QQQ cluster HA spec, item 4 and owner decision 1).

Cache Decision Why
BackupsMetrics cached Prometheus text (60 s) shared as qbit-backups.metrics Rendered from plan and run rows that change at runtime (plan edits in the admin UI, finished runs).
SlaChecker.MANIFEST_OK_AT node-local Throttles this node's storage HEAD of a manifest to once an hour. It caches storage state, not editable data, and a pruned run is skipped by its prunedDate, so each node is exactly as fresh as a single node is today.
SlaChecker.LAST_AUDIT_AT node-local Throttles this node's daily bucket audit; another node auditing again is only repeated work.
BackupsRuntime.PROCESS_PERMISSIONS node-local Built from the qbit config at startup, identical on every node.
  • The metrics cache moved from two static fields to an AtomicReference<Rendered> registered with ClusterCaches.shared(...). BackupsMetrics.invalidate() publishes the cluster invalidation; resetCache() stays as the local clear.
  • Invalidation points: BackupEngine.finishWith (every finished run) and the plan table's post insert/update/delete. BackupPlanTableCustomizer is now also the plan table's post customizer (alone, or added to the scheduled-job sync MultiCustomizer when a scheduler is configured).
  • TTLs are unchanged and remain the safety net.

Tests

  • New BackupsClusterCachesTest: ClusterCacheAudit.unregisteredStaticCaches("com.kingsrook.qbits.backups") is empty; a remote memo-invalidate event (node-b over a test wire transport) clears the metrics cache; a plan update publishes the event from node-a.
  • BackupsMetricsTest.testCacheEscapeAndFlag now asserts caching by identity and that a saved plan and finished run clear the cache at once.
  • ./mvnw -o verify (with -Denforcer.skip=true, see below): 207 tests pass, coverage checks met.

Release note: QQQ dependency

ClusterCaches is only in QQQ 4.1.0-SNAPSHOT today (qqq#1228; not in 4.1.0-RC.12). This PR sets the one-line property qqq.snapshot.version to 4.1.0-SNAPSHOT. The G7 guardrail (no SNAPSHOT QQQ dependencies) will fail CI until that property points at the QQQ RC that ships ClusterCaches. Before merging or releasing, change qqq.snapshot.version to that RC. Never release with the SNAPSHOT.

🤖 Generated with Claude Code

## What Makes qbit-backups correct on multi-node deployments (QQQ cluster HA spec, item 4 and owner decision 1). | Cache | Decision | Why | |---|---|---| | `BackupsMetrics` cached Prometheus text (60 s) | **shared** as `qbit-backups.metrics` | Rendered from plan and run rows that change at runtime (plan edits in the admin UI, finished runs). | | `SlaChecker.MANIFEST_OK_AT` | **node-local** | Throttles this node's storage HEAD of a manifest to once an hour. It caches storage state, not editable data, and a pruned run is skipped by its `prunedDate`, so each node is exactly as fresh as a single node is today. | | `SlaChecker.LAST_AUDIT_AT` | **node-local** | Throttles this node's daily bucket audit; another node auditing again is only repeated work. | | `BackupsRuntime.PROCESS_PERMISSIONS` | **node-local** | Built from the qbit config at startup, identical on every node. | - The metrics cache moved from two static fields to an `AtomicReference<Rendered>` registered with `ClusterCaches.shared(...)`. `BackupsMetrics.invalidate()` publishes the cluster invalidation; `resetCache()` stays as the local clear. - Invalidation points: `BackupEngine.finishWith` (every finished run) and the plan table's post insert/update/delete. `BackupPlanTableCustomizer` is now also the plan table's post customizer (alone, or added to the scheduled-job sync `MultiCustomizer` when a scheduler is configured). - TTLs are unchanged and remain the safety net. ## Tests - New `BackupsClusterCachesTest`: `ClusterCacheAudit.unregisteredStaticCaches("com.kingsrook.qbits.backups")` is empty; a remote memo-invalidate event (node-b over a test wire transport) clears the metrics cache; a plan update publishes the event from node-a. - `BackupsMetricsTest.testCacheEscapeAndFlag` now asserts caching by identity and that a saved plan and finished run clear the cache at once. - `./mvnw -o verify` (with `-Denforcer.skip=true`, see below): 207 tests pass, coverage checks met. ## Release note: QQQ dependency `ClusterCaches` is only in QQQ `4.1.0-SNAPSHOT` today (qqq#1228; not in 4.1.0-RC.12). This PR sets the one-line property `qqq.snapshot.version` to `4.1.0-SNAPSHOT`. The G7 guardrail (no SNAPSHOT QQQ dependencies) will fail CI until that property points at the QQQ RC that ships `ClusterCaches`. **Before merging or releasing, change `qqq.snapshot.version` to that RC.** Never release with the SNAPSHOT. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.