docs(http): put the outbound-HTTP rule where contributors read it

Rule 11 in the standing rules, which is the file implementation.md tells you to
read before writing code. AGENTS.md alone is the hub, not the enforceable list,
and its External Integrations section is descriptive.

Also restores the call-volume half of the "follow rate limiting best practices"
line, named after the patterns that actually implement it rather than left as a
virtue, and rescopes the MAX_RATE_LIMIT_WAIT_MS comment: it now bounds every
outbound client, not just the notification agents.
This commit is contained in:
enoch85
2026-08-27 19:40:15 +00:00
parent 1197340647
commit e3bae2a693
3 changed files with 7 additions and 2 deletions
@@ -53,3 +53,4 @@ the spec does not:
8. Database/migrations: if persistence changes are needed, keep migrations safe, reversible, and edge-case aware. All migrations MUST be generated and run via TypeORM - never manually crafted SQL. You MUST always follow [typeorm_instructions.txt](../../typeorm_instructions.txt) for migration commands and workflow. A migration is NEVER considered working until it has been tested - run it end-to-end and verify the result before treating it as done.
9. Rules/metadata systems: make sure any cache invalidation approach stays consistent with existing getter/provider patterns.
10. Rule naming standards: preserve established rule `name` and `humanName` conventions for equivalent concepts across media servers. Do not rename user-facing rule labels to encode backend caveats; keep naming stable and document server-specific semantics in code comments and focused tests instead.
11. Outbound HTTP: every client goes through `ExternalApiService` or `applyHttpRetry` (`modules/api/lib/httpRetry.ts`) - never the bare global `axios`, which carries no retry policy at all, and never a per-client `axios-retry` config. The shared policy already answers a 429 with the wait the server declared, capped at `MAX_RATE_LIMIT_WAIT_MS`; anything hand-rolled beside it only drifts.
+3
View File
@@ -344,6 +344,9 @@ When working with these integrations:
per-client axios-retry config: it already answers a 429 with the wait the
server declared, capped, so hand-rolled rate-limit handling only drifts
- Implement caching where appropriate (node-cache)
- Prefer one batched call per run over one per item: see the Seerr request
prefetch (#3152), the batched collection writes, and the removal-notification
batching (#3500)
- Use TypeScript interfaces for external API responses
## External API Documentation
+3 -2
View File
@@ -1,8 +1,9 @@
import axios, { type AxiosError, type AxiosInstance } from 'axios';
import axiosRetry, { type IAxiosRetryConfig } from 'axios-retry';
// Past this the send would be held open too long, and on Discord count against
// its invalid-request ban threshold, so give up instead.
// Past this the request would be held open too long, and on Discord count
// against its invalid-request ban threshold, so give up instead. This bounds
// every outbound client, not just the notification agents.
const MAX_RATE_LIMIT_WAIT_MS = 60000;
const RETRY_PADDING_MS = 250;