Skip to content

Commit ffe8f34

Browse files
committed
docs: add AGENTS.md codebase map
1 parent f7c9319 commit ffe8f34

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# AGENTS.md — codebase map for AI agents
2+
3+
Read this first. Orientation map for `ubgo/shutdown` so a fresh agent knows what every part does and where to change things, without reading every file.
4+
5+
## What this repo is
6+
7+
`ubgo/shutdown` is a **phased, parallel-within-phase, observable graceful-shutdown manager** for Go services. You register named handlers (and "actors" — long-running goroutines) into ordered phases; on a signal (or a programmatic trigger) the `Manager` runs each phase in order, handlers within a phase in parallel, with per-handler timeouts, an overall budget, a watchdog hard-exit, force-exit on a second signal, error aggregation, and observer hooks for telemetry. The core has **zero third-party dependencies**; framework/telemetry integrations live in `contrib/`. See `README.md` for the pitch, `doc.go` for the package overview.
8+
9+
## Modules
10+
11+
| Path | Module | Role | Deps |
12+
|---|---|---|---|
13+
| `.` | `github.com/ubgo/shutdown` | Core manager. | stdlib only (a `zero-dep-check` CI gate enforces this) |
14+
| `contrib/shutdown-{nethttp,gin,chi,echo,fiber}` | each own module | HTTP-server shutdown adapters. | the target framework |
15+
| `contrib/shutdown-{otel,prom,zap}` | each own module | Observer/Logger adapters for OpenTelemetry, Prometheus, zap. | the target lib |
16+
17+
Go 1.24. Each contrib is a separate module so the core stays dependency-free.
18+
19+
## Core files — what each owns
20+
21+
| File | Responsibility |
22+
|---|---|
23+
| `doc.go` | Package overview godoc. |
24+
| `types.go` | `HandlerFunc`, `Phase` (+ the predefined phase constants), `ErrorPolicy`, `Logger` interface, `Observer`, `RunFunc`/`InterruptFunc`. |
25+
| `manager.go` | `Manager` — the central coordinator: `New`, `Register`, `Subscribe`, `Listen` (signal-driven), `Shutdown` (programmatic), `OnSignal`. |
26+
| `register.go` | `Register`/`RegisterOption` (`WithPhase`, `WithTimeout`, …) and the internal `registration`. |
27+
| `runner.go` | Phase execution: parallel-within-phase by default, serial when opted in; per-handler ctx = min(handler timeout, remaining budget); error aggregation. |
28+
| `actor.go` | "Actors" — register a long-running `RunFunc` + `InterruptFunc` pair that the manager interrupts and waits for, unified into the same phase machinery. |
29+
| `watchdog.go` | The hard-exit safety net: after budget + grace, `os.Exit` with the stuck-handler names logged. |
30+
| `observer.go` | Observer fan-out (`OnSignal`/`OnPhaseStart`/`OnHandlerEnd`/`OnComplete`, …) consumed by `contrib/shutdown-otel`/`-prom`. |
31+
| `options.go` | `Option` / `config``WithBudget`, `WithLogger`, `WithSignals`, `WithForceOnSecondSignal`, `WithExitOnComplete`, `WithErrorPolicy`, `WithSerial`. |
32+
| `logger.go` | The minimal `Logger` interface's noop default (real loggers plug in via `WithLogger` / `contrib/shutdown-zap`). |
33+
34+
## The flow to understand
35+
36+
`manager.go:Listen` (or `Shutdown`) → sort registrations into phase buckets (`bucketsByPhase`) → for each phase ascending: fire `OnPhaseStart`, run handlers (`runner.go:runPhase`, parallel unless `WithSerial`), aggregate errors per `ErrorPolicy`, fire `OnPhaseEnd``OnComplete` with `errors.Join`. A second signal force-exits; the `watchdog` hard-exits if the budget is blown. Phases run logs/flush **last** by phase number so earlier errors are recorded.
37+
38+
## Conventions
39+
40+
- **Zero third-party deps in core** — the `zero-dep-check` task/CI gate fails if `go.mod` gains a non-stdlib require. Framework/telemetry code goes in `contrib/`.
41+
- **Race detector mandatory**; high coverage. `task ci` runs everything.
42+
- **No panics in libraries** — handlers' panics are recovered into a `PanicError` and surfaced in the aggregate.
43+
- Comments explain *why*, not *what*.
44+
45+
## Running
46+
47+
```sh
48+
task ci # fmt + vet + race tests + coverage + zero-dep-check
49+
task test:race
50+
task zero-dep-check
51+
```
52+
53+
## Where to look for X
54+
55+
- "Add a phase / change ordering" → `types.go` (phase constants) + `WithPhase` in `register.go`.
56+
- "Wire it to my HTTP framework" → `contrib/shutdown-<framework>`.
57+
- "Emit shutdown telemetry" → `observer.go` + `contrib/shutdown-otel` / `-prom`.
58+
- "Force-exit / watchdog behavior" → `manager.go` (`runShutdownWithForceWatch`) + `watchdog.go`.

0 commit comments

Comments
 (0)