Architecture¶
indexnow/
├── cmd/indexnow/main.go # cobra wiring, ENV defaults, exit-code plumbing
└── internal/
├── cli/ # logic in a testable form (no cobra deps)
│ ├── submit.go # RunSubmit, URL collection, output rendering, fail-on
│ └── errors.go
└── client/ # IndexNow HTTP client
├── client.go # Submit / SubmitBatch, retry loop, payload marshalling
├── endpoints.go # alias → URL resolution
├── retry.go # backoff / jitter math
└── errors.go
Separation of concerns¶
cmd/indexnowowns cobra and OS plumbing only: flag definitions, signal handling, ENV fallbacks, mappingcli.Exit*to process exit codes.internal/cliowns the CLI behavior in a form that is testable without spawning a binary:RunSubmit(ctx, opts, stdin, stdout, stderr, factory) int. Inputs are read fromio.Reader, output fromio.Writer, the HTTP client is provided viaSubmitterFactory— so tests don't need a network.internal/clientowns the IndexNow wire format and retry policy. Concurrency-safe; configured viaclient.Config.
Retry policy¶
The client retries on HTTP 429, 5xx, and transport errors. Backoff is exponential with jitter, bounded by BaseBackoff and MaxBackoff. Retry-After is parsed as both seconds and HTTP-date. Each Result carries the final StatusCode, Attempts, the URLs in the batch, and the terminal error (if any).
Batching¶
SubmitBatch splits its input at MaxBatchSize = 10000 (protocol limit) and emits one Result per HTTP call, in submission order.