Skip to content

Mechanical fixes from full framework review#1

Merged
datariot merged 9 commits into
mainfrom
fix/mechanical-review-fixes
Jul 6, 2026
Merged

Mechanical fixes from full framework review#1
datariot merged 9 commits into
mainfrom
fix/mechanical-review-fixes

Conversation

@datariot

@datariot datariot commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Lands the mechanical fixes from the goals/idioms/efficiency review.

Correctness

  • Shutdown timeout was a no-op: break inside select never exited the hook loop; hooks kept executing with a dead context, double-counting errors and leaking goroutines. Now stops at timeout and reports skipped hooks. Error aggregation via errors.Join.
  • HTTP bind failures were invisible: ListenAndServe errors were only logged in a goroutine; Start now binds synchronously and fails fast, matching the gRPC path.

Health system

  • Background check runner honors the previously dead CheckConfig.Interval/InitialDelay; probe endpoints serve cached results so a hanging dependency can never stall kubelet probes. Live-computation fallback preserved when the runner isn't started.
  • /health built from one snapshot read instead of two serialized live rounds; Redis readiness reduced from 5 round-trips (incl. writes) to a single PING.
  • gRPC health service re-synced from cached results every 5s instead of a one-shot startup snapshot.

Config actually applied

  • gRPC max recv/send sizes and connection timeout from BaseConfig are now passed to the server (were validated but ignored).
  • New WithHTTPServerConfig option makes HTTPServerConfig reachable; unimplemented LogRequestBody/LogResponseBody fields removed; Build() returns validation errors instead of swallowing them.
  • OTELEndpoint defaults to empty — default-config services no longer dial a dead localhost collector forever.

Error handling idioms

  • errors.Is/errors.As for sentinels (gobreaker, redis.Nil, http.ErrServerClosed, net.Error); retry exhaustion preserves the root cause and distinguishes context cancellation; new exported redis.ErrCacheMiss sentinel; constant-string fmt.Errorferrors.New sweep.

Hygiene

  • gofmt across the tree (30 files); all example modules go mod tidy'd so they build (un-breaks the CI examples step); compiled example binaries gitignored (already purged from history).
  • README/doc.go truth pass: Quick Start now compiles against the real API; claimed-but-unbuilt features (Redis Streams, transaction patterns) replaced with what actually ships; dead links removed.

Full suite passes locally with -race.

🤖 Generated with Claude Code

datariot and others added 9 commits July 6, 2026 08:31
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…amework

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- shutdown: stop executing hooks after timeout (break-in-select bug), aggregate with errors.Join
- observability: return all shutdown errors via errors.Join instead of first only
- app: apply configured gRPC max msg sizes and connection timeout; bind HTTP listener synchronously so port conflicts fail Start
- http: Build returns error on invalid config; WithHTTPServerConfig option makes HTTPServerConfig reachable; drop unimplemented LogRequest/ResponseBody fields; precompute CORS header joins
- config: default OTELEndpoint to empty so default services don't dial a dead collector

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- httpclient: preserve root cause in retry exhaustion (%w: %w), surface context cancellation distinctly, errors.Is for gobreaker sentinel, errors.As for net.Error, errors.New for constant sentinels
- redis: exported ErrCacheMiss sentinel with errors.Is(redis.Nil) detection; readiness check reduced from 5 round-trips (incl. writes) to a single PING
- jwt/configloader/prometheus: constant-string fmt.Errorf -> errors.New sweep

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- registry: Start/Stop lifecycle runs each check on its configured Interval/InitialDelay, caching results; probe endpoints serve the cached snapshot so a hanging dependency can never block kubelet probes
- registry: live-computation fallback preserved when runner not started (library/test use); /health built from one snapshot read instead of two serialized live rounds; typed probe dispatch replaces stringly liveness/readiness switch
- app: registry runner started after bundle registration, stopped on shutdown; gRPC health service now re-synced from cached results every 5s instead of a one-shot startup snapshot

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…view-fixes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Quick Start now compiles: two-value framework.New, real postgresql.NewBundle(config)
- drop claimed-but-unbuilt features (Redis Streams event publishing, transaction patterns) in favor of what ships
- remove phantom Adapters layer; fix dead doc links; clarify env config comes via configloader bundle; note gRPC server is registrar-gated

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CI lint job was failing since April: golangci-lint v1.55.2 (Go 1.21) cannot typecheck a Go 1.25 module; switch to golangci-lint-action@v8 pinned to v2.12.2
- errcheck: handle or explicitly ignore all unchecked Close/Write/Stop/Register returns (prod code returns/logs where meaningful; tests assert)
- staticcheck: drop deprecated PreferServerCipherSuites, De Morgan simplifications, single-case select to plain receive, nil ctx -> context.TODO in tests, error string casing
- unused: remove dead configloader Bundle.mu field

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@datariot datariot merged commit d19cd25 into main Jul 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant