Files
homelab-frontend/tasks/0.1-module-and-entrypoint.md
T
Story Crater BotandClaude Opus 5 058f11cf2b
CI / Test (push) Canceled after 0s
CI / Vet (push) Canceled after 0s
CI / Build (push) Canceled after 0s
CI / Security (govulncheck) (push) Canceled after 0s
chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working
tree under version control for the first time: gateway source, the task
board that drives the agent runs, test fixtures, and K8s manifests.

Anchor the gateway ignore rule to the repo root. Unanchored, "gateway"
also matched the cmd/gateway/ source directory, so the program entrypoint
was excluded from every commit.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-19 20:54:34 -07:00

1.6 KiB

0.1 — Module and entrypoint (GREEN)

Phase: 0 — Foundations Stage: GREEN

  • A single Go module builds one static binary with no cgo
  • The binary reads its configuration at startup and serves HTTP on a configurable listen address
  • SIGTERM starts a drain: the listener stops accepting new connections, in-flight requests run to completion, then the process exits 0
  • A request already in flight when SIGTERM arrives receives its full, uncorrupted response body
  • A request arriving after SIGTERM is not accepted on a new connection
  • The drain has a bounded deadline; exceeding it forces exit with a non-zero code and a logged reason
  • The process holds no Kubernetes credentials and makes no API-server calls

The gateway sits behind ingress-nginx, which owns TLS. The gateway never terminates TLS and never listens on 443. Graceful drain matters because in-flight requests here are LLM generations that can legitimately run for many minutes -> killing them mid-stream loses work a caller cannot cheaply redo.

Verify

go test ./internal/server/... -run TestGracefulShutdown -race -v
# expected: passes — a slow in-flight request completes with a full body after SIGTERM,
# and a request issued post-SIGTERM is refused; process exit code is 0

CGO_ENABLED=0 go build ./... && go vet ./...
# expected: both succeed

-race is required, not optional. A server that starts a listener in one goroutine and exposes its address from another is the obvious shape here, and it is racy unless the shared state is guarded. A test that passes without -race proves nothing about it.