Skip to content

Commit

Permalink
fix(reply-zero): use raw SQL for correct distinct pagination
Browse files Browse the repository at this point in the history
Prisma's `distinct` clause applies AFTER skip/take, causing incorrect
pagination. Switch to PostgreSQL DISTINCT ON to apply distinct filtering
BEFORE pagination, ensuring consistent page sizes and accurate totals.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • Loading branch information
Eliezer Steinbock and Claude Opus 4.5 committed Jan 5, 2026
1 parent 06413c6 commit 851f37d
Showing 1 changed file with 24 additions and 30 deletions.
54 changes: 24 additions & 30 deletions apps/web/app/(app)/[emailAccountId]/reply-zero/fetch-trackers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import prisma from "@/utils/prisma";
import { Prisma, type ThreadTracker } from "@/generated/prisma/client";
import type { ThreadTrackerType } from "@/generated/prisma/enums";
import { getDateFilter, type TimeRange } from "./date-filter";

Expand All @@ -18,37 +19,30 @@ export async function getPaginatedThreadTrackers({
const skip = (page - 1) * PAGE_SIZE;
const dateFilter = getDateFilter(timeRange);

const dateClause = dateFilter
? Prisma.sql`AND "sentAt" <= ${dateFilter.lte}`
: Prisma.empty;

const [trackers, total] = await Promise.all([
prisma.threadTracker.findMany({
where: {
emailAccountId,
resolved: false,
type,
sentAt: dateFilter,
},
orderBy: {
createdAt: "desc",
},
distinct: ["threadId"],
take: PAGE_SIZE,
skip,
}),
dateFilter
? prisma.$queryRaw<[{ count: bigint }]>`
SELECT COUNT(DISTINCT "threadId") as count
FROM "ThreadTracker"
WHERE "emailAccountId" = ${emailAccountId}
AND "resolved" = false
AND "type" = ${type}::text::"ThreadTrackerType"
AND "sentAt" <= ${dateFilter.lte}
`
: prisma.$queryRaw<[{ count: bigint }]>`
SELECT COUNT(DISTINCT "threadId") as count
FROM "ThreadTracker"
WHERE "emailAccountId" = ${emailAccountId}
AND "resolved" = false
AND "type" = ${type}::text::"ThreadTrackerType"
`,
prisma.$queryRaw<ThreadTracker[]>`
SELECT DISTINCT ON ("threadId") *
FROM "ThreadTracker"
WHERE "emailAccountId" = ${emailAccountId}
AND "resolved" = false
AND "type" = ${type}::text::"ThreadTrackerType"
${dateClause}
ORDER BY "threadId", "createdAt" DESC
LIMIT ${PAGE_SIZE}
OFFSET ${skip}
`,
prisma.$queryRaw<[{ count: bigint }]>`
SELECT COUNT(DISTINCT "threadId") as count
FROM "ThreadTracker"
WHERE "emailAccountId" = ${emailAccountId}
AND "resolved" = false
AND "type" = ${type}::text::"ThreadTrackerType"
${dateClause}
`,
]);

const count = Number(total?.[0]?.count);
Expand Down

0 comments on commit 851f37d

Please sign in to comment.