Skip to content

Commit a098567

Browse files
authored
feat(nimbus): Add subscribers field to feature config model. (#13787)
Because - We want to allow a user to subscribe to a feature and get notifications when that feature is used This commit - Adds the subscribers field to the Feature Config class. Fixes #13783
1 parent 041d97e commit a098567

File tree

5 files changed

+64
-0
lines changed

5 files changed

+64
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 5.2.7 on 2025-10-27 15:00
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
dependencies = [
9+
("experiments", "0296_nimbusexperiment_qa_run_date_and_more"),
10+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name="nimbusfeatureconfig",
16+
name="subscribers",
17+
field=models.ManyToManyField(
18+
blank=True,
19+
related_name="subscribed_nimbus_features",
20+
to=settings.AUTH_USER_MODEL,
21+
verbose_name="Subscribers",
22+
),
23+
),
24+
]

experimenter/experimenter/experiments/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,6 +2291,12 @@ class NimbusFeatureConfig(models.Model):
22912291
)
22922292
owner_email = models.EmailField(blank=True, null=True)
22932293
enabled = models.BooleanField(default=True)
2294+
subscribers = models.ManyToManyField(
2295+
User,
2296+
related_name="subscribed_nimbus_features",
2297+
blank=True,
2298+
verbose_name="Subscribers",
2299+
)
22942300

22952301
class Meta:
22962302
verbose_name = "Nimbus Feature Config"

experimenter/experimenter/experiments/tests/factories.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ def schemas(self, create, extracted, **kwargs):
108108
)
109109
)
110110

111+
@factory.post_generation
112+
def subscribers(self, create, extracted, **kwargs):
113+
if not create:
114+
return
115+
116+
if isinstance(extracted, Iterable):
117+
for subscriber in extracted:
118+
self.subscribers.add(subscriber)
119+
else:
120+
for _ in range(3):
121+
self.subscribers.add(UserFactory.create())
122+
111123
@classmethod
112124
def create_desktop_prefflips_feature(cls, **kwargs):
113125
"""Create a feature for Firefox Desktop with the slug "prefFlips"."""

experimenter/experimenter/experiments/tests/test_changelog_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ def test_outputs_expected_schema_for_complete_experiment(self):
277277
"schema": feature_config.schemas.get(version=None).schema,
278278
"slug": feature_config.slug,
279279
"enabled": feature_config.enabled,
280+
"subscribers": [user.id for user in feature_config.subscribers.all()],
280281
},
281282
feature_configs_data,
282283
)

experimenter/experimenter/experiments/tests/test_models.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5516,6 +5516,27 @@ def test_get_versioned_schema_range(self):
55165516
),
55175517
)
55185518

5519+
def test_feature_config_can_have_subscribers(self):
5520+
user1 = UserFactory.create()
5521+
user2 = UserFactory.create()
5522+
feature = NimbusFeatureConfigFactory.create()
5523+
feature.subscribers.add(user1, user2)
5524+
5525+
self.assertEqual(feature.subscribers.count(), 5)
5526+
self.assertIn(user1, feature.subscribers.all())
5527+
self.assertIn(user2, feature.subscribers.all())
5528+
5529+
def test_user_can_subscribe_to_multiple_feature_configs(self):
5530+
user = UserFactory.create()
5531+
feature1 = NimbusFeatureConfigFactory.create()
5532+
feature2 = NimbusFeatureConfigFactory.create()
5533+
feature1.subscribers.add(user)
5534+
feature2.subscribers.add(user)
5535+
5536+
self.assertEqual(user.subscribed_nimbus_features.count(), 2)
5537+
self.assertIn(feature1, user.subscribed_nimbus_features.all())
5538+
self.assertIn(feature2, user.subscribed_nimbus_features.all())
5539+
55195540

55205541
class ApplicationConfigTests(TestCase):
55215542
application_config = experimenter.experiments.constants.APPLICATION_CONFIG_DESKTOP

0 commit comments

Comments
 (0)