From 3a9994a9a60202ab910c78334e80723f4142c068 Mon Sep 17 00:00:00 2001 From: keyan Date: Fri, 3 Feb 2023 14:40:30 -0600 Subject: [PATCH] denormalize user streak to avoid extra dip --- api/resolvers/user.js | 9 --- .../migration.sql | 2 + .../migration.sql | 3 + prisma/schema.prisma | 3 + worker/streak.js | 56 ++++++++++++------- 5 files changed, 44 insertions(+), 29 deletions(-) create mode 100644 prisma/migrations/20230203193108_streak_user_denorm/migration.sql create mode 100644 prisma/migrations/20230203193324_streak_update/migration.sql diff --git a/api/resolvers/user.js b/api/resolvers/user.js index e7164395..48b73cce 100644 --- a/api/resolvers/user.js +++ b/api/resolvers/user.js @@ -490,15 +490,6 @@ export default { } }) }, - streak: async (user, args, { models }) => { - const res = await models.$queryRaw` - SELECT (now() at time zone 'America/Chicago')::date - "startedAt" AS days - FROM "Streak" - WHERE "userId" = ${user.id} AND "endedAt" IS NULL - ` - - return res.length ? res[0].days : null - }, stacked: async (user, { when }, { models }) => { if (user.stacked) { return user.stacked diff --git a/prisma/migrations/20230203193108_streak_user_denorm/migration.sql b/prisma/migrations/20230203193108_streak_user_denorm/migration.sql new file mode 100644 index 00000000..8bd7d59f --- /dev/null +++ b/prisma/migrations/20230203193108_streak_user_denorm/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "users" ADD COLUMN "streak" INTEGER; diff --git a/prisma/migrations/20230203193324_streak_update/migration.sql b/prisma/migrations/20230203193324_streak_update/migration.sql new file mode 100644 index 00000000..962836d8 --- /dev/null +++ b/prisma/migrations/20230203193324_streak_update/migration.sql @@ -0,0 +1,3 @@ +UPDATE users set streak = (now() AT TIME ZONE 'America/Chicago')::date - "Streak"."startedAt" +FROM "Streak" +WHERE "endedAt" IS NULL AND users.id = "Streak"."userId"; \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e05c4f0b..13d4680a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -45,6 +45,9 @@ model User { photoId Int? photo Upload? @relation(fields: [photoId], references: [id]) + // streak + streak Int? + // walkthrough upvotePopover Boolean @default(false) tipPopover Boolean @default(false) diff --git a/worker/streak.js b/worker/streak.js index 5352ed17..6dd7f934 100644 --- a/worker/streak.js +++ b/worker/streak.js @@ -13,33 +13,47 @@ function computeStreaks ({ models }) { FROM ((SELECT "userId", floor(sum("ItemAct".msats)/1000) as sats_spent FROM "ItemAct" - WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date + WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date >= (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date GROUP BY "userId") UNION ALL (SELECT "userId", sats as sats_spent FROM "Donation" - WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date + WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date >= (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date )) spending GROUP BY "userId" HAVING sum(sats_spent) >= ${STREAK_THRESHOLD} - ), existing_streaks (id) AS ( - SELECT "userId" - FROM "Streak" - WHERE "Streak"."endedAt" IS NULL + ), existing_streaks (id, started_at) AS ( + SELECT "userId", "startedAt" + FROM "Streak" + WHERE "Streak"."endedAt" IS NULL ), new_streaks (id) AS ( - SELECT day_streaks.id - FROM day_streaks - LEFT JOIN existing_streaks ON existing_streaks.id = day_streaks.id - WHERE existing_streaks.id IS NULL + SELECT day_streaks.id + FROM day_streaks + LEFT JOIN existing_streaks ON existing_streaks.id = day_streaks.id + WHERE existing_streaks.id IS NULL ), ending_streaks (id) AS ( - SELECT existing_streaks.id - FROM existing_streaks - LEFT JOIN day_streaks ON existing_streaks.id = day_streaks.id - WHERE day_streaks.id IS NULL - ), streak_insert AS ( - INSERT INTO "Streak" ("userId", "startedAt", created_at, updated_at) - SELECT id, (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date, now_utc(), now_utc() - FROM new_streaks + SELECT existing_streaks.id + FROM existing_streaks + LEFT JOIN day_streaks ON existing_streaks.id = day_streaks.id + WHERE day_streaks.id IS NULL + ), extending_streaks (id, started_at) AS ( + SELECT existing_streaks.id, existing_streaks.started_at + FROM existing_streaks + JOIN day_streaks ON existing_streaks.id = day_streaks.id + ), + -- a bunch of mutations + streak_insert AS ( + INSERT INTO "Streak" ("userId", "startedAt", created_at, updated_at) + SELECT id, (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date, now_utc(), now_utc() + FROM new_streaks + ), user_update_new_streaks AS ( + UPDATE users SET streak = 1 FROM new_streaks WHERE new_streaks.id = users.id + ), user_update_end_streaks AS ( + UPDATE users SET streak = NULL FROM ending_streaks WHERE ending_streaks.id = users.id + ), user_update_extend_streaks AS ( + UPDATE users + SET streak = (now() AT TIME ZONE 'America/Chicago')::date - extending_streaks.started_at + FROM extending_streaks WHERE extending_streaks.id = users.id ) UPDATE "Streak" SET "endedAt" = (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date, updated_at = now_utc() @@ -73,17 +87,19 @@ function checkStreak ({ models }) { FROM ((SELECT "userId", floor(sum("ItemAct".msats)/1000) as sats_spent FROM "ItemAct" - WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago')::date + WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date >= (now() AT TIME ZONE 'America/Chicago')::date AND "userId" = ${Number(id)} GROUP BY "userId") UNION ALL (SELECT "userId", sats as sats_spent FROM "Donation" - WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago')::date + WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date >= (now() AT TIME ZONE 'America/Chicago')::date AND "userId" = ${Number(id)} )) spending GROUP BY "userId" HAVING sum(sats_spent) >= ${STREAK_THRESHOLD} + ), user_start_streak AS ( + UPDATE users SET streak = 0 FROM streak_started WHERE streak_started.id = users.id ) INSERT INTO "Streak" ("userId", "startedAt", created_at, updated_at) SELECT id, (now() AT TIME ZONE 'America/Chicago')::date, now_utc(), now_utc()