33 lines
1.6 KiB
Markdown
33 lines
1.6 KiB
Markdown
# 0.1 — Module and entrypoint (GREEN)
|
|||
|
|
|
||
|
|
Phase: 0 — Foundations
|
||
|
|
Stage: GREEN
|
||
|
|
|
||
|
|
- [x] A single Go module builds one static binary with no cgo
|
||
|
|
- [x] The binary reads its configuration at startup and serves HTTP on a configurable listen address
|
||
|
|
- [x] `SIGTERM` starts a drain: the listener stops accepting new connections, in-flight requests run to completion, then the process exits `0`
|
||
|
|
- [x] A request already in flight when `SIGTERM` arrives receives its full, uncorrupted response body
|
||
|
|
- [x] A request arriving after `SIGTERM` is not accepted on a new connection
|
||
|
|
- [x] The drain has a bounded deadline; exceeding it forces exit with a non-zero code and a logged reason
|
||
|
|
- [x] 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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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.
|