Merge pull request #963 from stackernews/lastzapat
Add a denormalized lastZapAt field to items for notifications performance
This commit is contained in:
commit
a289c9a1f4
@ -184,15 +184,11 @@ export default {
|
||||
|
||||
if (meFull.noteItemSats) {
|
||||
queries.push(
|
||||
`(SELECT "Item".id::TEXT, MAX("ItemAct".created_at) AS "sortTime",
|
||||
MAX("Item".msats/1000) as "earnedSats", 'Votification' AS type
|
||||
`(SELECT "Item".id::TEXT, "Item"."lastZapAt" AS "sortTime",
|
||||
"Item".msats/1000 as "earnedSats", 'Votification' AS type
|
||||
FROM "Item"
|
||||
JOIN "ItemAct" ON "ItemAct"."itemId" = "Item".id
|
||||
WHERE "ItemAct"."userId" <> $1
|
||||
AND "ItemAct".created_at < $2
|
||||
AND "ItemAct".act IN ('TIP', 'FEE')
|
||||
AND "Item"."userId" = $1
|
||||
GROUP BY "Item".id
|
||||
WHERE "Item"."userId" = $1
|
||||
AND "Item"."lastZapAt" < $2
|
||||
ORDER BY "sortTime" DESC
|
||||
LIMIT ${LIMIT})`
|
||||
)
|
||||
@ -200,16 +196,12 @@ export default {
|
||||
|
||||
if (meFull.noteForwardedSats) {
|
||||
queries.push(
|
||||
`(SELECT "Item".id::TEXT, MAX("ItemAct".created_at) AS "sortTime",
|
||||
MAX("Item".msats / 1000 * "ItemForward".pct / 100) as "earnedSats", 'ForwardedVotification' AS type
|
||||
`(SELECT "Item".id::TEXT, "Item"."lastZapAt" AS "sortTime",
|
||||
("Item".msats / 1000 * "ItemForward".pct / 100) as "earnedSats", 'ForwardedVotification' AS type
|
||||
FROM "Item"
|
||||
JOIN "ItemAct" ON "ItemAct"."itemId" = "Item".id
|
||||
JOIN "ItemForward" ON "ItemForward"."itemId" = "Item".id AND "ItemForward"."userId" = $1
|
||||
WHERE "ItemAct"."userId" <> $1
|
||||
AND "Item"."userId" <> $1
|
||||
AND "ItemAct".created_at < $2
|
||||
AND "ItemAct".act IN ('TIP')
|
||||
GROUP BY "Item".id
|
||||
WHERE "Item"."userId" <> $1
|
||||
AND "Item"."lastZapAt" < $2
|
||||
ORDER BY "sortTime" DESC
|
||||
LIMIT ${LIMIT})`
|
||||
)
|
||||
@ -298,23 +290,11 @@ export default {
|
||||
LIMIT ${LIMIT})`
|
||||
)
|
||||
|
||||
// we do all this crazy subquery stuff to make 'reward' islands
|
||||
const notifications = await models.$queryRawUnsafe(
|
||||
`SELECT MAX(id) AS id, MAX("sortTime") AS "sortTime", sum("earnedSats") AS "earnedSats", type,
|
||||
MIN("sortTime") AS "minSortTime"
|
||||
`SELECT id, "sortTime", "earnedSats", type,
|
||||
"sortTime" AS "minSortTime"
|
||||
FROM
|
||||
(SELECT *,
|
||||
CASE
|
||||
WHEN type = 'Earn' THEN
|
||||
ROW_NUMBER() OVER(ORDER BY "sortTime" DESC) -
|
||||
ROW_NUMBER() OVER(PARTITION BY type = 'Earn' ORDER BY "sortTime" DESC)
|
||||
ELSE
|
||||
ROW_NUMBER() OVER(ORDER BY "sortTime" DESC)
|
||||
END as island
|
||||
FROM
|
||||
(${queries.join(' UNION ALL ')}) u
|
||||
) sub
|
||||
GROUP BY type, island
|
||||
(${queries.join(' UNION ALL ')}) u
|
||||
ORDER BY "sortTime" DESC
|
||||
LIMIT ${LIMIT}`, me.id, decodedCursor.time)
|
||||
|
||||
|
@ -220,12 +220,8 @@ export default {
|
||||
SELECT EXISTS(
|
||||
SELECT *
|
||||
FROM "Item"
|
||||
JOIN "ItemAct" ON
|
||||
"ItemAct"."itemId" = "Item".id
|
||||
AND "ItemAct"."userId" <> "Item"."userId"
|
||||
WHERE "ItemAct".created_at > $2
|
||||
AND "Item"."userId" = $1
|
||||
AND "ItemAct".act = 'TIP')`, me.id, lastChecked)
|
||||
WHERE "Item"."lastZapAt" > $2
|
||||
AND "Item"."userId" = $1)`, me.id, lastChecked)
|
||||
if (newSats.exists) {
|
||||
foundNotes()
|
||||
return true
|
||||
@ -296,15 +292,11 @@ export default {
|
||||
SELECT EXISTS(
|
||||
SELECT *
|
||||
FROM "Item"
|
||||
JOIN "ItemAct" ON
|
||||
"ItemAct"."itemId" = "Item".id
|
||||
AND "ItemAct"."userId" <> "Item"."userId"
|
||||
JOIN "ItemForward" ON
|
||||
"ItemForward"."itemId" = "Item".id
|
||||
AND "ItemForward"."userId" = $1
|
||||
WHERE "ItemAct".created_at > $2
|
||||
AND "Item"."userId" <> $1
|
||||
AND "ItemAct".act = 'TIP')`, me.id, lastChecked)
|
||||
WHERE "Item"."lastZapAt" > $2
|
||||
AND "Item"."userId" <> $1)`, me.id, lastChecked)
|
||||
if (newFwdSats.exists) {
|
||||
foundNotes()
|
||||
return true
|
||||
|
@ -5,7 +5,7 @@ services:
|
||||
build: ./docker/db
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "PGPASSWORD=${POSTGRES_PASSWORD} psql -U ${POSTGRES_USER} ${POSTGRES_DB} -c 'SELECT 1 FROM users LIMIT 1'"]
|
||||
test: ["CMD-SHELL", "PGPASSWORD=${POSTGRES_PASSWORD} pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB} -h 127.0.0.1 && psql -U ${POSTGRES_USER} ${POSTGRES_DB} -c 'SELECT 1 FROM users LIMIT 1'"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
|
45
prisma/migrations/20240324164838_last_zap_at/migration.sql
Normal file
45
prisma/migrations/20240324164838_last_zap_at/migration.sql
Normal file
@ -0,0 +1,45 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Item" ADD COLUMN "lastZapAt" TIMESTAMP(3);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Item_lastZapAt_idx" ON "Item"("lastZapAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Reply_itemId_idx" ON "Reply"("itemId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Reply_userId_idx" ON "Reply"("userId");
|
||||
|
||||
|
||||
-- when an item is zapped, update the lastZapAt field
|
||||
CREATE OR REPLACE FUNCTION sats_after_tip(item_id INTEGER, user_id INTEGER, tip_msats BIGINT) RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
item "Item";
|
||||
BEGIN
|
||||
SELECT * FROM "Item" WHERE id = item_id INTO item;
|
||||
IF user_id <> 27 AND item."userId" = user_id THEN
|
||||
RETURN 0;
|
||||
END IF;
|
||||
|
||||
UPDATE "Item"
|
||||
SET "msats" = "msats" + tip_msats,
|
||||
"lastZapAt" = now()
|
||||
WHERE id = item.id;
|
||||
|
||||
UPDATE "Item"
|
||||
SET "commentMsats" = "commentMsats" + tip_msats
|
||||
WHERE id <> item.id and path @> item.path;
|
||||
|
||||
RETURN 1;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- retrofit the lastZapAt field for all existing items
|
||||
UPDATE "Item" SET "lastZapAt" = "Zap".at
|
||||
FROM (
|
||||
SELECT "ItemAct"."itemId", MAX("ItemAct"."created_at") AS at
|
||||
FROM "ItemAct"
|
||||
WHERE "ItemAct".act = 'TIP'
|
||||
GROUP BY "ItemAct"."itemId"
|
||||
) AS "Zap"
|
||||
WHERE "Item"."id" = "Zap"."itemId";
|
@ -355,6 +355,7 @@ model Item {
|
||||
paidImgLink Boolean @default(false)
|
||||
commentMsats BigInt @default(0)
|
||||
lastCommentAt DateTime?
|
||||
lastZapAt DateTime?
|
||||
ncomments Int @default(0)
|
||||
msats BigInt @default(0)
|
||||
weightedDownVotes Float @default(0)
|
||||
@ -393,6 +394,7 @@ model Item {
|
||||
Replies Reply[]
|
||||
|
||||
@@index([uploadId])
|
||||
@@index([lastZapAt])
|
||||
@@index([bio], map: "Item.bio_index")
|
||||
@@index([createdAt], map: "Item.created_at_index")
|
||||
@@index([freebie], map: "Item.freebie_index")
|
||||
@ -428,6 +430,8 @@ model Reply {
|
||||
|
||||
@@index([ancestorId])
|
||||
@@index([ancestorUserId])
|
||||
@@index([itemId])
|
||||
@@index([userId])
|
||||
@@index([level])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user