feat: add post like

This commit is contained in:
Krispire Admin
2026-06-09 16:28:40 +05:30
parent da2bbc323d
commit e9299051f5
12 changed files with 658 additions and 8 deletions
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS post_likes;
ALTER TABLE posts DROP COLUMN IF EXISTS likes_count;
+26
View File
@@ -0,0 +1,26 @@
-- Post likes.
--
-- `post_likes` is the membership table (one row per user-per-post like),
-- written synchronously so a viewer's like state and the "liked by" list are
-- immediately consistent. The UNIQUE(post_id, user_id) makes liking idempotent.
--
-- `posts.likes_count` is a denormalized counter that is NOT updated on every
-- like (that hot-row UPDATE doesn't scale for popular posts). Instead each
-- like/unlike nudges a per-post delta in Redis, and a background worker folds
-- the deltas into this column every 15 minutes. Reads return
-- likes_count + the still-pending Redis delta, so the displayed total is
-- always current.
ALTER TABLE posts ADD COLUMN IF NOT EXISTS likes_count INTEGER NOT NULL DEFAULT 0;
CREATE TABLE IF NOT EXISTS post_likes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
post_id UUID NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (post_id, user_id)
);
-- Listing "who liked this post", newest first.
CREATE INDEX IF NOT EXISTS post_likes_post_idx ON post_likes (post_id, created_at DESC);
-- "Have I liked these posts?" — viewer-state hydration across a feed.
CREATE INDEX IF NOT EXISTS post_likes_user_idx ON post_likes (user_id);
@@ -0,0 +1,3 @@
DROP INDEX IF EXISTS notifications_post_like_uq;
ALTER TABLE notifications DROP COLUMN IF EXISTS actor_count;
ALTER TABLE notifications DROP COLUMN IF EXISTS post_id;
@@ -0,0 +1,14 @@
-- Aggregated like notifications.
--
-- Likes are high-volume, so instead of one notification row per like we keep a
-- single row per (recipient, post) and aggregate: actor_id holds the most
-- recent liker, actor_count how many distinct likers have aggregated into it.
-- The partial unique index lets the like path UPSERT that one row (bumping the
-- count, refreshing the actor, re-marking unread) — so the activity list shows
-- "X and N others liked your post", not a flood.
ALTER TABLE notifications ADD COLUMN IF NOT EXISTS post_id UUID REFERENCES posts(id) ON DELETE CASCADE;
ALTER TABLE notifications ADD COLUMN IF NOT EXISTS actor_count INTEGER NOT NULL DEFAULT 1;
CREATE UNIQUE INDEX IF NOT EXISTS notifications_post_like_uq
ON notifications (user_id, post_id)
WHERE kind = 'post_like';