Rename tgfp_nfl id columns to provider-neutral external ids + add data_source #385
No reviewers
Labels
No labels
Kestra
bug
enhancement
someday
subtask
☁️ api
🎛️ infrastructure
🐞 sentry
📆 2025 Season
📝 pages
allpicks
📝 pages
picks
📝 pages
standings
🚀 performance
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
johnsturgeon/tgfp-web!385
Loading…
Reference in a new issue
No description provided.
Delete branch "rename-tgfp-nfl-id-columns-to-provider-neutral-external-ids-368"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #368
Phase 2 of removing vestiges of the obsolete TGFPNfl library.
game.tgfp_nfl_game_id->game.external_game_idteam.tgfp_nfl_team_id->team.external_team_idBoth tables gain a
data_sourcecolumn recording which provider issued the external id, with a composite unique constraint on(data_source, external_*_id). The old single-column unique index is dropped (superseded by the composite constraint); the plain index is kept.The migration is hand written. Autogenerate renders a column rename as
drop_column+add_column, which would discard every external id in the table;alter_columnpreserves them. Postgres also leaves the index behind under its old name after a rename, so the migration dropsix_*_tgfp_nfl_*explicitly and recreates it non-unique.Team lookups in
create_picksnow filter ondata_sourceso a future provider reusing an external id cannot collide.Verified against the dev database (32 teams, 48 games)
data_sourcebackfilled toespn, zero nullsMigrations run automatically via
alembic upgrade headindocker/entrypoint.shon container start.Version bumped 2.8.0 -> 2.9.0.
This is a clean, well-scoped PR. I inspected the models, the migration, all four call sites, the base class, and confirmed no lingering references to the old column names. I have no blocking concerns — the findings below are minor.
Review: Rename
tgfp_nflid columns to external ids + adddata_sourceSolid, careful change. The hand-written migration correctly uses
alter_columnrenames (preserving data), explicitly drops the staleix_*_tgfp_nfl_*indexes that a Postgres rename would leave behind, backfillsdata_sourcebefore settingNOT NULL, and the downgrade path is symmetric. All four consumers (create_picks,sync_team_records,update_game, and the models) are updated consistently, and the_espn_teamlookup now matches the new composite unique key exactly, so the.one()call stays safe.Nits
app/models/game.py:42/app/models/team.py:28—data_sourceis a Python-side default only; the migration sets the columnNOT NULLwith noserver_default. Every insert here goes through the ORM (which supplies the default), so this is fine in practice, but it's slightly inconsistent withTGFPModelBase(app/models/base.py:18-32), wherecreated_at/updated_atuseserver_default=now(). A raw-SQL or data-migration insert that omitsdata_sourcewould fail. Considersa_column_kwargs={"server_default": "espn"}for parity and robustness, since a provider-neutral column is exactly the kind of thing a future backfill might touch outside the ORM.app/models/game.py:42/app/models/team.py:28— the field is typedstrwith an enum default, so a freshly constructed object holds aDataSourcemember in memory while a DB-loaded object holds a plainstr. Comparisons still work becauseDataSourcesubclassesstr, but typing the field asdata_source: DataSourcewould make the round-trip type consistent and self-documenting. Optional._espn_team(app/jobs/create_picks.py:33) issues 2–3 separate queries per game. This mirrors the prior behavior and runs in a weekly background job (not a request handler), so it's not a regression — noting only in case a future batch load is desired.Test coverage
There are no tests in the repo (pytest is configured in
pyproject.tomlbut no test files exist), so this isn't a gap introduced by the PR. The PR description documents a thorough manual verification against the dev database (data preservation, backfill, constraint presence, autogenerate 0-ops probe, downgrade→upgrade round trip), which is the right diligence for a data-preserving migration.