Skip to content

Commit

Permalink
🐛 [#4824] Schedule task to create FormVariables after saving FormStep
Browse files Browse the repository at this point in the history
this ensures that the Form cannot be left in a broken state with regards to FormVariables, because every component will always have a FormVariable

this is a bandaid fix, because ideally we would have a single endpoint and the FormStep wouldn't be updated if there are errors with variables
  • Loading branch information
stevenbal committed Dec 9, 2024
1 parent 0bda3f3 commit 38293b3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/openforms/forms/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from openforms.api.pagination import PageNumberPagination
from openforms.api.serializers import ExceptionSerializer, ValidationErrorSerializer
from openforms.forms.tasks import create_form_variables_for_components
from openforms.translations.utils import set_language_cookie
from openforms.utils.patches.rest_framework_nested.viewsets import NestedViewSetMixin
from openforms.utils.urls import is_admin_request
Expand Down Expand Up @@ -102,6 +103,34 @@ def get_serializer_context(self):
)
return context

@transaction.atomic()
def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)

form = get_object_or_404(Form, uuid=self.kwargs["form_uuid_or_slug"])
transaction.on_commit(
lambda: create_form_variables_for_components.apply_async(
args=(form.id,),
countdown=60,
)
)

return response

@transaction.atomic()
def update(self, request, *args, **kwargs):
response = super().update(request, *args, **kwargs)

form = get_object_or_404(Form, uuid=self.kwargs["form_uuid_or_slug"])
transaction.on_commit(
lambda: create_form_variables_for_components.apply_async(
args=(form.id,),
countdown=60,
)
)

return response


_FORMSTEP_ADMIN_FIELDS_MARKDOWN = get_admin_fields_markdown(FormStepSerializer)
FormStepViewSet.__doc__ = inspect.getdoc(FormStepViewSet).format(
Expand Down
23 changes: 23 additions & 0 deletions src/openforms/forms/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,29 @@ def repopulate_reusable_definition_variables_to_form_variables(form_id: int) ->
FormVariable.objects.create_for_form(form)


@app.task(ignore_result=True)
@transaction.atomic()
def create_form_variables_for_components(form_id: int) -> None:
"""Create FormVariables for each component in the Form
This task is scheduled after creating/updating a FormStep, to ensure that the saved
Form has the appropriate FormVariables, even if errors occur in the variables update
endpoint. This is done to avoid leaving the Form in a broken state.
See also: https://github.com/open-formulieren/open-forms/issues/4824#issuecomment-2514913073
"""
from .models import Form, FormVariable # due to circular import

form = Form.objects.get(id=form_id)

# delete the existing form variables, we will re-create them
FormVariable.objects.filter(
form=form_id, source=FormVariableSources.component
).delete()

FormVariable.objects.create_for_form(form)


@app.task()
def activate_forms():
"""Activate all the forms that should be activated by the specific date and time."""
Expand Down

0 comments on commit 38293b3

Please sign in to comment.