from typing import override from django.db import models from django.utils.translation import gettext_lazy as _ from apps.core.models import BaseModel class ConflictPolicy(models.TextChoices): MUTUAL_EXCLUSION = "mutual_exclusion", _("Mutual exclusion") PRIORITY = "priority", _("Priority tiers") class ConflictDomain(BaseModel): name = models.CharField( max_length=200, unique=True, verbose_name=_("name"), ) description = models.TextField( blank=True, verbose_name=_("description"), ) policy = models.CharField( max_length=30, choices=ConflictPolicy.choices, default=ConflictPolicy.MUTUAL_EXCLUSION, verbose_name=_("conflict policy"), ) max_concurrent = models.PositiveIntegerField( default=1, verbose_name=_("max concurrent experiments"), ) created_at = models.DateTimeField( auto_now_add=True, verbose_name=_("created at"), ) updated_at = models.DateTimeField( auto_now=True, verbose_name=_("updated at"), ) class Meta: verbose_name = _("conflict domain") verbose_name_plural = _("conflict domains") ordering = ["name"] @override def __str__(self) -> str: return f"{self.name} ({self.policy})" class ExperimentConflictDomain(BaseModel): experiment = models.ForeignKey( "experiments.Experiment", on_delete=models.CASCADE, related_name="conflict_memberships", verbose_name=_("experiment"), ) conflict_domain = models.ForeignKey( ConflictDomain, on_delete=models.CASCADE, related_name="experiment_memberships", verbose_name=_("conflict domain"), ) priority = models.IntegerField( default=0, verbose_name=_("priority"), help_text=_("Higher value wins in priority-based resolution"), ) created_at = models.DateTimeField( auto_now_add=True, verbose_name=_("created at"), ) class Meta: verbose_name = _("experiment conflict domain") verbose_name_plural = _("experiment conflict domains") ordering = ["-priority"] constraints = [ models.UniqueConstraint( fields=["experiment", "conflict_domain"], name="unique_experiment_conflict_domain", ), ] @override def __str__(self) -> str: return ( f"{self.experiment.name} in {self.conflict_domain.name} " f"(priority={self.priority})" )