Skip to content

feat(presence)!: talk to service-player over HTTP - #33

Merged
hbrombeer merged 1 commit into
mainfrom
feat/rest-client
Aug 4, 2026
Merged

feat(presence)!: talk to service-player over HTTP#33
hbrombeer merged 1 commit into
mainfrom
feat/rest-client

Conversation

@hbrombeer

Copy link
Copy Markdown
Member

service-player now publishes a REST API under /v1/players (service-player#99, released as v0.9.0 and documented in the reference). It keeps its gRPC contract only until its callers move; this is one of the two.

What changes

GrpcPlayerPresenceClientHttpPlayerPresenceClient, using the JDK's HttpClient and Jackson — the pair ForgeLinkClient already uses, so nothing new lands in the shaded jar and grpc-netty-shaded leaves it. common drops the protobuf contract and moves from grpc-conventions to kotlin-conventions.

Protobuf types no longer cross into the plugin. Presence speaks its own models (PlayerSessionInfo, PlayerLoginResult, PlayerLogoutResult, …), which is what lets the login outcome be a sealed result rather than a status enum PlayerConnectionListener had to re-interpret — handleSuccess and its LoginStatus when are gone.

was is
TryPlayerLogin POST /v1/players/sessions — 201 accepted, 409 already online
PlayerLogout DELETE /v1/players/{id}/session?proxyId=
PlayerHeartbeatBatch POST /v1/players/sessions/heartbeats
GetPlayerSession GET /v1/players/{id}/session
ResolvePlayerName GET /v1/players/sessions?name=
UpdatePlayerServer PUT /v1/players/{id}/session/server
SuggestPlayerNames GET /v1/players/names/suggestions
CountPlayersBy{Server,Proxy} GET /v1/players/counts/{servers,proxies}
Get/SetPlayerLocale GET/PUT /v1/players/{id}/locale

Behaviour

Unchanged where it matters: nothing throws, every lookup still resolves a failure into "unknown" so an exception never reaches Velocity's event loop, the 2s deadline is kept, and logout stays scoped to the calling proxy so it cannot undo a transfer.

One difference worth naming: a login the service could not answer is now Unavailable rather than a reply carrying an error status, so the proxy denies with the service unavailable message instead of the generic one. It could not ask — saying so beats implying the player did something wrong.

Breaking

PLAYER_PRESENCE_GRPC_TARGETPLAYER_SERVICE_URL. The scheme may be omitted, matching how the deploy sets the other service URLs. A proxy without it fails at startup rather than at the first login, so the deploy must set it in the same change that ships this jar.

Verification

./gradlew spotlessCheck build — 32 tests, 0 failures. The client's 17 cover the status-code mapping (201/409/400/5xx), an unreachable service, absent fields, the proxy-scoped logout, and the token header, against a real loopback HTTP server.

service-player publishes a REST API under /v1/players (service-player#99) and
keeps its gRPC contract only until its callers move. This is one of the two.

The client drops gRPC for the JDK's HttpClient and Jackson — the pair
ForgeLinkClient already uses, so nothing new lands in the shaded jar and
grpc-netty-shaded leaves it. Protobuf types no longer cross into the plugin
either: presence now speaks its own small models, which is what lets the login
outcome be a sealed result instead of a status enum the listener had to
re-interpret.

One behavioural difference worth naming: a login the service could not answer is
Unavailable rather than a reply with an error status, so the proxy denies with
"service unavailable" instead of the generic message. It could not ask, and
saying so is more useful than implying the player did something wrong.

BREAKING CHANGE: PLAYER_PRESENCE_GRPC_TARGET is replaced by PLAYER_SERVICE_URL.
The deploy must set it in the same change that ships this jar; a proxy without it
fails at startup rather than at the first login.
@hbrombeer
hbrombeer merged commit 3716964 into main Aug 4, 2026
3 checks passed
@hbrombeer
hbrombeer deleted the feat/rest-client branch August 4, 2026 15:12
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.

1 participant