Skip to content

feat: Add providerMode to get-and-persist player#308

Merged
Amund211 merged 1 commit into
mainfrom
feat/player-provider-mode
Jul 11, 2026
Merged

feat: Add providerMode to get-and-persist player#308
Amund211 merged 1 commit into
mainfrom
feat/player-provider-mode

Conversation

@Amund211

Copy link
Copy Markdown
Owner

Why

We're seeing a lot of bot traffic on the playerdata endpoints, which is burning through our Hypixel API rate limit. This adds a providerMode to the get-and-persist player flow so we can serve players from our own stats DB instead of always hitting Hypixel.

What

Adds a providerMode parameter to GetAndPersistPlayerWithCache with three allowed values. The value is validated on receipt — an invalid value is reported (Sentry) and returns an error.

  • always — query the provider (Hypixel) for fresh data and persist it. Original behaviour.
  • fallback — return the most recent stored stats when we have them, only querying the provider when we have no stored stats for the player. The stats DB does not store usernames, so the displayname is resolved separately: we check our own account store first and only fetch (Mojang) when it isn't stored.
  • never — never query the provider. If the player isn't stored, the request fails with a 500 (a generic error, not ErrPlayerNotFound, so it does not map to 404).

Supporting changes:

  • New PlayerRepository.GetPlayer(ctx, uuid) returning the most recently stored PlayerPIT, or domain.ErrPlayerNotFound. Implemented for the Postgres repo and the stub.
  • BuildGetAndPersistPlayerWithCache now takes the account repo + GetAccountByUUID use case for db-first username resolution; main.go wiring reordered accordingly.
  • The return-count metric gains a low-cardinality provider_mode attribute.
  • The cache key now includes the mode so different modes don't serve each other's (differently-sourced) results.

All callers currently pass fallback (playerdata port, milestone/prestiges, and the updatePlayerInInterval path used by history/sessions/session-at/wrapped), as requested for the initial rollout.

Tests

  • New app-layer tests covering each mode: fallback served-from-DB (no provider call) with username resolution from the account store and via fetch, fallback-to-provider on cache/DB miss, never served-from-DB, never-fails-without-provider, and invalid-mode.
  • New Postgres GetPlayer tests (most-recent selection, ErrPlayerNotFound, un-normalized UUID).
  • Existing tests updated for the new signature. Full suite + golangci-lint pass.

🤖 Generated with Claude Code

Add a providerMode parameter ("always", "fallback", "never") to
GetAndPersistPlayerWithCache to control whether we query the Hypixel
provider. This lets us serve players from our own stats DB and cut down
on Hypixel API usage, which bot traffic has been exhausting.

- always:   query the provider for fresh data and persist it (original
            behaviour).
- fallback: return the most recent stored stats when we have them, only
            querying the provider when we have no stored stats. Since the
            stats DB does not store usernames, the displayname is resolved
            separately from our account store, falling back to a fetch
            when it isn't stored.
- never:    never query the provider; if the player isn't stored the
            request fails (500).

The mode is validated on receipt and an invalid value is reported and
errors out. A new PlayerRepository.GetPlayer returns the most recent
stored PlayerPIT (or ErrPlayerNotFound). All callers currently pass
"fallback".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 11, 2026 23:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a providerMode parameter to the get-and-persist player flow so callers can prefer serving player stats from the local stats DB (and only hit external providers when needed), reducing Hypixel API usage and rate-limit pressure.

Changes:

  • Add ProviderMode (always / fallback / never) to GetAndPersistPlayerWithCache, including validation, metrics labeling, and mode-specific cache keys.
  • Add PlayerRepository.GetPlayer(ctx, uuid) to retrieve the most recently stored PlayerPIT (or domain.ErrPlayerNotFound) with Postgres + stub implementations and tests.
  • Update wiring and callers to pass fallback, and add/adjust tests to cover new behavior.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
main.go Reorders wiring so GetAndPersistPlayerWithCache can use account lookups for DB-first username resolution.
internal/ports/player_data.go Updates handler to call GetAndPersistPlayerWithCache with ProviderModeFallback.
internal/ports/player_data_test.go Updates port tests for new providerMode parameter.
internal/app/milestone.go Uses ProviderModeFallback for milestone flow to reduce provider calls.
internal/app/milestone_test.go Updates tests to assert ProviderModeFallback is passed through.
internal/app/get_and_persist.go Implements provider-mode behavior, mode-specific cache keys, and DB-first displayname resolution.
internal/app/get_and_persist_test.go Adds new tests covering all provider modes and invalid mode handling.
internal/adapters/playerrepository/repository.go Adds Postgres + stub GetPlayer implementation selecting most recent stats row.
internal/adapters/playerrepository/repository_test.go Adds Postgres GetPlayer tests (most-recent, not-found, invalid uuid).
internal/adapters/playerrepository/interface.go Extends repository interface with GetPlayer contract documentation.

Comment thread internal/app/get_and_persist.go
@Amund211 Amund211 merged commit 1c01756 into main Jul 11, 2026
10 checks passed
@Amund211 Amund211 deleted the feat/player-provider-mode branch July 11, 2026 23:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants