- cluster_node, cluster_lease, cluster_setting as standard QQQ tables (cluster.read / cluster.write), node status possible values, help for every table, field, process, widget and value source - Liquibase changelogs in the jar: schema (idempotent, no FKs, no superuser) and insert-only seeded settings - runtime: register + heartbeat on the database clock, drain requests flowing to QNodeLifecycle.startDraining, DRAINING/STOPPED tracking, lost-node sweep on the cluster-sweeper lease with the cluster.node.lost alert, idempotent purge of old rows; ClusterRuntimeService - ClusterLeases: one atomic compare-and-set UPDATE per change (ConditionalUpdateAction), tryAcquire / renew / release / isLeader - record actions Drain node and Cancel drain (standard ETL Review / Result, cluster.drain), Cluster app with the Nodes widget by role, cluster.node.heartbeat health check - CI (CircleCI qqq-orb), release-rc workflow, docs, 35 tests (memory backend, plus Liquibase and the RDBMS module on H2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.5 KiB
AGENTS.md
This file provides guidance to Codex and other agents when working with this repository.
Project overview
QBit Cluster runs a QQQ application as one unit on N nodes: node registry and heartbeats
(cluster_node), lost-node detection with the cluster.node.lost alert, compare-and-set leases
for singletons (cluster_lease, ClusterLeases), seeded settings (cluster_setting), Drain node
/ Cancel drain record actions, the cluster.node.heartbeat health check and the Cluster app with
the Nodes widget. Read docs/DESIGN.md and README.md first.
Build commands
Java 21; always use the wrapper (offline in this workspace):
./mvnw -o verify # checkstyle, tests, JaCoCo (>=70% instructions, >=90% classes)
./mvnw -o test -Dtest=ClusterLeasesTest
Tests use JUnit 5, AssertJ, MOCK auth and the memory backend; ClusterChangelogTest runs the
shipped changelogs through real Liquibase on H2 and the runtime through the RDBMS module. No
Docker. If core cluster classes are missing, the shared ~/.m2 4.1.0-SNAPSHOT was overwritten:
reinstall QQQ from the feature/cluster-ha-p1 worktree.
Architecture by package
com.kingsrook.qbits.cluster:ClusterQBitProducer(adds everything directly),ClusterQBitConfig,ClusterLeases.model:ClusterTables(table metadata, field and table names),NodeStatus,ClusterSettings(defaults + load),ClusterSettingValidator.runtime:ClusterRuntime(thread, tick, stop),ClusterRuntimeService,ClusterNodeRegistry(own row),ClusterNodeInfo(env, roles, JVM),ClusterSweeper,ClusterAlerts,ClusterSystem(system-session scope).processes:ClusterNodeActions(metadata),ClusterNodeActionSteps(Review / Result).widgets:ClusterNodesWidgetRenderer.health:ClusterHeartbeatHealthCheck.
Invariants
- Every write that two nodes could race on is a
ConditionalUpdateActioncompare-and-set; times come from the backend clock (databaseNow), never the pod clock. - The qbit never runs DDL. Schema and defaults ship as Liquibase SQL in the jar; defaults are
insert-only with empty rollbacks. Column names = snake_case of field names; keep the changelog,
ClusterTablesandClusterSettings.DEFAULTSin step (tests enforce it). - Processes are record actions only (never in navigation), standard streamed ETL, plain labels.
- Renderers read in the viewer's session; only the runtime's own bookkeeping runs as system.
- Every table, field, process, widget and possible-value source has help in
help/qbit-cluster.yaml(ClusterQBitProducerTest.helpIsComplete). Summaries are plain text, at most 120 characters, no underscores.
Naming and code style
Tables cluster_*, permissions cluster.read, cluster.write, cluster.drain, processes
clusterDrainNode / clusterCancelDrain, widget clusterNodes, lease cluster-sweeper.
Kingsrook style: three-space indent, braces on new lines, return (x);, flower-box Javadoc on
every class and method, the Apache license header. Do not weaken checkstyle or coverage gates.
Dependencies
Parent com.kingsrook:qbit-build-parent:2.0.0; the default qqq-snapshot profile imports
qqq-bom-pom ${qqq.snapshot.version} (4.1.0-SNAPSHOT until a QQQ RC ships the cluster APIs).
Release flow
CircleCI (kingsrook/qqq-orb): feature branches test; develop publishes SNAPSHOTs; release/*
publishes RCs (cut by .github/workflows/release-rc.yml); vX.Y.Z tags publish releases.
Publishing requires the owner's authorization. Update CHANGELOG before a release.