feat: add vp value to leaderboard#571
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds voting power value tracking to the leaderboard system by introducing a new vp_value column that accumulates the total voting power value for each user across spaces and proposals.
- Adds
vp_valuecolumn to the leaderboard table schema with appropriate indexing - Updates vote creation logic to increment the user's voting power value in the leaderboard
- Implements voting power value decrementation when proposals are deleted
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| test/schema.sql | Adds vp_value DECIMAL column and index to leaderboard table |
| src/writer/vote.ts | Updates vote creation to track and increment voting power values in leaderboard |
| src/writer/delete-proposal.ts | Implements batch processing to decrement voting power values when proposals are deleted |
| src/helpers/entityValue.ts | Refactors vote value calculation using reduce for better readability |
748e75e to
c313e29
Compare
This comment was marked as outdated.
This comment was marked as outdated.
a76dbb9 to
19c7502
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
206780c to
50e4e82
Compare
…ript - Add vp_value column to leaderboard table, updated asynchronously by votesVpValue when votes are finalized - Add PENDING_DELETE cb status for deferred vote deletion - Add deleteProposalVotes async script to process flagged votes in batches (update leaderboard/spaces counters, then delete) - Simplify delete-proposal writer: flags votes instead of deleting inline - Initialize vp_value to 0 on leaderboard row creation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
50e4e82 to
db2a9a6
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…nting on re-votes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… deltas Replace delta-based vp_value leaderboard updates with idempotent SUM queries from the votes table. Benchmarked at ~500ms per (voter, space) pair on 68M+ votes, using the PRIMARY KEY index. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
…letion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…te deletion Single UPDATE query with COUNT/SUM correlated subqueries instead of per-pair JOIN loop. Benchmarked fastest at ~500ms for 100 pairs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Claude says this: (But i didn't verify code myself but it sounds reasonable) The Orphaned Vote Bug — Step by StepSetup: Alice voted on Proposal P1 in space aave.eth. Her vote has cb = PENDING_COMPUTE, vp_value = 0. Step 0: votesVpValue wakes up, starts its cycle. SELECT id, voter, space, proposal FROM votes WHERE cb = -1 LIMIT 500
Returns: { id: 'vote_abc', voter: 'alice', space: 'aave.eth', proposal: 'P1' }Steps 2: getProposalVpValues() runs: SELECT id, cb, vp_value_by_strategy FROM proposals WHERE cb IN (-1,-2,1,-10) AND votes > 0
Returns: { id: 'P1', vpValueByStrategy: [0.5, 1.2] } — proposal exists, all good.Step 3: A moderator deletes Proposal P1. delete-proposal.ts runs atomically: DELETE FROM proposals WHERE id = 'P1';
UPDATE votes SET cb = -3 WHERE proposal = 'P1'; -- PENDING_DELETE
UPDATE leaderboard SET proposal_count = GREATEST(proposal_count - 1, 0) WHERE user = 'mod' AND space = 'aave.eth';
UPDATE spaces SET proposal_count = GREATEST(proposal_count - 1, 0) WHERE id = 'aave.eth';
Alice's vote is now cb = -3 (PENDING_DELETE) in the database.Step 4: votesVpValue doesn't know any of this happened. It still has the old data from Time 1-2. It computes vp_value = 100 and runs refreshVotesVpValues(): UPDATE votes SET vp_value = 100, cb = 1 WHERE id IN ('vote_abc');
UPDATE leaderboard l SET vp_value = COALESCE((
SELECT SUM(v.vp_value) FROM votes v WHERE v.voter = l.user AND v.space = l.space
), 0) WHERE (l.user, l.space) IN (('alice', 'aave.eth'));This overwrites cb = -3 (PENDING_DELETE) with cb = 1 (FINAL). |
Background workers (votesVpValue, scores) could overwrite cb=PENDING_DELETE set by delete-proposal, orphaning votes that should be cleaned up. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A valid concern, now fixed |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Prevent shutter from decrypting and scoring votes that are mid-deletion, avoiding wasted work and potential inconsistency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@ChaituVR Race conditions should be fixed now |
Summary
Adds
vp_valuetracking to the leaderboard table and defers vote deletion to an async background script. Leaderboard updates use idempotent SUM/COUNT queries from the votes table instead of fragile delta-based increments, preventing drift from re-votes, race conditions, or missed updates.Background workers (
votesVpValue,scores,shutter) now guard against overwritingcb=PENDING_DELETEset bydelete-proposal, preventing a race condition where votes marked for deletion could be orphaned.Changes
vp_valuecolumn to theleaderboardtablePENDING_DELETEconstant (cb = -3) for soft-deleting votesdeleteProposalVotesasync script to process pending vote deletions in batchesdelete-proposalwriter: mark votes asPENDING_DELETEinstead of deleting inlinevotesVpValue: refresh leaderboardvp_valueusingSUM(vp_value)from votes table (idempotent)deleteProposalVotes: refresh leaderboardvote_countandvp_valueusingCOUNT(*)/SUM()via single JOIN subquery (idempotent)votesVpValue: guard votecbupdate withAND cb = PENDING_COMPUTEto prevent overwritingPENDING_DELETEscores: guard vote update withAND cb != PENDING_DELETEto prevent overwriting deletion stateshutter: skipPENDING_DELETEvotes during decryption to avoid wasted work and inconsistencyBenchmark
Tested against production database (68M+ votes). All queries use the PRIMARY KEY
(voter, space, proposal)index.SUM(vp_value) WHERE voter+space(single pair)~500ms is mostly network latency to PlanetScale. The query itself is near-instant (PK index lookup).
Test plan
vp_valuecolumn is added to leaderboard tablecb = -3on proposal deletion instead of being deleted inlinedeleteProposalVotesscript picks up and deletes pending votesvp_valueis refreshed correctly after vote vp_value computationvote_countandvp_valueare correct after vote deletionPENDING_DELETEon votes mid-deletion🤖 Generated with Claude Code