feat(team): add updated_at to Project model#60550
Conversation
|
Reviews (1): Last reviewed commit: "feat: add updated_at to Project model" | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
This PR adds an updated_at timestamp to the Project model, enabling future project-aware cache invalidation/grace-period checks for team metadata without breaking raw SQL test writers.
Changes:
- Makes
ProjectinheritUpdatedMetaFields. - Adds migration
1187_project_updated_atwith nullableupdated_at. - Bumps
max_migration.txt.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
posthog/models/project.py |
Adds UpdatedMetaFields to Project. |
posthog/migrations/1187_project_updated_at.py |
Adds nullable updated_at column to posthog_project. |
posthog/migrations/max_migration.txt |
Updates latest migration marker to 1187_project_updated_at. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Size Change: 0 B Total Size: 81 MB ℹ️ View Unchanged
|
|
⏭️ Skipped snapshot commit because branch advanced to The new commit will trigger its own snapshot update workflow. If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:
|
Migration SQL ChangesHey 👋, we've detected some migrations on this PR. Here's the SQL output for each migration, make sure they make sense:
|
🔍 Migration Risk AnalysisWe've analyzed your migrations for potential risks. Summary: 1 Safe | 0 Needs Review | 0 Blocked ✅ SafeBrief or no lock, backwards compatible 📚 How to Deploy These Changes SafelyAddField: This operation acquires a brief lock but doesn't rewrite the table. Deployment uses lock timeouts with automatic retries, so lock contention will cause retries rather than connection pile-up. Last updated: 2026-06-02 04:11 UTC (12e9c22) |
0d61211 to
18aef19
Compare
18aef19 to
6846679
Compare
|
🎭 Playwright report · View test results →
These issues are not necessarily caused by your changes. |
Query snapshots: Backend query snapshots updatedChanges: 1 snapshots (1 modified, 0 added, 0 deleted) What this means:
Next steps:
|
d6e1765 to
9529c5f
Compare
9529c5f to
dd50073
Compare
Project now inherits UpdatedMetaFields to add an auto_now timestamp. This field is required for grace-period skip-checks in team_metadata cache invalidation, which depend on Project.updated_at to detect recent project renames and avoid phantom cache mismatches. Nullable column with no DB default to maintain compatibility with raw INSERT statements in nodejs and rust test utilities that only populate (id, organization_id, name, created_at).
dd50073 to
12e9c22
Compare
Problem
The
team_metadataHyperCache denormalizesorganization_nameandproject_nameonto each cached team entry, but cache invalidation only fires on Team save/delete. Renaming a Project never touches the Team row, so the cache serves stale project names until the TTL expires.The fix for that (wiring Project save/delete to cache invalidation) needs a grace-period skip-check so the verifier doesn't flag teams mid-refresh as drift. That check filters on a recent-update timestamp, but Project has only
created_at, with noupdated_atto filter on.Changes
Project now inherits
UpdatedMetaFields, which adds anauto_nowupdated_atcolumn. This matches how the rest of the codebase adds update timestamps and is the prerequisite for project-aware grace checks in the upcoming cache invalidation work.The column is nullable.
posthog_projectis written by rawINSERTstatements in nodejs and rust test utilities that populate only (id,organization_id,name,created_at), so aNOT NULLcolumn would break them. Nullable also keeps the migration fast: Django generates anADD COLUMN … DEFAULT <constant> NULLfollowed byDROP DEFAULT. Because the default is a constant literal (notnow()), Postgres applies it as a fast default — metadata-only, no table rewrite — and the trailingDROP DEFAULTremoves the default for future inserts.Note on existing rows: the fast default backfills every existing project row with the migration's constant timestamp, so existing rows are NOT NULL — they read as the migration time. Only projects created after the migration start NULL (until their first save). The grace check must therefore tolerate every existing project sharing the migration timestamp for the length of the grace window immediately after deploy; once that window elapses they age out normally.
How did you test this code?
I ran these automated checks, no manual testing:
./manage.py sqlmigrate posthog 1194_project_updated_atconfirmed the generated SQL adds the column with a constant default that is then dropped, so nonow()-driven table rewrite.DROP DEFAULTare NULL../manage.py makemigrations --check --dry-runreported no model state drift.Docs update
No docs changes needed.