Fold countdown module into voting round as private implementation#220
Conversation
Move arm, cancel, and evaluate from convex/model/countdown.ts into convex/model/votingRound.ts as private (non-exported) functions. The countdown had exactly one adapter (the voting round module), making it a hypothetical seam — not a real abstraction boundary. Changes: - Folding arm/cancel/evaluate into votingRound.ts removes the 70-line countdown.ts file and the cross-file import - All 5 Countdown.cancel and 3 Countdown.evaluate call sites now call the private helpers directly - cancelCountdown exported function continues to delegate to the private cancel helper, preserving the public interface - Tests: removed standalone Countdown.arm/cancel/evaluate describe blocks; replaced direct Countdown calls with armCountdown helper that exercises the round's public castVote interface - Removed unused deleteVote test helper The round module deepens: the entire auto-reveal lifecycle (arm, cancel, evaluate, scheduled reveal, token check) now lives in one file. All 160 tests pass. Closes #219
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Code ReviewOverviewThis PR eliminates a single-consumer module ( What's Good
Concerns1. A defensive edge case lost test coverage (moderate) The removed it("does not arm a room with no non-spectator members (empty is not all-in)", ...)The test comment explained why this exists: 2. async function armCountdown(t, roomId, voterIds) {
for (const userId of voterIds) {
await t.run(ctx => VotingRound.castVote(ctx, { roomId, userId, ... }))
}
}This only arms the countdown if 3. export async function cancelCountdown(ctx, roomId) {
await cancel(ctx, roomId);
}This is fine as a named public-API entry point, but it's now semantically identical to calling SummaryThe refactoring is well-motivated and cleanly executed. Two actionable items:
Neither is a blocker, but (1) in particular is a defensive behavior that the original author took care to document — it would be a shame to lose the signal entirely. |
…ensive test - Run npx convex codegen to remove stale countdown references from _generated/api.d.ts - Replace 3 outdated comments referencing the deleted 'Countdown seam' with accurate descriptions (votingRound.ts, model/votingRound.ts) - Restore defensive edge-case test for the areAllVotesIn empty-roster guard: a room with only spectators and stray votes must not arm the auto-reveal countdown. Tested through dropVoter's evaluate path.
Code ReviewOverviewThis PR folds What works well
Concerns1.
2. Evaluate-specific behaviours have no direct test coverage anymore The removed The spectator-only guard is now covered via 3. This helper only arms the countdown if Nits
SummaryClean, well-motivated refactor. Two things worth a look before merge: (a) confirm there is still a 🤖 Generated with Claude Code |
Closes #219
Move
arm,cancel, andevaluatefromconvex/model/countdown.tsintoconvex/model/votingRound.tsas private functions. The countdown had exactly one adapter (the voting round module), making it a hypothetical seam per the codebase-design vocabulary.Changes:
votingRound.ts;countdown.tsdeleted (70 lines)cancelstays as one private helper used from 5 call sites (not inlined)armCountdownhelper exercising the round's publiccastVoteinterface