A community based topic aggregation platform built on atproto
1-- +goose Up
2-- Create votes table for AppView indexing
3-- Votes are indexed from the firehose after being written to user repositories
4CREATE TABLE votes (
5 id BIGSERIAL PRIMARY KEY,
6 uri TEXT UNIQUE NOT NULL, -- AT-URI (at://voter_did/social.coves.interaction.vote/rkey)
7 cid TEXT NOT NULL, -- Content ID
8 rkey TEXT NOT NULL, -- Record key (TID)
9 voter_did TEXT NOT NULL, -- User who voted (from AT-URI repo field)
10
11 -- Subject (strong reference to post/comment)
12 subject_uri TEXT NOT NULL, -- AT-URI of voted item
13 subject_cid TEXT NOT NULL, -- CID of voted item (strong reference)
14
15 -- Vote data
16 direction TEXT NOT NULL CHECK (direction IN ('up', 'down')),
17
18 -- Timestamps
19 created_at TIMESTAMPTZ NOT NULL, -- Voter's timestamp from record
20 indexed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- When indexed by AppView
21 deleted_at TIMESTAMPTZ, -- Soft delete (for firehose delete events)
22
23 -- Foreign keys
24 CONSTRAINT fk_voter FOREIGN KEY (voter_did) REFERENCES users(did) ON DELETE CASCADE
25);
26
27-- Indexes for common query patterns
28CREATE INDEX idx_votes_subject ON votes(subject_uri, direction) WHERE deleted_at IS NULL;
29CREATE INDEX idx_votes_voter_subject ON votes(voter_did, subject_uri) WHERE deleted_at IS NULL;
30
31-- Partial unique index: One active vote per user per subject (soft delete aware)
32CREATE UNIQUE INDEX unique_voter_subject_active ON votes(voter_did, subject_uri) WHERE deleted_at IS NULL;
33CREATE INDEX idx_votes_uri ON votes(uri);
34CREATE INDEX idx_votes_voter ON votes(voter_did, created_at DESC);
35
36-- Comment on table
37COMMENT ON TABLE votes IS 'Votes indexed from user repositories via Jetstream firehose consumer';
38COMMENT ON COLUMN votes.uri IS 'AT-URI in format: at://voter_did/social.coves.interaction.vote/rkey';
39COMMENT ON COLUMN votes.subject_uri IS 'Strong reference to post/comment being voted on';
40COMMENT ON INDEX unique_voter_subject_active IS 'Ensures one active vote per user per subject (soft delete aware)';
41
42-- +goose Down
43DROP TABLE IF EXISTS votes CASCADE;