Repository navigation
Hypixel key rate limiter + deploy volume-resolution fix - #21
Conversation
Adds a process-wide rolling-window rate limiter in front of the Hypixel client. Requests are counted on attempt (including ones that later time out), because those may still have reached Hypixel and consumed quota. Recovered from an uncommitted working tree on the production server. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…elimiter # Conflicts: # tests/test_marketguard_api.py
resolve_named_volumes() matched any host volume ending in the logical suffix, so a second Compose project owning e.g. proxy_caddy_data made the lookup ambiguous and aborted every deployment. COMPOSE_PROJECT_NAME was named in the error text but never actually read. Now the project name is resolved the way Compose resolves it (env var, env file, compose `name:`, then directory name) and a candidate matching `<project>_<logical>` wins. Unrelated stacks on the same host no longer block a deploy, and no volume has to be deleted to unblock one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a87c594af
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if not api_key: | ||
| raise HypixelUpstreamError("Hypixel player API is not configured.") | ||
|
|
||
| await _HYPIXEL_KEY_RATE_LIMITER.acquire() |
There was a problem hiding this comment.
Propagate limiter exhaustion from player lookups
Once /api/v1/players reaches 300 authenticated calls in the rolling window, this acquisition raises HypixelRateLimitError, but PlayerService.get_players() catches its HypixelUpstreamError superclass at player_service.py:70-72 and converts the affected lookups into status: "unavailable". Consequently the route's dedicated rate-limit handler at routes.py:322-329 is never reached: callers receive HTTP 200 without Retry-After, and the unavailable result is cached as a successful response. Re-raise HypixelRateLimitError before the generic upstream catch so exhaustion is surfaced as the documented temporary failure.
AGENTS.md reference: AGENTS.md:L74-L80
Useful? React with 👍 / 👎.
Brings the currently deployed production state back onto
main.What is in here
feat(marketguard): Hypixel API key quota, 300 requests / 5 min. A process-wide rolling-window limiter in front ofHypixelPlayerClient, the only client that sends anAPI-Keyheader. Requests are counted on attempt, including ones that later time out, because those may still have reached Hypixel and consumed quota. This code was found uncommitted on the production server and existed in no branch — recovering it is the main point of this PR.fix(deploy): scope named-volume lookup to this Compose project.resolve_named_volumes()matched any host volume ending in the logical suffix, so a second Compose project owningproxy_caddy_datamade every deployment abort with "Ambiguous Docker volumes". Its own error text suggestedCOMPOSE_PROJECT_NAME, which the script never read, and deleting "stale" volumes, which on this host would have wiped the master reverse proxy's TLS certificates. The project name is now resolved the way Compose resolves it, and<project>_<logical>wins.agent/document-optional-player-profile(player API test expectations, optional profile docs).origin/mainmerged in, so the MarketGuard snapshot-refresh fix,refresher.pyand thecryptographyCVE bump are included.Verification
/api/v1/readyreturnsstatus: ok,/login,/market/,/api/v2/lowestbin,/api/v1/bazaarand/openapi.jsonall 200.max_requests=300/window_seconds=300are live.One merge conflict was resolved in
tests/test_marketguard_api.py: same call, different kwarg order and dummy key. Kepttest-hypixel-key, the convention used ~10 times elsewhere in the file, over main's one-offtest-key. Functionally identical, that test does not assert the key value.🤖 Generated with Claude Code