Skip to content

fix(vote): éviter les double-votes sur useVote/VoteProvider (chargement + double-clic) - #270

Closed
hboisgibault wants to merge 1 commit into
masterfrom
fix/usevote-double-vote
Closed

fix(vote): éviter les double-votes sur useVote/VoteProvider (chargement + double-clic)#270
hboisgibault wants to merge 1 commit into
masterfrom
fix/usevote-double-vote

Conversation

@hboisgibault

Copy link
Copy Markdown
Collaborator

Objectif

Éviter les double-votes côté interface sur les votes d'arguments/messages (useVote : UpDownVoteBox, VoteButton, SuggestionVoteBox, voteables Message, Proposal, DebateSuggestion), qui provoquent côté API une PG::UniqueViolation → HTTP 500 (LogoraAPI #763).

Cause racine (côté interface)

Les composants basés sur useVote décident entre POST (create), PATCH (update) et DELETE selon un état activeVote chargé de façon asynchrone via le VoteProvider (liste GET /votes). Tant que cette liste n'est pas arrivée, activeVote vaut false : un clic part donc en create, même si l'utilisateur a déjà voté → doublon côté serveur.

Correctifs

  1. VoteProvider expose désormais les voteableIds enregistrés et un indicateur votesLoading.
  2. useVote refuse de créer un vote tant que le VoteProvider n'a pas fini de charger les votes existants du voteable enregistré (isVoteReady). Les composants ne sont donc plus « aveugles » pendant le chargement.
  3. Verrou synchrone anti double-clic (useRef, en complément de l'état voteDisabled existant) : pendant qu'un create/update/delete est en vol, tout nouveau clic est ignoré (garde posée de façon synchrone, pas seulement via setState).
  4. UpDownVoteBox, VoteButton, SuggestionVoteBox désactivent leur bouton tant que l'état du vote n'est pas prêt.

Tests

  • useVote > should not create a vote while the existing votes are still loading : aucun POST pendant le chargement, puis POST autorisé une fois chargé.
  • useVote > should not create multiple votes on rapid clicks : deux clics rapides ne produisent qu'un seul POST.
  • VoteButton > should be disabled while the vote state is still loading.

Note

Correctif côté interface uniquement. Une idempotence côté API (VotesController#create) reste recommandée en défense en profondeur (voir issue LogoraAPI #763).

Ce PR a été créé par un agent IA (OpenHands) pour le compte de l'utilisateur.

- VoteProvider now exposes the registered voteableIds and a votesLoading
  flag, so consumers know when the user's existing votes have been loaded.
- useVote no longer creates a vote while the VoteProvider is still loading
  the existing votes of a registered voteable (prevents the duplicate
  create that would raise PG::UniqueViolation on the API).
- A synchronous ref lock (on top of the existing voteDisabled state)
  blocks rapid double-clicks from issuing concurrent create/update/delete.
- UpDownVoteBox, VoteButton and SuggestionVoteBox disable their buttons
  while the vote state is not ready yet.
@hboisgibault
hboisgibault force-pushed the fix/usevote-double-vote branch from 9b3f47a to 3781170 Compare August 17, 2026 11:59
@hboisgibault

Copy link
Copy Markdown
Collaborator Author

PR remplacé par une version simplifiée et plus élégante : voir #271 (verrou synchrone minimal anti envoi multiple). La protection définitive contre les doublons restants est portée côté API (Logora/LogoraAPI#779, création idempotente).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants