Proof of Concept: Push Gateway decoding#371
Merged
Merged
Conversation
Adds updateRaidLobby method on Gym (pub-timestamp dedup guard), UpdateGymRaidLobby entry-point using minimal in-memory path (no DB write, no spam webhooks), and buildRaidLobbyWebhook helper. Unknown gyms are silently dropped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds updateBattleLobby method on Station (pub-timestamp dedup guard), UpdateStationBattleLobby entry-point using minimal in-memory path (no DB write, no spam webhooks), and buildMaxBattleLobbyWebhook helper. Unknown stations are silently dropped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds decodePushGateway dispatcher: gates on message_type before unmarshal (unknown types returned early), then routes raid/Max-battle lobby payloads to UpdateGymRaidLobby/UpdateStationBattleLobby. Wires push_contents iteration in grpc_server_raw.go and the push_contents JSON array in routes.go Raw handler. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a proto marshal/unmarshal round-trip test for RawProtoRequest with PushGatewayContent to guard against field number regressions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- routes.go: extend the contents-absent guard to also check len(pushItems)==0, so a push-only HTTP request (push_contents but no contents/nebula_contents) is no longer wrongly rejected with a 422 and its push items discarded. - decoder/gym_state.go: rename RaidLobbyWebhook json tags lat/lon -> latitude/longitude to match every other webhook payload in the codebase. - decoder/station_state.go: same fix for MaxBattleLobbyWebhook. - decode_push_gateway_test.go: update ClassifiesRaidLobby and ClassifiesBreadLobby to call decodePushGateway with the correct message_type and a valid marshalled PushGatewayMessage, exercising gate-pass → unmarshal → dispatch. A recover() wraps the call because decoder caches (gymCache/stationCache) are nil in unit tests, causing a nil-pointer panic inside Update*Lobby before any DB access. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The success path was silent, making it impossible to see whether a lobby message was received, dropped (gym/station unknown), or emitted as a webhook. Logs receipt, the unknown-fort drop, and webhook emission with the geofence area count. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The dedup guard used pubMs <= lastPubMs, so a message whose message_pub_timestamp_ms is 0 was dropped on the very first update (0 <= 0). Observed in practice on Max (bread) lobby messages, which arrive with pub=0. Treat a zero timestamp as unorderable and always apply; keep the strictly-newer dedup only when a real timestamp is present. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The value is a millisecond timestamp, but the field was named lobby_join_end. Golbat's webhook convention is unix seconds by default with an _ms suffix for millisecond fields (cf. temp_evolution_finish_ms), so a consumer would misread this as seconds. Rename to lobby_join_end_ms on both the raid_lobby and max_battle_lobby webhooks. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Push-gateway raid/Max lobby messages never carry message_pub_timestamp_ms (always 0), so the publish-timestamp ordering was dead weight: the zero-pub path already applied every message. Remove the Gym.RaidLobbyPubMs / Station.BattleLobbyPubMs fields, the comparison in updateRaidLobby / updateBattleLobby (now plain appliers), the pubMs parameter threaded through the Update* entrypoints and decode, and the unused pub log field. Tests updated to assert each update applies. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jfberry
added a commit
that referenced
this pull request
Jun 5, 2026
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.
Summary
As part of a proof of concept for decoding other data sources, this adds a simple raid lobby count tracker (and the Max battle equivalent).
raw_receiver.proto(message_type+payload), parsed on both the gRPC and HTTP/rawinbound paths.message_typeand updates the relevant gym (raid) or station (Max battle).db:"-", not written to the database):Gym.RaidLobbyCount/RaidLobbyEndMsandStation.BattleLobbyCount/BattleLobbyEndMs, served through the fort rtree / API.raid_lobbyandmax_battle_lobby.Notes
gym/raid/max_battleso consumers can opt in given the update frequency.Test Plan
go build ./...andgo test(decoder, webhooks, grpc) passraid_lobby/max_battle_lobbywebhooks fire and the fort API returns the lobby fields🤖 Generated with Claude Code