Repository navigation
Mod elections: the results post charts the whole count - #357
Conversation
The results post in the election's topic listed the winners and linked to the elections page. Now it shows the whole count too, so anyone reading the topic can see it was honest: - everyone's first-choice votes and share of all votes, as a bar chart - what each stage did: who was elected with how many votes, whose extra votes moved on, who went out - where everyone finished - how any tie was settled - every stage in numbers, folded away It's built from the stored result alone, like the page, so it never says who ranked whom. The charts are text (block-character bars in Markdown tables, to an eighth of a cell), so they read the same on the full site, in Dumbcourse and in email; the stylesheet tints them on the full site. Elections already published get the same post: the tick finds each one's results post by its link and revises it in place without bumping the topic, or replies if there's none, and records the election in the PluginStore so it happens once per ResultsPost::VERSION. It waits while the module is off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FGn9A1EjvUZh9u1zSaCHPh
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5a1a75354
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .where.not(topic_id: nil) | ||
| .where.not(id: done) | ||
| .order(:id) | ||
| .each { |election| write!(election) } |
There was a problem hiding this comment.
Batch the per-election backfill queries
When this version is deployed, the loop performs separate topic, user, post, and PluginStore queries for every published election, so the backfill scales as an N+1 query sequence over election history. Load the relevant topics, candidates/users, and posts in batches and persist the completed IDs once per batch rather than querying inside write! for every row.
AGENTS.md reference: AGENTS.md:L24-L24
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Not changing this one. The per-election queries run once per published election, ever: the first tick after deploy writes each election's post and records it. Elections are quarterly by default, so a forum has a handful, not one per post, topic or recipient (which is what AGENTS.md's batching rule is about). After that first pass, each tick is one PluginStore read plus one election query that returns nothing. Batching topics, users and posts across elections would add code to save a few queries one time. If the maintainer wants it batched anyway, I'll do it.
Generated by Claude Code
Publishing and the tick could both find no results post for an election just published and both add one. Writes now go one at a time under a DistributedMutex, so whichever comes second finds the first's post. A failed write was still recorded as done, so that election never got its post: Announcer.reply rescued the error and returned the logger's true. It now returns nil on failure, and an election is recorded only once its post is there (or already says the same), so the next tick tries again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FGn9A1EjvUZh9u1zSaCHPh
Summary
The results post in the election's topic only listed the winners and linked to the elections page. Now it also shows the whole count, so anyone reading the topic can see it was honest:
[details].It's built from the stored result alone (
elections.result), the same data as the elections page, so it never says who ranked whom.The charts are text: bars of block characters, to an eighth of a cell, in Markdown tables. They read the same on the full site, in Dumbcourse and in email, and
mod-elections.scsstints them on the full site. Everything after the winners is inside[wrap=mod-election-count].Elections already published get it too. The tick runs
ResultsPost.backfill!. For each published election not yet in the PluginStore list forResultsPost::VERSION, it finds the results post by its link (/elections?id=N)) and revises it in place withbypass_bump. If there's no such post, it replies. Either way the election is recorded, so this happens once per version. It waits while the module is off. BumpingVERSIONrewrites every election's post.Visibility: the post is as visible as the election topic's category. In a public category, visitors who aren't signed in can now read the full count; until now only members could, on the elections page.
Affected module(s)
Test plan
spec/lib/mod_elections_results_post_spec.rb(4 examples) covers:pnpm lintclean; rubocop and stree clean.Checklist
pnpm lintis cleanbundle exec rubocopis cleanconfig/locales/server.en.ymlorclient.en.yml(no settings; the post's wording is inserver.en.yml)Generated by Claude Code