Repository navigation
X2: mokkari 4.8.0 + full-size candidate cover url - #218
Merged
Merged
Conversation
… url mokkari 4.8.0 shipped all three upstream asks from tasks/metron-rate-limit-plan.md. U1 (#167) — `Session(rate_limiter=...)`. comicbox's `PacedSession` subclass, which overrode the private `_execute_http_request` and disabled `_check_rate_limit`, collapses to `GateRateLimiter`: a registration through the public hook. `RateGate` stays rather than mokkari's `HeaderPacedRateLimiter`; the paced_session module docstring has the point-by-point comparison so nobody "simplifies" it later. One private reach remains, `Session._http`, for the per-endpoint and header-less telemetry the hook cannot see -- a `requests` response hook, which also keeps the observe/cooldown/release order the override had. U2 (#168) — bounded pagination 429 retries. With a limiter set a page is retried through it without sleeping, so a paginated call now waits on the gate's rebuilt window, and a spent daily quota aborts mid-pagination instead of being slept out. U3 (#169) — a pooled `requests.Session`: one TLS handshake per run instead of per request. `close_shared_sessions()` releases the pool at the end of a run and from the new `OnlineSession.close()` / context manager; an `os.register_at_fork` handler drops inherited sessions in a child rather than letting two processes share sockets. Also: - `CandidateSummary.cover_url_full` — display only; the matcher keeps hashing `cover_url`, because hashing a larger image moves every score. ComicVine picks largest-first and never falls back to a thumbnail tier; Metron's image is already full size. Zero API budget either way. - `RateLimiterError` classifies as INVALID, like `CacheError`. - `outcome_stats.record_gate_wait` splits the gate wait off the send, so `requests` counts responses received -- what the server's logs show. - Tests move off `mokkari.session.requests.request`, which intercepts nothing under 4.8.0, onto a `requests` adapter mounted on the pooled session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ajslater
added a commit
that referenced
this pull request
Sep 21, 2026
…re (#220) `make lint` has been exiting 2 since #218: vulture flags `stream`, `verify`, `cert` and `proxies` on both fake `BaseAdapter.send` overrides. The names cannot change. `requests.Session.send` calls `adapter.send(request, **kwargs)` with those exact keywords, so renaming them is a TypeError at runtime, and collapsing them into `**kwargs` fails basedpyright's override check (positional parameter count mismatch). So the signature stays and the body consumes them. `del` rather than a `vulture_ignorelist.py` entry: the whitelist matches by bare name across the whole tree, and `stream` / `verify` / `cert` / `proxies` are ordinary enough words that listing them would blind vulture to real dead code elsewhere. The existing `option_string` entry is safe there precisely because nothing else would ever be called that. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
comicbox 5.2.0, PR X2 of 2. Implements §6–§9 of
tasks/comicbox-5.2.0-plan.md. Independent of#217 (X1), which mints the
v5.2.0NEWS section this appends to.
mokkari 4.8.0
4.8.0
shipped all three upstream asks from
tasks/metron-rate-limit-plan.md,now ticked there.
U1 (#167) —
Session(rate_limiter=...)comicbox's
PacedSessionsubclass overrode the private_execute_http_requestand disabled_check_rate_limit. It collapses toGateRateLimiter: a registration through the public hook.PacedSessionis deleted.
RateGatestays; mokkari'sHeaderPacedRateLimiteris deliberatelynot adopted, and the module docstring now carries the point-by-point
comparison so nobody simplifies it later. The short version: the
reference limiter does not wait at all before the first response (N
threads burst), blocks every caller on a 429 instead of releasing one
per freed slot, has no
per_minuteceiling, no stats, and raises on thedaily window by comparing the server's epoch reset against the local
clock — the clock-drift trap the gate was designed around, and which
5.1.1's
Skipped(reason="quota_reserved")abort semantics depend on nothitting.
One private reach remains:
Session._http, for arequestsresponsehook. The
rate_limiterhook carries no URL, no status code and no rawheaders, and 5.1.2's telemetry — per-endpoint counts and "responses
without rate-limit headers, by status", reported to Metron's maintainer —
needs all three. The hook fires inside
_http.request, which preservesthe old override's observe → cooldown → release order. Pacing no longer
depends on any private seam. A public accessor is filed as follow-up U7;
per the repo's convention I have not offered upstream a patch.
U2 (#168) — bounded pagination 429 retries
With a limiter set, a 429 mid-pagination retries the page through the
limiter without sleeping, so the wait is the gate's rebuilt window
rather than two stacked delays. No comicbox code compensated for the old
unbounded loop, so nothing was deleted. Two consequences are now tested:
the retry does not call
mokkari.session.time.sleep, and a spent dailyquota (
RateGate.acquire→OnlineLookupAbortedError, not aRateLimitError) propagates out of a paginated call instead of beingswallowed — the 5.1.1 abort semantics now hold mid-pagination too.
U3 (#169) — pooled
requests.SessionOne TLS handshake per run instead of per request. Two consequences
handled:
close_shared_sessions()releases the pool at the end of everyRunner.run()(read out ofsys.modules, so an offline run still neverimports mokkari) and from the new
OnlineSession.close()/ contextmanager; and an
os.register_at_forkhandler drops inherited sessions ina child, rebinding the lock rather than taking it — the thread that held
it at fork time does not exist in the child.
CandidateSummary.cover_url_fullDisplay only. The matcher keeps hashing
cover_url: hashing a largerimage moves every score and would need a fresh calibration run.
original_url→medium_url) andnever falls back to
small_urlorthumbnail— a record with onlythose tiers has nothing larger to show, and
Noneis what a frontendkeys "no hover" on.
and both are
Nonewith no image.Imagesvariants ride in the searchresponse comicbox already paid for.
Accounting change
record_http_requestloses itsblocked_secondsparameter; the gatewait comes in on the new
record_gate_wait._ApiCounts.requestsnowcounts responses received, which is what the server's own logs show;
a send that never answered appears only under
connection_failures,where it used to be double-counted under its endpoint too.
Test migration
Every test that patched
mokkari.session.requests.requestwasintercepting nothing under 4.8.0 — sends go through
Session._http. Theynow mount a
requests.adapters.BaseAdapter(newtests/util/metron_transport.py), which runs the whole real stack:requests.Session.send, comicbox's response hook, mokkari's cookiepolicy and the pool, exactly as production does.
Verification
make lint→ 0 errors, 0 warnings, 0 notesmake ty→ All checks passed!make complexity→ no functions over 15; radoncc --min Candmi --min Bboth silentuv.lockresolvesmokkari 4.8.0. CI reportsskippingon PRs intodevelopby design; the local sequence above is the verification.Deliberate non-adoption
HeaderPacedRateLimiter(above); even spacing of sends (the gate'ssliding log is already exact to DRF's, and spacing would slow small
batches for nothing);
Session.last_cache_status(diagnostic only,unchanged from the 4.6.0 audit).
Public surface codex Wave 2 imports
CandidateSummary.cover_url_full,OnlineSession.close().🤖 Generated with Claude Code