Files
dbx/CLAUDE.md
Aleksey Shakhmatov 2c9af28548
Some checks failed
CI / test (push) Failing after 13s
Add production features: slog adapter, scan helpers, slow query logging, pool stats, tracer passthrough, test tx isolation
- slog.go: SlogLogger adapts *slog.Logger to dbx.Logger interface
- scan.go: Collect[T] and CollectOne[T] generic helpers using pgx.RowToStructByName
- cluster.go: slow query logging via Config.SlowQueryThreshold (Warn level in queryEnd)
- stats.go: PoolStats with Cluster.Stats() aggregating pool stats across all nodes
- config.go/node.go: NodeConfig.Tracer passthrough for pgx.QueryTracer (OpenTelemetry)
- options.go: WithSlowQueryThreshold and WithTracer functional options
- dbxtest/tx.go: RunInTx runs callback in always-rolled-back transaction for test isolation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:19:26 +03:00

2.9 KiB

CLAUDE.md — dbx

Commands

go build ./...                          # compile
go test ./...                           # all tests
go test -race ./...                     # tests with race detector
go test -v -run TestName ./...          # single test
go vet ./...                            # static analysis

Architecture

  • Module: git.codelab.vc/pkg/dbx, Go 1.24, depends on pgx/v5
  • Single package dbx (+ dbxtest for test helpers)

Core patterns

  • Cluster is the entry point — connects master + replicas, routes writes to master, reads to replicas with master fallback
  • Routing is method-based: Exec/Query/QueryRow/Begin/BeginTx/CopyFrom/SendBatch → master; ReadQuery/ReadQueryRow → replicas
  • Retry with exponential backoff + jitter, node fallback; retrier.do() iterates nodes then backs off
  • Balancer interface (Next([]*Node) *Node) — built-in RoundRobinBalancer skips unhealthy nodes
  • Health checker — background goroutine pings all nodes on an interval, flips Node.healthy atomic bool
  • RunTx — panic-safe transaction wrapper: recovers panics, rolls back, re-panics
  • Querier injectionInjectQuerier/ExtractQuerier pass Querier via context for service layers
  • SlogLogger — adapts *slog.Logger to the dbx.Logger interface (slog.go)
  • Collect/CollectOne — generic scan helpers using pgx.RowToStructByName (scan.go)
  • Slow query loggingConfig.SlowQueryThreshold triggers Warn-level logging in queryEnd
  • PoolStatsCluster.Stats() aggregates pool statistics across all nodes (stats.go)
  • Tracer passthroughNodeConfig.Tracer / WithTracer sets pgx.QueryTracer for OpenTelemetry
  • RunInTx — test helper that runs a callback in an always-rolled-back transaction (dbxtest/tx.go)

Error classification

  • IsRetryable(err) — connection errors (class 08), serialization failures (40001), deadlocks (40P01), too_many_connections (53300)
  • IsConnectionError(err) — PG class 08 + string matching for pgx-wrapped errors
  • IsConstraintViolation(err) — PG class 23
  • PgErrorCode(err) — extract raw code from *pgconn.PgError

Conventions

  • Struct-based Config with defaults() method (not functional options for NewCluster constructor, but Option type exists for ApplyOptions in tests)
  • Functional options (Option func(*Config)) used via ApplyOptions (e.g., in dbxtest)
  • stdlib-only tests — no testify, no gomock
  • atomic.Bool for thread safety (Node.healthy, Cluster.closed)
  • dbxtest.NewTestCluster skips tests when DB unreachable, auto-closes via t.Cleanup
  • dbxtest.TestLogger writes to testing.T for test log output
  • dbxtest.RunInTx runs a callback in a transaction that is always rolled back

See also

  • AGENTS.md — universal AI agent guide with common tasks, gotchas, and ASCII diagrams