Expand description
Repeat suppression: a session that already asked about a ref, and was told something a retry cannot change yet, is not sent back to the network for the same answer (#507, ADR-0057).
The rate cap bounds how fast doiget asks. It did not bound how often it
asks the same thing: an agent retrying 500 refused DOIs ten times each is
5,000 requests without ever exceeding 5/s. The provenance log already
records, per call, what the caller was told (session_end rows carry
ref and error_code, #507 step 1), so the data to answer “has this
session been told this already?” exists before the network is touched.
RepeatIndex is that answer, fed from the log as it is written.
Scope, and why each bound is what it is:
- One session: a
doiget serveprocess, or one CLI run (batch). The capability profile is fixed for its lifetime, so “the configuration has not changed” holds by construction – except forconfig.toml, which the HTTP client reads per call. Each entry therefore carries a fingerprint of that file, and a changed file lifts the replay. - By disposition (ADR-0055):
terminalandneeds_configanswers are replayed forREPLAY_WINDOW; aretry_afteranswer is let through onceRETRY_AFTER_GAPhas passed and refused with the true remaining time before that. Backoff keeps working; hammering does not. - Never silent: a replay is an error the caller can see is a replay, with the time of the original answer.
- Always overridable by the caller, never by configuration:
forceon the request asks anyway, and the log records that it did. There is no setting that turns suppression off, which is what LEGAL.md 6a’s “cannot be overridden by configuration” requires of a safeguard.
Structs§
- Repeat
Index - Recent answers, per ref, for one session.
Enums§
- Verdict
- What a new request for a ref should do.
Constants§
- REPLAY_
WINDOW - How long a
terminalorneeds_configanswer is replayed. - RETRY_
AFTER_ GAP - The minimum gap before a
retry_afteranswer is asked again.
Functions§
- config_
fingerprint - A hash of
config.toml’s bytes, or 0 when there is none. Read per call: it is the one input the HTTP client re-reads within a session. The read is acrate::store::blocking_section, as store reads are, since it runs inside every fetch (#649 review).