Skip to content

feat(tracking): write eight more alarm types through PoracleNG's /api/v2 - #828

Merged
hokiepokedad2 merged 5 commits into
developfrom
feat/v2tracking
Aug 24, 2026
Merged

feat(tracking): write eight more alarm types through PoracleNG's /api/v2#828
hokiepokedad2 merged 5 commits into
developfrom
feat/v2tracking

Conversation

@hokiepokedad2

Copy link
Copy Markdown
Contributor

Merge after #827. Moves eight more alarm types onto PoracleNG's uid-addressed v2 PUT: lure, raid, egg, quest, gym, maxbattle, nest and fort. Pokemon was the pilot in #814; this makes nine of eleven.

Per-type field translators generated from 5.2.1's openapi.golden.json, one commit each. ITrackedUidRemapper and UserOwnedOverrideAreaProxy wired for every moved type.

Two prerequisites that had to land first

Single-flight around PoracleServerProfileService.GetAsync. Nine types probing the server profile concurrently on a cold cache is nine identical calls.

A per-type V2AbsentCacheKey. Without it, one gin 404 page not found on any single route dropped all nine types back to v1 at once. That is the kind of failure that looks like "v2 doesn't work" and is really one missing route.

Code the migration deleted

The lure NaturalKeyTrackingUpdate delete-create-restore dance, and maxbattle's delete-and-recreate. Both existed only because v1 had no addressed update.

Verified against the live 5.2.1 server, not just its source

Sentinels confirmed stored verbatim. fort.include_empty confirmed to default true on v2 and false on v1 — the migration guide flags it and it is real, so the translator sends it explicitly rather than letting the default flip what existing rules match. All nine v2-write types observed rotating uids on the wire.

The caveat that matters, and it is not a regression

TrackingUpdateReconciler.EnsureNoMergeIntoAnotherAlarmAsync still runs above the v2 branch on all eight types, and it encodes v1's merge rule. v2's PUT is a full replace that refuses only exact duplicates.

So on 5.2.1 PoracleWeb.NET now refuses edits the server would happily store — a rule differing from another by exactly one updatable field such as template — and pays an extra GetByUserAsync round-trip per edit to do it.

Behaviour is preserved rather than broken, and keeping the guard was the safe call for one change. But it is dead weight on the v2 path, and the inline comment claiming "none of the v1 repair below applies" sits directly above a v1-shaped guard that does. Worth a follow-up to strip it per-type once each is proven on v2.

A missed eleventh type, caught in review

The Pokéstop Events list never had orderAlarms applied, so every edit made the saved card jump to the end of the grid — and its spec was asserting that broken order. Both fixed. That is the "fix one of eleven" pattern, found because this branch had to touch all of them.

What is still on v1 here

Every read. Deliberately — see #828's note on the snapshot measurement. Invasion moved nothing in either direction and cannot until upstream fixes its read.

Verification

Backend 2531, frontend 1398, production Angular build clean.

Raid, egg, quest, nest, gym, max battle, fort change and lure join pokemon on
the uid-addressed PUT. Invasion deliberately does not: a v2 read of a
named-grunt rule carries no targeting field, and PoracleWeb.NET holds only the
grunt name, which live data fills with values it cannot reverse.

Taking the v2 branch skips the whole v1 repair path as a unit, which is the
point. Lure loses NaturalKeyTrackingUpdate's delete-create-restore dance and
max battle loses its delete-then-create window; the other seven skip the
reconcile of the duplicate a v1 create leaves behind. The pre-write guards
stay -- v2's POST still merges and its 409 covers only an exact duplicate.

TrackingV2Translator becomes table-driven, one table per type, because
V2PokemonRule declares 28 integer filters and V2FortRule declares one, and
additionalProperties:false turns a leaked field into a 422 the fallback
silently papers over. TrackingV2TypeTranslationTests asserts each table
against the schema's property list in both directions.

Verified against the live 5.2.1 instance rather than the Go source, per
CLAUDE.md. Every translated body was POSTed and PUT at it and the v1 read
diffed: byte-identical but for the rotated uid. Three traps came out of that,
all now handled -- egg level is required with minimum 1, fort has no
clean/edit/summary at all, and fort include_empty defaults TRUE on v2 where v1
defaults FALSE, so omitting it flipped a stored 0 to 1. Sentinels turn out to
store exactly as v1 stores them despite the migration guide, so they are sent
verbatim rather than omitted.

Two prerequisites landed with it. PoracleServerProfileService.GetAsync is
single-flighted behind a static gate -- it is registered transient, a cold
cache costs a /health GET plus a schema_migrations SELECT, and a dashboard
load now sends several version-gated writes at once. The absent-route flag is
keyed per type, so one gin 404 cannot drop the other eight, and for incident
(whose only surface is v2) a shared flag would mean the type vanishing.

Eight alarm lists gain a stable content order. They rendered PoracleNG's
insertion order, so an edited card would have jumped to the end of the grid
now that an edit rotates the uid.
Pokestop events are the eleventh tracking type and the one this workstream
missed. That type has only ever had PoracleNG's v2 write surface, so a
replace has re-keyed the rule on every edit since it shipped -- the same
card-jumps-to-the-end defect the eight moved types were just given
orderAlarms for. Order on the event type, the field the card is titled by.

The rendering test asserted PoracleNG's insertion order, so it was
defending the defect; it now asserts the content order, and a named
regression test drives the uid-rotation case.
The squash merges each appended their own heading rather than joining the existing
one, so the section carried duplicates again. Bullets are untouched; only the
headings are merged, into Keep a Changelog's order.
@hokiepokedad2
hokiepokedad2 merged commit 6008201 into develop Aug 24, 2026
6 checks passed
@hokiepokedad2
hokiepokedad2 deleted the feat/v2tracking branch August 24, 2026 22:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant