Skip to content

Commit

Permalink
hardcoded count for bucket config fixes #3014 (#3091)
Browse files Browse the repository at this point in the history
* generate bucketConfig when accepted to rs fixes #3014

* feedback changes

* changes to use nimbus schema validation, changes randomizationUnit to preset value

* docs

* feedback changes

* formatting and deleting experimentRecipe.json

* unused import
  • Loading branch information
tiftran authored Jul 27, 2020
1 parent 1068778 commit 6c86913
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 175 deletions.
22 changes: 22 additions & 0 deletions app/experimenter/experiments/api/v4/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from experimenter.experiments.models import (
Experiment,
ExperimentVariant,
ExperimentBucketRange,
)

NIMBUS_DATA = get_data()
Expand All @@ -22,6 +23,24 @@ def get_value(self, obj):
return None


class ExperimentBucketRangeSerializer(serializers.ModelSerializer):
namespace = serializers.SlugRelatedField(read_only=True, slug_field="name")
randomizationUnit = serializers.SerializerMethodField()
total = serializers.SerializerMethodField()

class Meta:
model = ExperimentBucketRange
fields = ("randomizationUnit", "namespace", "start", "count", "total")

def get_randomizationUnit(self, obj):
return NIMBUS_DATA["ExperimentDesignPresets"]["empty_aa"]["preset"]["arguments"][
"bucketConfig"
]["randomizationUnit"]

def get_total(self, obj):
return obj.namespace.total


class ExperimentRapidArgumentSerializer(serializers.ModelSerializer):
slug = serializers.ReadOnlyField(source="normandy_slug")
userFacingName = serializers.ReadOnlyField(source="name")
Expand Down Expand Up @@ -53,6 +72,9 @@ class Meta:
)

def get_bucketConfig(self, obj):

if hasattr(obj, "bucket"):
return ExperimentBucketRangeSerializer(obj.bucket).data
return {
"randomizationUnit": "normandy_id",
"namespace": "",
Expand Down
163 changes: 0 additions & 163 deletions app/experimenter/experiments/tests/api/v4/experimentRecipe.json

This file was deleted.

86 changes: 76 additions & 10 deletions app/experimenter/experiments/tests/api/v4/test_serializers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import datetime
import json
import os
from jsonschema import validate

from django.test import TestCase

from experimenter.experiments.models import Experiment
from experimenter.experiments.models import Experiment, ExperimentBucketNamespace
from experimenter.experiments.tests.factories import (
ExperimentFactory,
ExperimentVariantFactory,
Expand Down Expand Up @@ -38,12 +35,6 @@ def test_serializer_outputs_expected_schema(self):
serializer = ExperimentRapidRecipeSerializer(experiment)
data = serializer.data

fn = os.path.join(os.path.dirname(__file__), "experimentRecipe.json")

with open(fn, "r") as f:
json_schema = json.load(f)
self.assertIsNone(validate(instance=data, schema=json_schema))

arguments = data.pop("arguments")
branches = arguments.pop("branches")

Expand Down Expand Up @@ -88,3 +79,78 @@ def test_serializer_outputs_expected_schema(self):
{"ratio": 33, "slug": "control", "value": None},
],
)

def test_serializer_outputs_expected_schema_with_nameSpace_bucket(self):
audience = "us_only"
features = ["pinned_tabs", "picture_in_picture"]
normandy_slug = "experimenter-normandy-slug"
today = datetime.datetime.today()
experiment = ExperimentFactory.create(
type=Experiment.TYPE_RAPID,
rapid_type=Experiment.RAPID_AA_CFR,
audience=audience,
features=features,
normandy_slug=normandy_slug,
firefox_min_version="80.0",
proposed_enrollment=9,
proposed_start_date=today,
)

ExperimentVariantFactory.create(
experiment=experiment, slug="control", is_control=True
)
ExperimentVariantFactory.create(experiment=experiment, slug="variant-2")

ExperimentBucketNamespace.request_namespace_buckets(
experiment.normandy_slug, experiment, 100
)

serializer = ExperimentRapidRecipeSerializer(experiment)
data = serializer.data

arguments = data.pop("arguments")
branches = arguments.pop("branches")

self.assertDictEqual(
data,
{
"id": normandy_slug,
"filter_expression": "env.version|versionCompare('80.0') >= 0",
"targeting": "localeLanguageCode == 'en' && region == 'US'"
" && browserSettings.update.channel == 'release'",
"enabled": True,
},
)

bucket = experiment.bucket

self.assertDictEqual(
dict(arguments),
{
"userFacingName": experiment.name,
"userFacingDescription": experiment.public_description,
"slug": normandy_slug,
"active": True,
"isEnrollmentPaused": False,
"endDate": None,
"proposedEnrollment": experiment.proposed_enrollment,
"features": features,
"referenceBranch": "control",
"startDate": today.isoformat(),
"bucketConfig": {
"count": bucket.count,
"namespace": bucket.namespace.name,
"randomizationUnit": "userId",
"start": bucket.start,
"total": bucket.namespace.total,
},
},
)
converted_branches = [dict(branch) for branch in branches]
self.assertEqual(
converted_branches,
[
{"ratio": 33, "slug": "variant-2", "value": None},
{"ratio": 33, "slug": "control", "value": None},
],
)
15 changes: 14 additions & 1 deletion app/experimenter/kinto/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,37 @@
from celery.utils.log import get_task_logger
from django.conf import settings

from mozilla_nimbus_shared import get_data

from experimenter.celery import app
from experimenter.experiments.api.v4.serializers import ExperimentRapidRecipeSerializer
from experimenter.experiments.changelog_utils import update_experiment_with_change_log
from experimenter.experiments.models import Experiment
from experimenter.experiments.models import Experiment, ExperimentBucketNamespace
from experimenter.kinto import client


logger = get_task_logger(__name__)
metrics = markus.get_metrics("kinto.tasks")

NIMBUS_DATA = get_data()


@app.task
@metrics.timer_decorator("push_experiment_to_kinto.timing")
def push_experiment_to_kinto(experiment_id):
metrics.incr("push_experiment_to_kinto.started")

experiment = Experiment.objects.get(id=experiment_id)
ExperimentBucketNamespace.request_namespace_buckets(
experiment.normandy_slug,
experiment,
NIMBUS_DATA["ExperimentDesignPresets"]["empty_aa"]["preset"]["arguments"][
"bucketConfig"
]["count"],
)

data = ExperimentRapidRecipeSerializer(experiment).data

logger.info(f"Pushing {experiment} to Kinto")

try:
Expand Down
21 changes: 20 additions & 1 deletion app/experimenter/kinto/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@
from django.conf import settings
from django.test import TestCase

from experimenter.experiments.models import Experiment
from mozilla_nimbus_shared import get_data

from experimenter.experiments.models import Experiment, ExperimentBucketRange
from experimenter.experiments.tests.factories import ExperimentFactory
from experimenter.kinto.tests.mixins import MockKintoClientMixin
from experimenter.kinto import tasks
from experimenter.experiments.api.v4.serializers import ExperimentRapidRecipeSerializer

NIMBUS_DATA = get_data()


class TestPushExperimentToKintoTask(MockKintoClientMixin, TestCase):
def setUp(self):
super().setUp()
self.experiment = ExperimentFactory.create_with_status(
Experiment.STATUS_DRAFT,
proposed_start_date=datetime.date(2020, 1, 20),
normandy_slug="normandy-slug",
audience="us_only",
)

Expand All @@ -25,6 +30,20 @@ def test_push_experiment_to_kinto_sends_experiment_data(self):

data = ExperimentRapidRecipeSerializer(self.experiment).data

self.assertTrue(
ExperimentBucketRange.objects.filter(experiment=self.experiment).exists()
)

bucketConfig = data["arguments"]["bucketConfig"].copy()
bucketConfig.pop("start")
bucketConfig.pop("namespace")

designPreset = NIMBUS_DATA["ExperimentDesignPresets"]["empty_aa"]["preset"][
"arguments"
]["bucketConfig"]

self.assertEqual(bucketConfig, designPreset)

self.mock_kinto_client.create_record.assert_called_with(
data=data,
collection=settings.KINTO_COLLECTION,
Expand Down

0 comments on commit 6c86913

Please sign in to comment.