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.
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.
## 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)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
Makes qbit-backups correct on multi-node deployments (QQQ cluster HA spec, item 4 and owner decision 1).
BackupsMetricscached Prometheus text (60 s)qbit-backups.metricsSlaChecker.MANIFEST_OK_ATprunedDate, so each node is exactly as fresh as a single node is today.SlaChecker.LAST_AUDIT_ATBackupsRuntime.PROCESS_PERMISSIONSAtomicReference<Rendered>registered withClusterCaches.shared(...).BackupsMetrics.invalidate()publishes the cluster invalidation;resetCache()stays as the local clear.BackupEngine.finishWith(every finished run) and the plan table's post insert/update/delete.BackupPlanTableCustomizeris now also the plan table's post customizer (alone, or added to the scheduled-job syncMultiCustomizerwhen a scheduler is configured).Tests
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.testCacheEscapeAndFlagnow 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
ClusterCachesis only in QQQ4.1.0-SNAPSHOTtoday (qqq#1228; not in 4.1.0-RC.12). This PR sets the one-line propertyqqq.snapshot.versionto4.1.0-SNAPSHOT. The G7 guardrail (no SNAPSHOT QQQ dependencies) will fail CI until that property points at the QQQ RC that shipsClusterCaches. Before merging or releasing, changeqqq.snapshot.versionto that RC. Never release with the SNAPSHOT.🤖 Generated with Claude Code