How to Read This Codebase
Recommended Reading Order
-
Domain models —
internal/models/node.go,internal/models/subscription.go. Understand state machines and business rules.- See: Domain Model
-
Request flow —
cmd/api-server/main.go->internal/app/bootstrap/api_server.go->internal/api/router.go->internal/api/middleware.go-> handlers -> services -> repositories. -
Workflows —
internal/workflows/provision.go,internal/activities/. Understand the Temporal orchestration pattern.- See: Workflows
-
Upgrade rollout —
internal/workflows/rollout.go,internal/opsagent/upgrade/. Understand three-level workflow hierarchy and agent-side three-layer architecture. -
Agent communication —
proto/agent.proto,internal/grpc/server.go,cmd/ops-agent/main.go. Understand bidirectional gRPC communication. -
Health monitoring —
internal/health/leader.go->internal/health/machine.go->internal/health/heartbeat.go->internal/health/outbox.go->internal/incident/service.go->internal/incident/notifier/. Uptime:internal/uptime/state_log_handler.go->internal/uptime/worker.go.- See: Health and Incidents
-
Chain configuration —
hoodcloud-chain-configs/chains/. Understand the declarative, chain-agnostic approach.
Key Files
Payment Service Key Files
Common Patterns
Repository Pattern
All database interactions use repositories defined ininternal/contracts/repository.go, implemented in internal/database/. Isolates SQL from business logic, testable with mocks.
Service Layer
Services ininternal/service/ coordinate between repositories and external systems. Encapsulates business rules, orchestrates operations.
Temporal Workflows
Durable orchestrations ininternal/workflows/. Survive process restarts, automatic retries, compensation on failure. Activities in internal/activities/ are idempotent.
Declarative Configuration
Chains defined in YAML (hoodcloud-chain-configs/), not code. Observation collectors, health policies, and recipes are all configuration-driven.
Event-Driven Architecture
All state transitions and dimension changes emit events viahealth_event_outbox:
Graceful Degradation
Optional services degrade gracefully — NATS, telemetry, and other optional subsystems fall back to no-op implementations on initialization failure.Error Handling
Error Types and Handling
Workflow Error Propagation
internal/workflows/provision.go (compensate()), internal/workflows/migrate.go (compensateMigration()).
HTTP Error Responses
Temporal Retry Policies
Tracing Code Paths
”How does a node get marked as DOWN?”
- Health evaluator leader fires every 30s (leader-gated via advisory lock) ->
ListSnapshots()(3-way JOIN, includesstate_version) EvaluateHeartbeat()per node — pure function, no I/O. If heartbeat timed out: incrementConsecutiveFailures. If>= ConsecutiveFailuresForDown(3): return transition to DOWN.NodeHealthMachine.ApplyHeartbeatDecisions()— batch update with optimistic locking on bothnode_health_state.versionandnodes.state_version. InsertsHealthTransitionEventintohealth_event_outbox.OutboxWorker(NOT leader-gated, usesFOR UPDATE SKIP LOCKED) dispatches toCompositeTransitionHandler-> incident service createsnode_downincident -> migration handler evaluates grace period and cooldown, triggers migration with deterministic workflow ID (migrate-node-{nodeID}-{healthStateVersion}).
”How does a node get upgraded?”
- Operator creates rollout via
POST /api/v1/rollouts— either withupgrade_id(auto mode: manifest auto-populates binary details, state compatibility, config changes) or with all fields explicit (manual mode) - Operator starts rollout via
POST /api/v1/rollouts/{id}/start RolloutWorkflowlaunched in Temporal →ResolveRolloutTargetsassigns nodes to batches- Per batch: launches
UpgradeNodeWorkflowchildren in parallel UpgradeNodeWorkflow:PreCheckNode→UpdateNodeState(maintenance)→SendUpgradeCommand- Agent receives
COMMAND_TYPE_UPGRADE(value 9) in heartbeat → executor runs 8 actions viaRuntimeAdapter WaitForCommandCompletion→UpdateNodeBinaryVersion→WaitForHealthValidation→UpdateNodeState(syncing)- On failure: agent runs per-action compensation (reverse order), workflow marks node
failed/rolled_back
”How does uptime get computed?”
- State transition emitted by
NodeHealthMachine->health_event_outbox OutboxWorkerdispatches toCompositeTransitionHandler->StateLogHandler.OnTransition()closes previousnode_state_logentry, inserts new entryUptimeWorker(5min cycle) finds last complete bucket per node, computes hourly buckets fromnode_state_logentries, upserts intonode_uptime_hourly- API request:
UptimeServicequeriesnode_uptime_hourlywithSUM(uptime_seconds)/SUM(total_seconds)over requested window
”How does an agent send a heartbeat?”
- Agent heartbeat loop (15s) ->
sendHeartbeat() - gRPC
ControlPlaneService.Heartbeat()with node_id - Control plane updates
agent_registrations.last_seen_at, returns pending commands from Redis queue - Agent executes commands, reports results via
ReportEvent()
Debugging Tips
Database Migrations
Migrations are handled by the dedicatedcmd/migrate binary, not at service startup. Run as a pre-deploy step:
Leader Election
Logging
Database Guardrails
Per-service connection pools and statement timeouts are configured to prevent resource exhaustion:
Observability: A pgx query tracer emits
db_query_duration_seconds histograms per service. Statement timeout errors are counted via db_statement_timeout_total.
Database Queries
Distributed Traces (Tempo)
WhenOTEL_ENABLED=true:
- Open Grafana -> Explore -> Tempo
- Search by service name or trace ID
- TraceQL queries:
{resource.service.name="api-server"},{status=error}
Temporal Workflows
- Open Temporal UI:
http://localhost:8233 - Search for workflow ID:
provision-{uuid} - View execution history (activities, retries, errors)
Redis Command Queue
NATS Streams
Victoria Metrics
Terraform State
Status Page (Gatus)
http://localhost:8081 — health dashboard for all services, infrastructure, and observability stack.
Running Tests
Unit Tests
Integration Tests
Uses testcontainers (Docker required):repository_test.go (NodeRepository CRUD, state transitions), commandqueue_test.go (ProgressStore, stall detection).
E2E Tests
Requires full Docker Compose environment:Payment Service Tests
Related Documents
- Overview — System overview, tech stack, service descriptions
- Domain Model — Domain objects, state machines, business rules
- Workflows — HTTP flow, Temporal workflows, provisioning inputs
- Health and Incidents — Health evaluation, incidents, notifications
- Payment Service — Payment architecture
- Extending — Extension points, adding new capabilities
- Environment Variables — Configuration reference
- Deployment and Operations — Local dev, operations