fix(): fixed bugs with cache invalidation, notifications and guardrails

This commit is contained in:
ITQ
2026-02-24 13:16:29 +03:00
parent b27254e2fb
commit 7bf3ccee5c
14 changed files with 290 additions and 82 deletions
-21
View File
@@ -5,7 +5,6 @@ from django.core.exceptions import ValidationError
from django.db import transaction
from django.db.models import QuerySet
from apps.experiments.models import STARTED_STATUSES
from apps.metrics.models import (
ExperimentMetric,
MetricDefinition,
@@ -131,16 +130,6 @@ def experiment_metric_add(
metric: MetricDefinition,
is_primary: bool = False,
) -> ExperimentMetric:
if experiment.status in STARTED_STATUSES:
raise ValidationError(
{
"experiment": (
"Metrics cannot be modified after the experiment "
"has been started "
f"(status: '{experiment.status}')."
)
}
)
if is_primary:
experiment.experiment_metrics.filter(is_primary=True).update(
is_primary=False,
@@ -160,16 +149,6 @@ def experiment_metric_remove(
experiment: Any,
metric: MetricDefinition,
) -> None:
if experiment.status in STARTED_STATUSES:
raise ValidationError(
{
"experiment": (
"Metrics cannot be modified after the experiment "
"has been started "
f"(status: '{experiment.status}')."
)
}
)
deleted, _ = ExperimentMetric.objects.filter(
experiment=experiment,
metric=metric,
@@ -103,6 +103,46 @@ class MetricDefinitionCreateTest(TestCase):
calculation_rule={"type": "count", "event": "x"},
)
def test_reject_percentile_out_of_range(self) -> None:
with self.assertRaises(ValidationError):
metric_definition_create(
key="bad_pct",
name="Bad Percentile",
metric_type=MetricType.PERCENTILE,
calculation_rule={
"type": "percentile",
"event": "page_loaded",
"property": "latency_ms",
"percentile": 200,
},
)
def test_reject_rule_type_mismatch(self) -> None:
with self.assertRaises(ValidationError):
metric_definition_create(
key="mismatch",
name="Mismatch",
metric_type=MetricType.RATIO,
calculation_rule={
"type": "count",
"numerator_event": "click",
"denominator_event": "exposure",
},
)
def test_reject_extra_rule_fields(self) -> None:
with self.assertRaises(ValidationError):
metric_definition_create(
key="extra_field",
name="Extra",
metric_type=MetricType.COUNT,
calculation_rule={
"type": "count",
"event": "click",
"unknown": "value",
},
)
class MetricDefinitionUpdateTest(TestCase):
def test_update_name_and_description(self) -> None: