From b0d588bd9876e280fa229a15e468d1ebd4e4cd68 Mon Sep 17 00:00:00 2001 From: Prakhar Pratyush Date: Sun, 22 Oct 2023 09:01:07 +0530 Subject: [PATCH] models: Set defaults for the user_topic policies. Now that we're enabling the feature in the UI, we should set these to the planned long-term defaults for these settings. Also, this commit cleans up the '0476' and '0477' migration files related to user_topic policies. '0476' sets 'null=True' '0477' is noop '0482' sets the default values and performs backfilling. Co-authored-by: Tim Abbott --- ...matically_follow_topics_policy_and_more.py | 10 +- ...matically_follow_topics_policy_and_more.py | 35 +------ ...ly_follow_unmute_topics_policy_defaults.py | 98 +++++++++++++++++++ zerver/models.py | 4 +- 4 files changed, 105 insertions(+), 42 deletions(-) create mode 100644 zerver/migrations/0482_automatically_follow_unmute_topics_policy_defaults.py diff --git a/zerver/migrations/0476_realmuserdefault_automatically_follow_topics_policy_and_more.py b/zerver/migrations/0476_realmuserdefault_automatically_follow_topics_policy_and_more.py index 4f8952fef0..3db4b56269 100644 --- a/zerver/migrations/0476_realmuserdefault_automatically_follow_topics_policy_and_more.py +++ b/zerver/migrations/0476_realmuserdefault_automatically_follow_topics_policy_and_more.py @@ -2,8 +2,6 @@ from django.db import migrations, models -AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER = 4 - class Migration(migrations.Migration): dependencies = [ @@ -15,28 +13,28 @@ class Migration(migrations.Migration): model_name="realmuserdefault", name="automatically_follow_topics_policy", field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER + null=True, ), ), migrations.AddField( model_name="realmuserdefault", name="automatically_unmute_topics_in_muted_streams_policy", field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER + null=True, ), ), migrations.AddField( model_name="userprofile", name="automatically_follow_topics_policy", field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER + null=True, ), ), migrations.AddField( model_name="userprofile", name="automatically_unmute_topics_in_muted_streams_policy", field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER + null=True, ), ), ] diff --git a/zerver/migrations/0477_alter_realmuserdefault_automatically_follow_topics_policy_and_more.py b/zerver/migrations/0477_alter_realmuserdefault_automatically_follow_topics_policy_and_more.py index 7ad1fbe5f7..9379539ba0 100644 --- a/zerver/migrations/0477_alter_realmuserdefault_automatically_follow_topics_policy_and_more.py +++ b/zerver/migrations/0477_alter_realmuserdefault_automatically_follow_topics_policy_and_more.py @@ -1,42 +1,9 @@ # Generated by Django 4.2.5 on 2023-10-02 05:53 -from django.db import migrations, models - -AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER = 4 +from django.db import migrations class Migration(migrations.Migration): dependencies = [ ("zerver", "0476_realmuserdefault_automatically_follow_topics_policy_and_more"), ] - - operations = [ - migrations.AlterField( - model_name="realmuserdefault", - name="automatically_follow_topics_policy", - field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER - ), - ), - migrations.AlterField( - model_name="realmuserdefault", - name="automatically_unmute_topics_in_muted_streams_policy", - field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER - ), - ), - migrations.AlterField( - model_name="userprofile", - name="automatically_follow_topics_policy", - field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER - ), - ), - migrations.AlterField( - model_name="userprofile", - name="automatically_unmute_topics_in_muted_streams_policy", - field=models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER - ), - ), - ] diff --git a/zerver/migrations/0482_automatically_follow_unmute_topics_policy_defaults.py b/zerver/migrations/0482_automatically_follow_unmute_topics_policy_defaults.py new file mode 100644 index 0000000000..f405fc4169 --- /dev/null +++ b/zerver/migrations/0482_automatically_follow_unmute_topics_policy_defaults.py @@ -0,0 +1,98 @@ +# Generated by Django 4.2.6 on 2023-10-20 23:43 + +from django.db import migrations, models +from django.db.backends.base.schema import BaseDatabaseSchemaEditor +from django.db.migrations.state import StateApps +from django.db.models import Max + +AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_SEND = 2 +AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_INITIATION = 3 + + +def set_default_user_topic_policies( + apps: StateApps, schema_editor: BaseDatabaseSchemaEditor +) -> None: + RealmUserDefault = apps.get_model("zerver", "RealmUserDefault") + UserProfile = apps.get_model("zerver", "UserProfile") + + BATCH_SIZE = 1000 + + # In deployments which run migrations without stopping the server + # (e.g. Zulip Cloud), nothing prevents new users from being + # created while we are doing these batched updates. We add an + # extra BATCH_SIZE in order to minimize the risk that we will + # leave any newly-created users with the old values. This is not + # a guarantee, of course, as new users may be created between + # whenever this migration finishes and when the server restarts + # into the new default. + max_id_realm_user_default = ( + RealmUserDefault.objects.aggregate(Max("id", default=0))["id__max"] + BATCH_SIZE + ) + max_id_user_profile = ( + UserProfile.objects.aggregate(Max("id", default=0))["id__max"] + BATCH_SIZE + ) + + lower_bound = 0 + while lower_bound < max_id_realm_user_default: + RealmUserDefault.objects.filter( + id__gt=lower_bound, id__lte=lower_bound + BATCH_SIZE + ).update( + automatically_follow_topics_policy=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_INITIATION, + automatically_unmute_topics_in_muted_streams_policy=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_SEND, + ) + lower_bound += BATCH_SIZE + + lower_bound = 0 + while lower_bound < max_id_user_profile: + UserProfile.objects.filter(id__gt=lower_bound, id__lte=lower_bound + BATCH_SIZE).update( + automatically_follow_topics_policy=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_INITIATION, + automatically_unmute_topics_in_muted_streams_policy=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_SEND, + ) + lower_bound += BATCH_SIZE + + +class Migration(migrations.Migration): + atomic = False + dependencies = [ + ("zerver", "0481_alter_realm_uuid_alter_realm_uuid_owner_secret"), + ] + + operations = [ + migrations.RunPython( + set_default_user_topic_policies, + reverse_code=migrations.RunPython.noop, + elidable=True, + ), + migrations.AlterField( + model_name="userprofile", + name="automatically_follow_topics_policy", + field=models.PositiveSmallIntegerField( + null=False, + default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_INITIATION, + ), + ), + migrations.AlterField( + model_name="userprofile", + name="automatically_unmute_topics_in_muted_streams_policy", + field=models.PositiveSmallIntegerField( + null=False, + default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_SEND, + ), + ), + migrations.AlterField( + model_name="realmuserdefault", + name="automatically_follow_topics_policy", + field=models.PositiveSmallIntegerField( + null=False, + default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_INITIATION, + ), + ), + migrations.AlterField( + model_name="realmuserdefault", + name="automatically_unmute_topics_in_muted_streams_policy", + field=models.PositiveSmallIntegerField( + null=False, + default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_SEND, + ), + ), + ] diff --git a/zerver/models.py b/zerver/models.py index 0874a9b923..d8128d8e45 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -1690,10 +1690,10 @@ class UserBaseSettings(models.Model): AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER, ] automatically_follow_topics_policy = models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER + default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_INITIATION, ) automatically_unmute_topics_in_muted_streams_policy = models.PositiveSmallIntegerField( - default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_NEVER + default=AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_ON_SEND, ) # Whether or not the user wants to sync their drafts.