Итак, я решил попробовать внести свой вклад в этот проект, но, похоже, всё окажется сложнее, чем я ожидал. 
Я создал черновик PR: FIX: do not return duplicates from /polls/voters.json by clechasseur · Pull Request #1 · clechasseur/discourse · GitHub
В этом PR я сначала добавил тесты, воспроизводящие проблему, затем применил простое решение от Робa, и тесты начали проходить.
Также я попробовал более элегантное решение (то, которое мне больше понравилось), но, хотя оно и предотвращает дублирование голосующих, оно также меняет порядок возврата голосующих на разных страницах, включая первую. Это потенциально может считаться ломающим изменением (в зависимости от того, как с этим справляется фронтенд — я ещё не смотрел).
Однако, если отойти от деталей, меня остаётся вопрос: что на самом деле означает параметр limit при вызове этого эндпоинта? Он не ограничивает общее количество возвращаемых голосующих, а лишь количество голосующих для каждого варианта опроса. Этот эффект виден в тесте, который я добавил для опроса с множественным выбором здесь — первая страница действительно ограничена двумя голосующими на вариант, но в общей сложности возвращаются три разных голосующих (распределённых по вариантам). Переход к элегантному решению (то есть использование LIMIT :limit OFFSET :offset) приводит к тому, что limit применяется к общему количеству голосов, а не голосующих. Я не на 100% уверен, что это лучше или более интуитивно понятно.
В любом случае, я новичок в этом, поэтому, возможно, слишком сильно углубляюсь. Простое решение действительно убирает дубликаты голосующих и не создаёт слишком много проблем, поэтому, возможно, стоит выбрать его. Я подожду отзывов, прежде чем отправлять PR в основной репозиторий.
—
Кстати, я думаю, что в этой части кода есть ещё одна ошибка. Запрос для загрузки голосующих сортируется по digest, rank и username, но при сортировке по rank используется такое условие:
CASE WHEN rank = 'Abstain' THEN 1 ELSE CAST(rank AS integer) END
Однако ’Abstain’ на самом деле соответствует рангу 0, а не 1 — ранг 1 также может возвращаться как ’1’. Это потенциально делает сортировку недетерминированной между запросами, что означает, что в зависимости от количества голосующих и используемого значения limit при пагинированных запросах можно фактически пропустить некоторых голосующих. В моих новых тестах мне пришлось сортировать возвращённых голосующих, чтобы обойти недетерминированность. (Поскольку это недетерминировано, я предполагаю, что воспроизвести это в тесте непросто, но я могу попробовать…)