From e17863e4607743cb634160eeca4bb4f58cb97ae1 Mon Sep 17 00:00:00 2001 From: MichaelSun48 Date: Mon, 3 Mar 2025 14:30:20 -0800 Subject: [PATCH 1/5] Add groupsearchviewlastseen table --- migrations_lockfile.txt | 2 +- src/sentry/backup/comparators.py | 1 + ...37_create_groupsearchviewlastseen_table.py | 71 +++++++++++++++++++ src/sentry/models/__init__.py | 1 + src/sentry/models/groupsearchviewlastseen.py | 28 ++++++++ .../services/organization/impl.py | 2 + src/sentry/testutils/helpers/backups.py | 7 ++ tests/sentry/users/models/test_user.py | 3 + 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py create mode 100644 src/sentry/models/groupsearchviewlastseen.py diff --git a/migrations_lockfile.txt b/migrations_lockfile.txt index 9a3e7f0391f3b1..adbfdd7084e1ad 100644 --- a/migrations_lockfile.txt +++ b/migrations_lockfile.txt @@ -15,7 +15,7 @@ remote_subscriptions: 0003_drop_remote_subscription replays: 0004_index_together -sentry: 0836_create_groupsearchviewstarred_table +sentry: 0837_create_groupsearchviewlastseen_table social_auth: 0002_default_auto_field diff --git a/src/sentry/backup/comparators.py b/src/sentry/backup/comparators.py index e2a81d13ee0811..4544fb9604288e 100644 --- a/src/sentry/backup/comparators.py +++ b/src/sentry/backup/comparators.py @@ -806,6 +806,7 @@ def get_default_comparators() -> dict[str, list[JSONScrubbingComparator]]: DateUpdatedComparator("date_added", "date_updated"), ], "sentry.groupsearchview": [DateUpdatedComparator("date_updated")], + "sentry.groupsearchviewlastseen": [DateUpdatedComparator("last_seen")], "sentry.groupsearchviewstarred": [DateUpdatedComparator("date_updated", "date_added")], "sentry.groupsearchviewproject": [ DateUpdatedComparator("date_updated"), diff --git a/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py b/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py new file mode 100644 index 00000000000000..2f10c702f0a018 --- /dev/null +++ b/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py @@ -0,0 +1,71 @@ +# Generated by Django 5.1.5 on 2025-03-03 22:24 + +import django.db.models.deletion +from django.db import migrations, models + +import sentry.db.models.fields.bounded +import sentry.db.models.fields.foreignkey +import sentry.db.models.fields.hybrid_cloud_foreign_key +from sentry.new_migrations.migrations import CheckedMigration + + +class Migration(CheckedMigration): + # This flag is used to mark that a migration shouldn't be automatically run in production. + # This should only be used for operations where it's safe to run the migration after your + # code has deployed. So this should not be used for most operations that alter the schema + # of a table. + # Here are some things that make sense to mark as post deployment: + # - Large data migrations. Typically we want these to be run manually so that they can be + # monitored and not block the deploy for a long period of time while they run. + # - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to + # run this outside deployments so that we don't block them. Note that while adding an index + # is a schema change, it's completely safe to run the operation after the code has deployed. + # Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment + + is_post_deployment = False + + dependencies = [ + ("sentry", "0836_create_groupsearchviewstarred_table"), + ] + + operations = [ + migrations.CreateModel( + name="GroupSearchViewLastSeen", + fields=[ + ( + "id", + sentry.db.models.fields.bounded.BoundedBigAutoField( + primary_key=True, serialize=False + ), + ), + ( + "user_id", + sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey( + "sentry.User", db_index=True, on_delete="CASCADE" + ), + ), + ("last_seen", models.DateTimeField()), + ( + "group_search_view", + sentry.db.models.fields.foreignkey.FlexibleForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="sentry.groupsearchview" + ), + ), + ( + "organization", + sentry.db.models.fields.foreignkey.FlexibleForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="sentry.organization" + ), + ), + ], + options={ + "db_table": "sentry_groupsearchviewlastseen", + "constraints": [ + models.UniqueConstraint( + fields=("user_id", "organization_id", "group_search_view_id", "last_seen"), + name="sentry_groupsearchviewlastseen_unique_last_seen_per_org_user_view", + ) + ], + }, + ), + ] diff --git a/src/sentry/models/__init__.py b/src/sentry/models/__init__.py index 4505f86fa51c97..f4fdb751fb58c3 100644 --- a/src/sentry/models/__init__.py +++ b/src/sentry/models/__init__.py @@ -53,6 +53,7 @@ from .groupresolution import * # NOQA from .grouprulestatus import * # NOQA from .groupsearchview import * # NOQA +from .groupsearchviewlastseen import * # NOQA from .groupsearchviewstarred import * # NOQA from .groupseen import * # NOQA from .groupshare import * # NOQA diff --git a/src/sentry/models/groupsearchviewlastseen.py b/src/sentry/models/groupsearchviewlastseen.py new file mode 100644 index 00000000000000..1af57bbcd4e297 --- /dev/null +++ b/src/sentry/models/groupsearchviewlastseen.py @@ -0,0 +1,28 @@ +from django.db import models +from django.db.models import UniqueConstraint + +from sentry.backup.scopes import RelocationScope +from sentry.db.models import FlexibleForeignKey, region_silo_model +from sentry.db.models.base import Model +from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey + + +@region_silo_model +class GroupSearchViewLastSeen(Model): + __relocation_scope__ = RelocationScope.Organization + + user_id = HybridCloudForeignKey("sentry.User", on_delete="CASCADE") + organization = FlexibleForeignKey("sentry.Organization") + group_search_view = FlexibleForeignKey("sentry.GroupSearchView") + + last_seen = models.DateTimeField() + + class Meta: + app_label = "sentry" + db_table = "sentry_groupsearchviewlastseen" + constraints = [ + UniqueConstraint( + fields=["user_id", "organization_id", "group_search_view_id", "last_seen"], + name="sentry_groupsearchviewlastseen_unique_last_seen_per_org_user_view", + ) + ] diff --git a/src/sentry/organizations/services/organization/impl.py b/src/sentry/organizations/services/organization/impl.py index 00446a425a9f95..021109806e0098 100644 --- a/src/sentry/organizations/services/organization/impl.py +++ b/src/sentry/organizations/services/organization/impl.py @@ -24,6 +24,7 @@ from sentry.models.groupassignee import GroupAssignee from sentry.models.groupbookmark import GroupBookmark from sentry.models.groupsearchview import GroupSearchView +from sentry.models.groupsearchviewlastseen import GroupSearchViewLastSeen from sentry.models.groupsearchviewstarred import GroupSearchViewStarred from sentry.models.groupseen import GroupSeen from sentry.models.groupshare import GroupShare @@ -592,6 +593,7 @@ def merge_users(self, *, organization_id: int, from_user_id: int, to_user_id: in GroupSeen, GroupShare, GroupSearchView, + GroupSearchViewLastSeen, GroupSearchViewStarred, GroupSubscription, IncidentActivity, diff --git a/src/sentry/testutils/helpers/backups.py b/src/sentry/testutils/helpers/backups.py index ced626790e5271..6caeb689822ac7 100644 --- a/src/sentry/testutils/helpers/backups.py +++ b/src/sentry/testutils/helpers/backups.py @@ -74,6 +74,7 @@ from sentry.models.groupassignee import GroupAssignee from sentry.models.groupbookmark import GroupBookmark from sentry.models.groupsearchview import GroupSearchView, GroupSearchViewProject +from sentry.models.groupsearchviewlastseen import GroupSearchViewLastSeen from sentry.models.groupsearchviewstarred import GroupSearchViewStarred from sentry.models.groupseen import GroupSeen from sentry.models.groupshare import GroupShare @@ -624,6 +625,12 @@ def create_exhaustive_organization( group_search_view=group_search_view, project=project, ) + GroupSearchViewLastSeen.objects.create( + organization=org, + user_id=owner_id, + group_search_view=group_search_view, + last_seen=timezone.now(), + ) GroupSearchViewStarred.objects.create( organization=org, user_id=owner_id, diff --git a/tests/sentry/users/models/test_user.py b/tests/sentry/users/models/test_user.py index b25ee251f4d853..97d3a600dd1c34 100644 --- a/tests/sentry/users/models/test_user.py +++ b/tests/sentry/users/models/test_user.py @@ -15,6 +15,7 @@ from sentry.models.groupassignee import GroupAssignee from sentry.models.groupbookmark import GroupBookmark from sentry.models.groupsearchview import GroupSearchView +from sentry.models.groupsearchviewlastseen import GroupSearchViewLastSeen from sentry.models.groupsearchviewstarred import GroupSearchViewStarred from sentry.models.groupseen import GroupSeen from sentry.models.groupshare import GroupShare @@ -332,6 +333,7 @@ def test_duplicate_memberships(self, expected_models: list[type[Model]]): GroupSeen, GroupShare, GroupSearchView, + GroupSearchViewLastSeen, GroupSearchViewStarred, GroupSubscription, IncidentActivity, @@ -373,6 +375,7 @@ def test_only_source_user_is_member_of_organization(self, expected_models: list[ GroupSeen, GroupShare, GroupSearchView, + GroupSearchViewLastSeen, GroupSearchViewStarred, GroupSubscription, IncidentActivity, From 3974fa3321840ac8699675f47643e75cc505cd52 Mon Sep 17 00:00:00 2001 From: MichaelSun48 Date: Mon, 3 Mar 2025 14:36:50 -0800 Subject: [PATCH 2/5] Remove last_seen from constraint --- .../migrations/0837_create_groupsearchviewlastseen_table.py | 4 ++-- src/sentry/models/groupsearchviewlastseen.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py b/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py index 2f10c702f0a018..88cf65b44e7739 100644 --- a/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py +++ b/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.5 on 2025-03-03 22:24 +# Generated by Django 5.1.5 on 2025-03-03 22:36 import django.db.models.deletion from django.db import migrations, models @@ -62,7 +62,7 @@ class Migration(CheckedMigration): "db_table": "sentry_groupsearchviewlastseen", "constraints": [ models.UniqueConstraint( - fields=("user_id", "organization_id", "group_search_view_id", "last_seen"), + fields=("user_id", "organization_id", "group_search_view_id"), name="sentry_groupsearchviewlastseen_unique_last_seen_per_org_user_view", ) ], diff --git a/src/sentry/models/groupsearchviewlastseen.py b/src/sentry/models/groupsearchviewlastseen.py index 1af57bbcd4e297..1a6951dc8690a0 100644 --- a/src/sentry/models/groupsearchviewlastseen.py +++ b/src/sentry/models/groupsearchviewlastseen.py @@ -22,7 +22,7 @@ class Meta: db_table = "sentry_groupsearchviewlastseen" constraints = [ UniqueConstraint( - fields=["user_id", "organization_id", "group_search_view_id", "last_seen"], + fields=["user_id", "organization_id", "group_search_view_id"], name="sentry_groupsearchviewlastseen_unique_last_seen_per_org_user_view", ) ] From 37dfd5207b78f46b4a3c0abe3be8fa4853c19fa5 Mon Sep 17 00:00:00 2001 From: MichaelSun48 Date: Mon, 3 Mar 2025 15:58:12 -0800 Subject: [PATCH 3/5] use defaultfieldsmodel. Rename to last_visited for consistency --- src/sentry/backup/comparators.py | 2 +- ...37_create_groupsearchviewlastseen_table.py | 71 ------------------- src/sentry/models/__init__.py | 2 +- ...tseen.py => groupsearchviewlastvisited.py} | 11 +-- .../services/organization/impl.py | 4 +- src/sentry/testutils/helpers/backups.py | 6 +- tests/sentry/users/models/test_user.py | 6 +- 7 files changed, 16 insertions(+), 86 deletions(-) delete mode 100644 src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py rename src/sentry/models/{groupsearchviewlastseen.py => groupsearchviewlastvisited.py} (67%) diff --git a/src/sentry/backup/comparators.py b/src/sentry/backup/comparators.py index 4544fb9604288e..0825aebe7502b8 100644 --- a/src/sentry/backup/comparators.py +++ b/src/sentry/backup/comparators.py @@ -806,7 +806,7 @@ def get_default_comparators() -> dict[str, list[JSONScrubbingComparator]]: DateUpdatedComparator("date_added", "date_updated"), ], "sentry.groupsearchview": [DateUpdatedComparator("date_updated")], - "sentry.groupsearchviewlastseen": [DateUpdatedComparator("last_seen")], + "sentry.groupsearchviewlastvisited": [DateUpdatedComparator("last_visited")], "sentry.groupsearchviewstarred": [DateUpdatedComparator("date_updated", "date_added")], "sentry.groupsearchviewproject": [ DateUpdatedComparator("date_updated"), diff --git a/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py b/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py deleted file mode 100644 index 88cf65b44e7739..00000000000000 --- a/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py +++ /dev/null @@ -1,71 +0,0 @@ -# Generated by Django 5.1.5 on 2025-03-03 22:36 - -import django.db.models.deletion -from django.db import migrations, models - -import sentry.db.models.fields.bounded -import sentry.db.models.fields.foreignkey -import sentry.db.models.fields.hybrid_cloud_foreign_key -from sentry.new_migrations.migrations import CheckedMigration - - -class Migration(CheckedMigration): - # This flag is used to mark that a migration shouldn't be automatically run in production. - # This should only be used for operations where it's safe to run the migration after your - # code has deployed. So this should not be used for most operations that alter the schema - # of a table. - # Here are some things that make sense to mark as post deployment: - # - Large data migrations. Typically we want these to be run manually so that they can be - # monitored and not block the deploy for a long period of time while they run. - # - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to - # run this outside deployments so that we don't block them. Note that while adding an index - # is a schema change, it's completely safe to run the operation after the code has deployed. - # Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment - - is_post_deployment = False - - dependencies = [ - ("sentry", "0836_create_groupsearchviewstarred_table"), - ] - - operations = [ - migrations.CreateModel( - name="GroupSearchViewLastSeen", - fields=[ - ( - "id", - sentry.db.models.fields.bounded.BoundedBigAutoField( - primary_key=True, serialize=False - ), - ), - ( - "user_id", - sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey( - "sentry.User", db_index=True, on_delete="CASCADE" - ), - ), - ("last_seen", models.DateTimeField()), - ( - "group_search_view", - sentry.db.models.fields.foreignkey.FlexibleForeignKey( - on_delete=django.db.models.deletion.CASCADE, to="sentry.groupsearchview" - ), - ), - ( - "organization", - sentry.db.models.fields.foreignkey.FlexibleForeignKey( - on_delete=django.db.models.deletion.CASCADE, to="sentry.organization" - ), - ), - ], - options={ - "db_table": "sentry_groupsearchviewlastseen", - "constraints": [ - models.UniqueConstraint( - fields=("user_id", "organization_id", "group_search_view_id"), - name="sentry_groupsearchviewlastseen_unique_last_seen_per_org_user_view", - ) - ], - }, - ), - ] diff --git a/src/sentry/models/__init__.py b/src/sentry/models/__init__.py index f4fdb751fb58c3..d31cc910e06f71 100644 --- a/src/sentry/models/__init__.py +++ b/src/sentry/models/__init__.py @@ -53,7 +53,7 @@ from .groupresolution import * # NOQA from .grouprulestatus import * # NOQA from .groupsearchview import * # NOQA -from .groupsearchviewlastseen import * # NOQA +from .groupsearchviewlastvisited import * # NOQA from .groupsearchviewstarred import * # NOQA from .groupseen import * # NOQA from .groupshare import * # NOQA diff --git a/src/sentry/models/groupsearchviewlastseen.py b/src/sentry/models/groupsearchviewlastvisited.py similarity index 67% rename from src/sentry/models/groupsearchviewlastseen.py rename to src/sentry/models/groupsearchviewlastvisited.py index 1a6951dc8690a0..f33c1059557438 100644 --- a/src/sentry/models/groupsearchviewlastseen.py +++ b/src/sentry/models/groupsearchviewlastvisited.py @@ -1,28 +1,29 @@ from django.db import models from django.db.models import UniqueConstraint +from django.utils import timezone from sentry.backup.scopes import RelocationScope from sentry.db.models import FlexibleForeignKey, region_silo_model -from sentry.db.models.base import Model +from sentry.db.models.base import DefaultFieldsModel from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey @region_silo_model -class GroupSearchViewLastSeen(Model): +class GroupSearchViewLastVisited(DefaultFieldsModel): __relocation_scope__ = RelocationScope.Organization user_id = HybridCloudForeignKey("sentry.User", on_delete="CASCADE") organization = FlexibleForeignKey("sentry.Organization") group_search_view = FlexibleForeignKey("sentry.GroupSearchView") - last_seen = models.DateTimeField() + last_visited = models.DateTimeField(null=False, default=timezone.now) class Meta: app_label = "sentry" - db_table = "sentry_groupsearchviewlastseen" + db_table = "sentry_groupsearchviewlastvisited" constraints = [ UniqueConstraint( fields=["user_id", "organization_id", "group_search_view_id"], - name="sentry_groupsearchviewlastseen_unique_last_seen_per_org_user_view", + name="sentry_groupsearchviewlastvisited_unique_last_visited_per_org_user_view", ) ] diff --git a/src/sentry/organizations/services/organization/impl.py b/src/sentry/organizations/services/organization/impl.py index 021109806e0098..073e468c5f2c80 100644 --- a/src/sentry/organizations/services/organization/impl.py +++ b/src/sentry/organizations/services/organization/impl.py @@ -24,7 +24,7 @@ from sentry.models.groupassignee import GroupAssignee from sentry.models.groupbookmark import GroupBookmark from sentry.models.groupsearchview import GroupSearchView -from sentry.models.groupsearchviewlastseen import GroupSearchViewLastSeen +from sentry.models.groupsearchviewlastvisited import GroupSearchViewLastVisited from sentry.models.groupsearchviewstarred import GroupSearchViewStarred from sentry.models.groupseen import GroupSeen from sentry.models.groupshare import GroupShare @@ -593,7 +593,7 @@ def merge_users(self, *, organization_id: int, from_user_id: int, to_user_id: in GroupSeen, GroupShare, GroupSearchView, - GroupSearchViewLastSeen, + GroupSearchViewLastVisited, GroupSearchViewStarred, GroupSubscription, IncidentActivity, diff --git a/src/sentry/testutils/helpers/backups.py b/src/sentry/testutils/helpers/backups.py index 6caeb689822ac7..2231f5f85d2f26 100644 --- a/src/sentry/testutils/helpers/backups.py +++ b/src/sentry/testutils/helpers/backups.py @@ -74,7 +74,7 @@ from sentry.models.groupassignee import GroupAssignee from sentry.models.groupbookmark import GroupBookmark from sentry.models.groupsearchview import GroupSearchView, GroupSearchViewProject -from sentry.models.groupsearchviewlastseen import GroupSearchViewLastSeen +from sentry.models.groupsearchviewlastvisited import GroupSearchViewLastVisited from sentry.models.groupsearchviewstarred import GroupSearchViewStarred from sentry.models.groupseen import GroupSeen from sentry.models.groupshare import GroupShare @@ -625,11 +625,11 @@ def create_exhaustive_organization( group_search_view=group_search_view, project=project, ) - GroupSearchViewLastSeen.objects.create( + GroupSearchViewLastVisited.objects.create( organization=org, user_id=owner_id, group_search_view=group_search_view, - last_seen=timezone.now(), + last_visited=timezone.now(), ) GroupSearchViewStarred.objects.create( organization=org, diff --git a/tests/sentry/users/models/test_user.py b/tests/sentry/users/models/test_user.py index 97d3a600dd1c34..14244c17693231 100644 --- a/tests/sentry/users/models/test_user.py +++ b/tests/sentry/users/models/test_user.py @@ -15,7 +15,7 @@ from sentry.models.groupassignee import GroupAssignee from sentry.models.groupbookmark import GroupBookmark from sentry.models.groupsearchview import GroupSearchView -from sentry.models.groupsearchviewlastseen import GroupSearchViewLastSeen +from sentry.models.groupsearchviewlastvisited import GroupSearchViewLastVisited from sentry.models.groupsearchviewstarred import GroupSearchViewStarred from sentry.models.groupseen import GroupSeen from sentry.models.groupshare import GroupShare @@ -333,7 +333,7 @@ def test_duplicate_memberships(self, expected_models: list[type[Model]]): GroupSeen, GroupShare, GroupSearchView, - GroupSearchViewLastSeen, + GroupSearchViewLastVisited, GroupSearchViewStarred, GroupSubscription, IncidentActivity, @@ -375,7 +375,7 @@ def test_only_source_user_is_member_of_organization(self, expected_models: list[ GroupSeen, GroupShare, GroupSearchView, - GroupSearchViewLastSeen, + GroupSearchViewLastVisited, GroupSearchViewStarred, GroupSubscription, IncidentActivity, From 3df01638954b7ee32b9d98cb0aa18601eb0b7784 Mon Sep 17 00:00:00 2001 From: MichaelSun48 Date: Mon, 3 Mar 2025 16:01:54 -0800 Subject: [PATCH 4/5] Regenereate migration file --- ...37_create_groupsearchviewlastseen_table.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py diff --git a/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py b/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py new file mode 100644 index 00000000000000..d3af2fc742d850 --- /dev/null +++ b/src/sentry/migrations/0837_create_groupsearchviewlastseen_table.py @@ -0,0 +1,74 @@ +# Generated by Django 5.1.5 on 2025-03-04 00:01 + +import django.db.models.deletion +import django.utils.timezone +from django.db import migrations, models + +import sentry.db.models.fields.bounded +import sentry.db.models.fields.foreignkey +import sentry.db.models.fields.hybrid_cloud_foreign_key +from sentry.new_migrations.migrations import CheckedMigration + + +class Migration(CheckedMigration): + # This flag is used to mark that a migration shouldn't be automatically run in production. + # This should only be used for operations where it's safe to run the migration after your + # code has deployed. So this should not be used for most operations that alter the schema + # of a table. + # Here are some things that make sense to mark as post deployment: + # - Large data migrations. Typically we want these to be run manually so that they can be + # monitored and not block the deploy for a long period of time while they run. + # - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to + # run this outside deployments so that we don't block them. Note that while adding an index + # is a schema change, it's completely safe to run the operation after the code has deployed. + # Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment + + is_post_deployment = False + + dependencies = [ + ("sentry", "0836_create_groupsearchviewstarred_table"), + ] + + operations = [ + migrations.CreateModel( + name="GroupSearchViewLastVisited", + fields=[ + ( + "id", + sentry.db.models.fields.bounded.BoundedBigAutoField( + primary_key=True, serialize=False + ), + ), + ("date_updated", models.DateTimeField(auto_now=True)), + ("date_added", models.DateTimeField(auto_now_add=True)), + ( + "user_id", + sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey( + "sentry.User", db_index=True, on_delete="CASCADE" + ), + ), + ("last_visited", models.DateTimeField(default=django.utils.timezone.now)), + ( + "group_search_view", + sentry.db.models.fields.foreignkey.FlexibleForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="sentry.groupsearchview" + ), + ), + ( + "organization", + sentry.db.models.fields.foreignkey.FlexibleForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="sentry.organization" + ), + ), + ], + options={ + "db_table": "sentry_groupsearchviewlastvisited", + "constraints": [ + models.UniqueConstraint( + fields=("user_id", "organization_id", "group_search_view_id"), + name="sentry_groupsearchviewlastvisited_unique_last_visited_per_org_user_view", + ) + ], + }, + ), + ] From 7ce9b59970c827a099996371c982f69dfefd72ce Mon Sep 17 00:00:00 2001 From: MichaelSun48 Date: Mon, 3 Mar 2025 16:36:35 -0800 Subject: [PATCH 5/5] Update comparators --- src/sentry/backup/comparators.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sentry/backup/comparators.py b/src/sentry/backup/comparators.py index 0825aebe7502b8..970ec939562889 100644 --- a/src/sentry/backup/comparators.py +++ b/src/sentry/backup/comparators.py @@ -806,7 +806,9 @@ def get_default_comparators() -> dict[str, list[JSONScrubbingComparator]]: DateUpdatedComparator("date_added", "date_updated"), ], "sentry.groupsearchview": [DateUpdatedComparator("date_updated")], - "sentry.groupsearchviewlastvisited": [DateUpdatedComparator("last_visited")], + "sentry.groupsearchviewlastvisited": [ + DateUpdatedComparator("last_visited", "date_added", "date_updated") + ], "sentry.groupsearchviewstarred": [DateUpdatedComparator("date_updated", "date_added")], "sentry.groupsearchviewproject": [ DateUpdatedComparator("date_updated"),