fix(poll): reconcile concurrent respondent submissions

This commit is contained in:
2026-07-22 02:54:14 +02:00
parent cac7733bee
commit eb003208e4
4 changed files with 557 additions and 31 deletions
@@ -32,8 +32,10 @@ from govoplan_poll.backend.service import (
_assert_governed_invitation_gateway_allowed,
_assert_poll_accepts_responses,
_existing_response,
_insert_or_reconcile_identified_response,
_lock_poll_for_response,
_now,
_update_existing_response,
assert_no_sensitive_participation_metadata,
get_poll_invitation_by_token,
normalize_response_answers,
@@ -632,25 +634,32 @@ def _submit_locked_governed_response(
trusted_metadata["comment"] = comment
now = _now()
if existing is not None:
if not poll.allow_response_update:
raise PollError("Response updates are not allowed for this poll")
existing.answers = normalized_answers
existing.respondent_label = payload.respondent_label
existing.submitted_at = now
existing.metadata_ = trusted_metadata
response = existing
response = _update_existing_response(
session,
poll=poll,
response=existing,
answers=normalized_answers,
respondent_label=payload.respondent_label,
submitted_at=now,
metadata=trusted_metadata,
)
else:
response = PollResponse(
tenant_id=poll.tenant_id,
poll_id=poll.id,
response, _reconciled = _insert_or_reconcile_identified_response(
session,
poll=poll,
respondent_id=respondent_id,
respondent_label=payload.respondent_label,
answers=normalized_answers,
submitted_at=now,
metadata_=trusted_metadata,
metadata=trusted_metadata,
conflict_validator=lambda winner: _enforce_capacity(
session,
poll=poll,
existing=winner,
normalized_answers=normalized_answers,
limit=policy.max_participants_per_option,
),
)
session.add(response)
session.flush()
if idempotency_key is not None:
session.add(
PollParticipationSubmission(