Skip to content

Commit

Permalink
Reduce the number of db queries for feature flags
Browse files Browse the repository at this point in the history
  • Loading branch information
danniel committed Jul 5, 2024
1 parent 5f5af7a commit 6b582be
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 50 deletions.
75 changes: 52 additions & 23 deletions backend/hub/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,50 +457,79 @@ def import_cities(self, request):


def flags_phase_1(modeladmin, request, queryset):
FeatureFlag.objects.filter(flag="enable_org_registration").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_approval").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_voting").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_candidate_registration").update(is_enabled=True)
enabled = [
"enable_org_registration",
"enable_org_approval",
"enable_org_voting",
"enable_candidate_registration",
]
FeatureFlag.objects.filter(flag__in=enabled).update(is_enabled=True)

disabled = [
"enable_candidate_voting",
]
FeatureFlag.objects.filter(flag__in=disabled).update(is_enabled=False)

FeatureFlag.objects.filter(flag="enable_candidate_supporting").update(
is_enabled=get_feature_flag(FLAG_CHOICES.global_support_round)
)
FeatureFlag.objects.filter(flag="enable_candidate_voting").update(is_enabled=False)


flags_phase_1.short_description = _("Set flags for PHASE 1 - organization & candidate registrations")


def flags_phase_2(modeladmin, request, queryset):
FeatureFlag.objects.filter(flag="enable_org_registration").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_approval").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_voting").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_candidate_registration").update(is_enabled=False)
FeatureFlag.objects.filter(flag="enable_candidate_supporting").update(is_enabled=False)
FeatureFlag.objects.filter(flag="enable_candidate_voting").update(is_enabled=False)
enabled = [
"enable_org_registration",
"enable_org_approval",
"enable_org_voting",
]
FeatureFlag.objects.filter(flag__in=enabled).update(is_enabled=True)

disabled = [
"enable_candidate_registration",
"enable_candidate_supporting",
"enable_candidate_voting",
]
FeatureFlag.objects.filter(flag__in=disabled).update(is_enabled=False)


flags_phase_2.short_description = _("Set flags for PHASE 2 - candidate validation")


def flags_phase_3(modeladmin, request, queryset):
FeatureFlag.objects.filter(flag="enable_org_registration").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_approval").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_voting").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_candidate_registration").update(is_enabled=False)
FeatureFlag.objects.filter(flag="enable_candidate_supporting").update(is_enabled=False)
FeatureFlag.objects.filter(flag="enable_candidate_voting").update(is_enabled=True)
enabled = [
"enable_org_registration",
"enable_org_approval",
"enable_org_voting",
"enable_candidate_voting",
]
FeatureFlag.objects.filter(flag__in=enabled).update(is_enabled=True)

disabled = [
"enable_candidate_registration",
"enable_candidate_supporting",
]
FeatureFlag.objects.filter(flag__in=disabled).update(is_enabled=False)


flags_phase_3.short_description = _("Set flags for PHASE 3 - voting")


def flags_final_phase(modeladmin, request, queryset):
FeatureFlag.objects.filter(flag="enable_org_registration").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_approval").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_org_voting").update(is_enabled=True)
FeatureFlag.objects.filter(flag="enable_candidate_registration").update(is_enabled=False)
FeatureFlag.objects.filter(flag="enable_candidate_supporting").update(is_enabled=False)
FeatureFlag.objects.filter(flag="enable_candidate_voting").update(is_enabled=False)
enabled = [
"enable_org_registration",
"enable_org_approval",
"enable_org_voting",
]
FeatureFlag.objects.filter(flag__in=enabled).update(is_enabled=True)

disabled = [
"enable_candidate_registration",
"enable_candidate_supporting",
"enable_candidate_voting",
]
FeatureFlag.objects.filter(flag__in=disabled).update(is_enabled=False)


flags_final_phase.short_description = _("Set flags for FINAL PHASE - results")
Expand Down
8 changes: 4 additions & 4 deletions backend/hub/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,15 @@ def __init__(self, *args, **kwargs):

self.initial["org"] = self.user.orgs.first().id

if FeatureFlag.objects.filter(flag="single_domain_round", is_enabled=True).exists():
if FeatureFlag.is_enabled("single_domain_round"):
self.fields["domain"].widget.attrs["disabled"] = True
self.initial["domain"] = Domain.objects.first().id

def clean_org(self):
return self.user.orgs.first().id

def clean_domain(self):
if FeatureFlag.objects.filter(flag="single_domain_round", is_enabled=True).exists():
if FeatureFlag.is_enabled("single_domain_round"):
return Domain.objects.first()
return self.cleaned_data.get("domain")

Expand Down Expand Up @@ -227,7 +227,7 @@ class Meta:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

if not FeatureFlag.objects.filter(flag="enable_candidate_registration", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_candidate_registration"):
for key in self.fields.keys():
self.fields[key].widget.attrs["disabled"] = True

Expand All @@ -239,7 +239,7 @@ def __init__(self, *args, **kwargs):
self.fields[key].widget.attrs["required"] = True

def save(self, commit=True):
if not FeatureFlag.objects.filter(flag="enable_candidate_registration", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_candidate_registration"):
# This should not happen unless someone messes with the form code
raise PermissionDenied

Expand Down
12 changes: 11 additions & 1 deletion backend/hub/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ class Meta:
def __str__(self):
return f"{FLAG_CHOICES[self.flag]}"

@staticmethod
def is_enabled(flag: str) -> bool:
"""
Check if the requested feature flag is enabled
"""
if not flag:
return False

return FeatureFlag.objects.filter(flag=flag, is_enabled=True).exists()


class BlogPost(TimeStampedModel):
title = models.CharField(_("Title"), max_length=254)
Expand Down Expand Up @@ -528,7 +538,7 @@ def save(self, *args, **kwargs):
if self.id and CandidateVote.objects.filter(candidate=self).exists():
raise ValidationError(_("Cannot update candidate after votes have been cast."))

if FeatureFlag.objects.filter(flag="single_domain_round", is_enabled=True).exists():
if FeatureFlag.is_enabled("single_domain_round"):
self.domain = Domain.objects.first()

# This covers the flow when a candidate is withdrawn as the official proposal or the organization, while
Expand Down
2 changes: 1 addition & 1 deletion backend/hub/social_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def update_user_org(org: Organization, token: str, *, in_auth_flow: bool = False
redirect the user to a relevant error page.
"""

if not FeatureFlag.objects.filter(flag="enable_org_registration", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_org_registration"):
if in_auth_flow:
raise ImmediateHttpResponse(redirect(reverse("error-org-registration-closed")))
else:
Expand Down
35 changes: 14 additions & 21 deletions backend/hub/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,18 +255,12 @@ class OrganizationRegisterRequestCreateView(HubCreateView):
)

def get(self, request, *args, **kwargs):
if (
not settings.ENABLE_ORG_REGISTRATION_FORM
or not FeatureFlag.objects.filter(flag="enable_org_registration", is_enabled=True).exists()
):
if not settings.ENABLE_ORG_REGISTRATION_FORM or not FeatureFlag.is_enabled("enable_org_registration"):
raise PermissionDenied
return super().get(request, *args, **kwargs)

def post(self, request, *args, **kwargs):
if (
not settings.ENABLE_ORG_REGISTRATION_FORM
or not FeatureFlag.objects.filter(flag="enable_org_registration", is_enabled=True).exists()
):
if not settings.ENABLE_ORG_REGISTRATION_FORM or not FeatureFlag.is_enabled("enable_org_registration"):
raise PermissionDenied
return super().post(request, *args, **kwargs)

Expand Down Expand Up @@ -294,7 +288,7 @@ def post(self, request, *args, **kwargs):

@permission_required_or_403("hub.approve_organization", (Organization, "pk", "pk"))
def organization_vote(request, pk, action):
if not FeatureFlag.objects.filter(flag="enable_org_approval", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_org_approval"):
raise PermissionDenied

try:
Expand Down Expand Up @@ -354,7 +348,7 @@ class CandidateListView(HubListView):
template_name = "candidate/list.html"

def get_qs(self):
if FeatureFlag.objects.filter(flag="enable_candidate_voting", is_enabled=True).exists():
if FeatureFlag.is_enabled("enable_candidate_voting"):
return Candidate.objects_with_org.filter(
org__status=Organization.STATUS.accepted, status=Candidate.STATUS.accepted, is_proposed=True
)
Expand Down Expand Up @@ -432,12 +426,12 @@ class CandidateRegisterRequestCreateView(LoginRequiredMixin, HubCreateView):
form_class = CandidateRegisterForm

def get(self, request, *args, **kwargs):
if not FeatureFlag.objects.filter(flag="enable_candidate_registration", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_candidate_registration"):
raise PermissionDenied
return super().get(request, *args, **kwargs)

def post(self, request, *args, **kwargs):
if not FeatureFlag.objects.filter(flag="enable_candidate_registration", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_candidate_registration"):
raise PermissionDenied
return super().post(request, *args, **kwargs)

Expand All @@ -461,17 +455,16 @@ def get_success_url(self):
return reverse("candidate-update", args=(self.object.id,))

def post(self, request, *args, **kwargs):
if (
FeatureFlag.objects.filter(flag="enable_candidate_registration", is_enabled=True).exists()
or FeatureFlag.objects.filter(flag="enable_candidate_supporting", is_enabled=True).exists()
if FeatureFlag.is_enabled("enable_candidate_registration") or FeatureFlag.is_enabled(
"enable_candidate_supporting"
):
return super().post(request, *args, **kwargs)
raise PermissionDenied


@permission_required_or_403("hub.vote_candidate", (Candidate, "pk", "pk"))
def candidate_vote(request, pk):
if not FeatureFlag.objects.filter(flag="enable_candidate_voting", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_candidate_voting"):
raise PermissionDenied

try:
Expand Down Expand Up @@ -505,7 +498,7 @@ def candidate_vote(request, pk):

@permission_required_or_403("hub.delete_candidate", (Candidate, "pk", "pk"))
def candidate_revoke(request, pk):
if not FeatureFlag.objects.filter(flag="enable_candidate_supporting", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_candidate_supporting"):
raise PermissionDenied

candidate = get_object_or_404(Candidate, pk=pk)
Expand All @@ -523,7 +516,7 @@ def candidate_revoke(request, pk):

@permission_required_or_403("hub.support_candidate", (Candidate, "pk", "pk"))
def candidate_support(request, pk):
if not FeatureFlag.objects.filter(flag="enable_candidate_supporting", is_enabled=True).exists():
if not FeatureFlag.is_enabled("enable_candidate_supporting"):
raise PermissionDenied

candidate = get_object_or_404(Candidate, pk=pk, is_proposed=True)
Expand All @@ -544,9 +537,9 @@ def candidate_support(request, pk):
@permission_required_or_403("hub.approve_candidate", (Candidate, "pk", "pk"))
def candidate_status_confirm(request, pk):
if (
FeatureFlag.objects.filter(flag="enable_candidate_registration", is_enabled=True).exists()
or FeatureFlag.objects.filter(flag="enable_candidate_supporting", is_enabled=True).exists()
or FeatureFlag.objects.filter(flag="enable_candidate_voting", is_enabled=True).exists()
FeatureFlag.is_enabled("enable_candidate_registration")
or FeatureFlag.is_enabled("enable_candidate_supporting")
or FeatureFlag.is_enabled("enable_candidate_voting")
):
raise PermissionDenied

Expand Down
Binary file modified backend/locale/ro/LC_MESSAGES/django.mo
Binary file not shown.

0 comments on commit 6b582be

Please sign in to comment.