J’ai donc pensé que je tenterais celui-ci pour ma première contribution, mais il semble que ce soit un peu plus compliqué que prévu. 
J’ai un PR de brouillon en ligne : FIX: do not return duplicates from /polls/voters.json by clechasseur · Pull Request #1 · clechasseur/discourse · GitHub
Dans ce PR, j’ai d’abord ajouté des tests qui reproduisent le problème, puis j’ai appliqué la simple correction de Rob et cela a fait passer les tests.
J’ai également essayé la solution plus élégante (celle que j’aurais préférée), mais bien qu’elle empêche les électeurs en double, elle modifie également l’électeur retourné dans chaque page, y compris la première, ce qui pourrait potentiellement être considéré comme un changement majeur (selon la façon dont le frontend le gère - je n’ai pas encore regardé).
En prenant du recul, cependant, je me demande quelle est la véritable signification du paramètre limit lorsque vous appelez ce point de terminaison - il ne limite pas vraiment le nombre total d’électeurs retournés, mais seulement le nombre d’électeurs retournés pour chaque option de vote. Vous pouvez voir cet effet dans le test que j’ai ajouté pour le sondage à choix multiples ici - la première page est effectivement limitée à 2 électeurs par option, mais au total, trois électeurs différents sont retournés (répartis sur les options). Passer à la solution élégante (c’est-à-dire utiliser LIMIT :limit OFFSET :offset) fait que la limit s’applique au nombre total de votes et non d’électeurs. Je ne suis pas sûr à 100% que ce soit mieux ou plus intuitif.
Quoi qu’il en soit, je suis nouveau dans ce domaine et je réfléchis peut-être trop. La solution simple supprime les électeurs en double et ne cause pas trop de dégâts, donc c’est peut-être la bonne voie à suivre. J’attendrai des commentaires avant de soumettre un PR au dépôt parent.
–
Par ailleurs, je pense qu’il y a un autre bug dans cette partie du code. La requête pour charger les électeurs est triée par digest, rank et username - mais lors du tri par rank, elle utilise cette condition :
CASE WHEN rank = 'Abstain' THEN 1 ELSE CAST(rank AS integer) END
Cependant, 'Abstain' correspond en fait au rang 0, et non au rang 1 - le rang 1 peut également être retourné sous forme de '1'. Cela rend potentiellement le tri non déterministe entre les requêtes, ce qui signifie que, selon le nombre d’électeurs et la valeur de limit utilisée, il pourrait être possible de manquer des électeurs lors des requêtes paginées. Dans mes nouveaux tests, j’ai dû trier les électeurs retournés pour contourner la nature non déterministe. (Parce que c’est non déterministe, je suppose que ce n’est pas facile à reproduire dans un test, mais je peux essayer…)