Paradaux

PAR-35

0

Remove firm_players defer to treasury

Pending ReleaserianBusinessImprovement

Both Treasury and Business store overlapping player data (login times, UUID↔name mapping) in separate tables. Consolidate into one economy_players table and backfill.

Technical notes — Business owns firm_players (FirmPlayerMapper: uuid↔name cache, touched by FirmPlayerCreationEventListener on login); Treasury owns player_login_times (PlayerLoginMapper: last-login epoch). Neither stores both. Add an economy-schema migration (V<n>__economy_players.sql — schema changes go there) for a unified economy_players(player_uuid_bin, current_name, name_lower, first_seen, last_seen, last_login_epoch); point both mappers at it (Treasury owns the writer, business reads), then drop the old tables. Cross-plugin coordination required.

Resources

Comments

tesks · Jun 4, 2026, 9:56 AM

Code context — Two overlapping tables in the shared economy schema: business's firm_players (FirmPlayerMapper: uuid↔name cache, touched by FirmPlayerCreationEventListener on login) and Treasury's player_login_times (PlayerLoginMapper: last-login epoch). Neither stores both.

Approach: new economy-schema migration (V<n>__economy_players.sql — schema changes go there) for a unified economy_players(player_uuid_bin, current_name, name_lower, first_seen, last_seen, last_login_epoch); point both mappers at it, Treasury owns the writer, business reads, then drop the old tables. Cross-plugin coordination required.

tesks · Jun 11, 2026, 11:21 AM

Migration sizing — economy_players consolidation (prod data, 2026-06-11)

Ran the row-count / overlap analysis against the prod economy DB.

Counts

MetricValue
firm_players rows109,663
player_login_times rows109,236
Overlap (UUID in both)109,206
Only in firm_players457
Only in player_login_times30
Distinct union (final economy_players row count)109,693

Reconciliation checks out: 109,206 + 457 + 30 = 109,693.

Superset / backfill direction

firm_players is effectively the superset and the richer table — it carries every identity column the unified schema needs (current_name, name_lower, first_seen, last_seen), while player_login_times only adds last_login_epoch (no name/timestamp data). So:

  • Base the unified table on firm_players (covers 109,663 of 109,693 = 99.97%).
  • Backfill last_login_epoch onto it from player_login_times for the 109,206 overlap rows.
  • 30 rows exist only in player_login_times (have a last_login_epoch but no name/first_seen/last_seen) — these need current_name/name_lower/first_seen/last_seen left NULL or sourced elsewhere (e.g. Mojang/usercache). Decide the unified schema's nullability for these 30 before migrating.
  • 457 rows exist only in firm_players — they get NULL last_login_epoch (never recorded by Treasury). The unified schema must allow last_login_epoch NULL.

Schema-design implications for V<n>__economy_players.sql

  • last_login_epoch must be nullable (457 rows have no login epoch).
  • current_name/name_lower/first_seen/last_seen must tolerate NULL or the 30 login-only rows must be enriched before/at backfill.
  • PK player_uuid_bin is consistent across both tables (both PK on it), so no dedup logic needed beyond the UNION.

Recommended backfill (single-pass, after the migration creates economy_players)

-- 1. seed from firm_players (the richer/superset table) — 109,663 rows
INSERT INTO economy_players
  (player_uuid_bin, current_name, name_lower, first_seen, last_seen, last_login_epoch)
SELECT fp.player_uuid_bin, fp.current_name, fp.name_lower,
       fp.first_seen, fp.last_seen, plt.last_login_epoch
FROM firm_players fp
LEFT JOIN player_login_times plt
  ON plt.player_uuid_bin = fp.player_uuid_bin;

-- 2. add the 30 login-only rows (name/timestamps NULL)
INSERT INTO economy_players
  (player_uuid_bin, current_name, name_lower, first_seen, last_seen, last_login_epoch)
SELECT plt.player_uuid_bin, NULL, NULL, NULL, NULL, plt.last_login_epoch
FROM player_login_times plt
LEFT JOIN firm_players fp ON fp.player_uuid_bin = plt.player_uuid_bin
WHERE fp.player_uuid_bin IS NULL;

Expected final count: 109,693 rows.

Next step

Sizing is small and clean (sub-110k rows, 99.97% covered by firm_players, only 30 edge rows) — no scaling concern, safe for a single-transaction Flyway migration. Open decision before writing the migration: whether to leave the 30 login-only rows' name/timestamp columns NULL or enrich them. Once that's settled, the V<n>__economy_players.sql migration + the two backfill statements above can be written, then re-point both mappers (Treasury writes, Business reads) and drop the old tables.

Activity

  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a commit — Commit de3fd14 — Show a firm's proprietor on the explorer firm page (PAR-208)
  • ParadauxIO linked a commit — Commit baa372c — Remove the /tax trigger balance test command
  • ParadauxIO linked a commit — Commit d75f957 — Drop legacy firm_players & player_login_times in V19 (PAR-35)
  • ParadauxIO linked a commit — Commit 4d62b8f — economy_players cutover phase 6: single owner for the login clock (PAR-35)
  • ParadauxIO linked a commit — Commit a76e1b5 — economy_players cutover phase 5: Business defers player directory to Treasury
  • ParadauxIO linked a commit — Commit cd1865b — Migrate treasury sales customer-name join to economy_players (PAR-35, phase 4)
  • ParadauxIO linked a commit — Commit 0abd7dd — Migrate explorer name resolution to economy_players (PAR-35, phase 3)
  • ParadauxIO linked a commit — Commit bd3ce2a — Migrate rest-api name resolution to economy_players (PAR-35, phase 2)
  • ParadauxIO linked a commit — Commit 2dfa9ba — Harden economy_players write path for the cutover (PAR-35, phase 1)
  • tesks changed status to Status → Pending Release
  • tesks changed status to Status → In Progress
  • paradaux changed status to Status → Planned
  • paradaux description: Description updated
  • tesks commented
  • tesks description: Description updated
  • tesks commented
  • tesks assigned Assigned to rian