Skip to content

Commit 0896b9f

Browse files
authored
Use the read replica more (#1152)
* Switch to read replica: getEvent API endpoint * Switch to read replica: v2 run list presenter * Switch to read replica: Job presenter * Switch to read replica: Job list presenter * Switch to read replica: billing client * Switch to read replica: OrgUsagePresenter * Switch to read replica: OrgBillingPlanPresenter * Switch to read replica: ScheduleListPresenter * Switch to read replica: EventRepository taskEvent.findMany
1 parent 3a2dd98 commit 0896b9f

9 files changed

+45
-68
lines changed

apps/webapp/app/presenters/JobListPresenter.server.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,12 @@ import { User } from "~/models/user.server";
1010
import { z } from "zod";
1111
import { projectPath } from "~/utils/pathBuilder";
1212
import { JobRunStatus } from "@trigger.dev/database";
13+
import { BasePresenter } from "./v3/basePresenter.server";
1314

1415
export type ProjectJob = Awaited<ReturnType<JobListPresenter["call"]>>[0];
1516

16-
export class JobListPresenter {
17-
#prismaClient: PrismaClient;
18-
19-
constructor(prismaClient: PrismaClient = prisma) {
20-
this.#prismaClient = prismaClient;
21-
}
17+
export class JobListPresenter extends BasePresenter {
18+
2219

2320
public async call({
2421
userId,
@@ -39,7 +36,7 @@ export class JobListPresenter {
3936
? { some: { integration: { slug: integrationSlug } } }
4037
: {};
4138

42-
const jobs = await this.#prismaClient.job.findMany({
39+
const jobs = await this._replica.job.findMany({
4340
select: {
4441
id: true,
4542
slug: true,
@@ -106,7 +103,7 @@ export class JobListPresenter {
106103
}[];
107104

108105
if (jobs.length > 0) {
109-
latestRuns = await this.#prismaClient.$queryRaw<
106+
latestRuns = await this._replica.$queryRaw<
110107
{
111108
createdAt: Date;
112109
status: JobRunStatus;

apps/webapp/app/presenters/JobPresenter.server.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@ import { User } from "~/models/user.server";
1111
import { z } from "zod";
1212
import { projectPath } from "~/utils/pathBuilder";
1313
import { Job } from "@trigger.dev/database";
14+
import { BasePresenter } from "./v3/basePresenter.server";
1415

15-
export class JobPresenter {
16-
#prismaClient: PrismaClient;
17-
18-
constructor(prismaClient: PrismaClient = prisma) {
19-
this.#prismaClient = prismaClient;
20-
}
16+
export class JobPresenter extends BasePresenter {
17+
2118

2219
public async call({
2320
userId,
@@ -30,7 +27,7 @@ export class JobPresenter {
3027
projectSlug: Project["slug"];
3128
organizationSlug: Organization["slug"];
3229
}) {
33-
const job = await this.#prismaClient.job.findFirst({
30+
const job = await this._replica.job.findFirst({
3431
select: {
3532
id: true,
3633
slug: true,

apps/webapp/app/presenters/OrgBillingPlanPresenter.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
1-
import { PrismaClient, prisma } from "~/db.server";
2-
import { logger } from "~/services/logger.server";
31
import { BillingService } from "../services/billing.server";
2+
import { BasePresenter } from "./v3/basePresenter.server";
43

5-
export class OrgBillingPlanPresenter {
6-
#prismaClient: PrismaClient;
7-
8-
constructor(prismaClient: PrismaClient = prisma) {
9-
this.#prismaClient = prismaClient;
10-
}
11-
4+
export class OrgBillingPlanPresenter extends BasePresenter {
125
public async call({ slug, isManagedCloud }: { slug: string; isManagedCloud: boolean }) {
136
const billingPresenter = new BillingService(isManagedCloud);
147
const plans = await billingPresenter.getPlans();
@@ -17,7 +10,7 @@ export class OrgBillingPlanPresenter {
1710
return;
1811
}
1912

20-
const organization = await this.#prismaClient.organization.findFirst({
13+
const organization = await this._replica.organization.findFirst({
2114
where: {
2215
slug,
2316
},
@@ -27,7 +20,7 @@ export class OrgBillingPlanPresenter {
2720
return;
2821
}
2922

30-
const maxConcurrency = await this.#prismaClient.$queryRaw<
23+
const maxConcurrency = await this._replica.$queryRaw<
3124
{ organization_id: string; max_concurrent_runs: BigInt }[]
3225
>`WITH events AS (
3326
SELECT

apps/webapp/app/presenters/OrgUsagePresenter.server.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
import { estimate } from "@trigger.dev/billing";
2-
import { sqlDatabaseSchema, PrismaClient, prisma } from "~/db.server";
2+
import { sqlDatabaseSchema } from "~/db.server";
33
import { featuresForRequest } from "~/features.server";
44
import { BillingService } from "~/services/billing.server";
5+
import { BasePresenter } from "./v3/basePresenter.server";
56

6-
export class OrgUsagePresenter {
7-
#prismaClient: PrismaClient;
8-
9-
constructor(prismaClient: PrismaClient = prisma) {
10-
this.#prismaClient = prismaClient;
11-
}
12-
7+
export class OrgUsagePresenter extends BasePresenter {
138
public async call({ userId, slug, request }: { userId: string; slug: string; request: Request }) {
14-
const organization = await this.#prismaClient.organization.findFirst({
9+
const organization = await this._replica.organization.findFirst({
1510
where: {
1611
slug,
1712
members: {
@@ -27,7 +22,7 @@ export class OrgUsagePresenter {
2722
}
2823

2924
// Get count of runs since the start of the current month
30-
const runsCount = await this.#prismaClient.jobRun.count({
25+
const runsCount = await this._replica.jobRun.count({
3126
where: {
3227
organizationId: organization.id,
3328
createdAt: {
@@ -48,7 +43,7 @@ export class OrgUsagePresenter {
4843
// ]
4944
// This will be used to generate the chart on the usage page
5045
// Use prisma queryRaw for this since prisma doesn't support grouping by month
51-
const monthlyRunsDataRaw = await this.#prismaClient.$queryRaw<
46+
const monthlyRunsDataRaw = await this._replica.$queryRaw<
5247
{
5348
month: string;
5449
count: number;
@@ -64,7 +59,7 @@ export class OrgUsagePresenter {
6459
const monthlyRunsDataDisplay = fillInMissingRunMonthlyData(monthlyRunsData, 6);
6560

6661
// Max concurrency each day over past 30 days
67-
const concurrencyChartRawData = await this.#prismaClient.$queryRaw<
62+
const concurrencyChartRawData = await this._replica.$queryRaw<
6863
{ day: Date; max_concurrent_runs: BigInt }[]
6964
>`
7065
WITH time_boundaries AS (
@@ -115,7 +110,7 @@ export class OrgUsagePresenter {
115110
concurrencyChartRawData
116111
);
117112

118-
const dailyRunsRawData = await this.#prismaClient.$queryRaw<
113+
const dailyRunsRawData = await this._replica.$queryRaw<
119114
{ day: Date; runs: BigInt }[]
120115
>`SELECT date_trunc('day', "createdAt") as day, COUNT(*) as runs FROM ${sqlDatabaseSchema}."JobRun" WHERE "organizationId" = ${organization.id} AND "createdAt" >= NOW() - INTERVAL '30 days' AND "internal" = FALSE GROUP BY day`;
121116

apps/webapp/app/presenters/RunListPresenter.server.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from "~/components/runs/RunStatuses";
88
import { PrismaClient, prisma } from "~/db.server";
99
import { getUsername } from "~/utils/username";
10+
import { BasePresenter } from "./v3/basePresenter.server";
1011

1112
type RunListOptions = {
1213
userId: string;
@@ -27,12 +28,8 @@ const DEFAULT_PAGE_SIZE = 20;
2728

2829
export type RunList = Awaited<ReturnType<RunListPresenter["call"]>>;
2930

30-
export class RunListPresenter {
31-
#prismaClient: PrismaClient;
32-
33-
constructor(prismaClient: PrismaClient = prisma) {
34-
this.#prismaClient = prismaClient;
35-
}
31+
export class RunListPresenter extends BasePresenter {
32+
3633

3734
public async call({
3835
userId,
@@ -53,7 +50,7 @@ export class RunListPresenter {
5350
const directionMultiplier = direction === "forward" ? 1 : -1;
5451

5552
// Find the organization that the user is a member of
56-
const organization = await this.#prismaClient.organization.findFirstOrThrow({
53+
const organization = await this._replica.organization.findFirstOrThrow({
5754
select: {
5855
id: true,
5956
},
@@ -64,7 +61,7 @@ export class RunListPresenter {
6461
});
6562

6663
// Find the project scoped to the organization
67-
const project = await this.#prismaClient.project.findFirstOrThrow({
64+
const project = await this._replica.project.findFirstOrThrow({
6865
select: {
6966
id: true,
7067
},
@@ -75,7 +72,7 @@ export class RunListPresenter {
7572
});
7673

7774
const job = jobSlug
78-
? await this.#prismaClient.job.findFirstOrThrow({
75+
? await this._replica.job.findFirstOrThrow({
7976
where: {
8077
slug: jobSlug,
8178
projectId: project.id,
@@ -84,10 +81,10 @@ export class RunListPresenter {
8481
: undefined;
8582

8683
const event = eventId
87-
? await this.#prismaClient.eventRecord.findUnique({ where: { id: eventId } })
84+
? await this._replica.eventRecord.findUnique({ where: { id: eventId } })
8885
: undefined;
8986

90-
const runs = await this.#prismaClient.jobRun.findMany({
87+
const runs = await this._replica.jobRun.findMany({
9188
select: {
9289
id: true,
9390
number: true,

apps/webapp/app/presenters/v3/ScheduleListPresenter.server.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { PrismaClient, prisma, sqlDatabaseSchema } from "~/db.server";
44
import { displayableEnvironment } from "~/models/runtimeEnvironment.server";
55
import { getUsername } from "~/utils/username";
66
import { calculateNextScheduledTimestamp } from "~/v3/utils/calculateNextSchedule.server";
7+
import { BasePresenter } from "./basePresenter.server";
78

89
type ScheduleListOptions = {
910
projectId: string;
@@ -34,12 +35,7 @@ export type ScheduleListItem = {
3435
export type ScheduleList = Awaited<ReturnType<ScheduleListPresenter["call"]>>;
3536
export type ScheduleListAppliedFilters = ScheduleList["filters"];
3637

37-
export class ScheduleListPresenter {
38-
#prismaClient: PrismaClient;
39-
40-
constructor(prismaClient: PrismaClient = prisma) {
41-
this.#prismaClient = prismaClient;
42-
}
38+
export class ScheduleListPresenter extends BasePresenter {
4339

4440
public async call({
4541
userId,
@@ -54,7 +50,7 @@ export class ScheduleListPresenter {
5450
tasks !== undefined || environments !== undefined || (search !== undefined && search !== "");
5551

5652
// Find the project scoped to the organization
57-
const project = await this.#prismaClient.project.findFirstOrThrow({
53+
const project = await this._replica.project.findFirstOrThrow({
5854
select: {
5955
id: true,
6056
environments: {
@@ -82,7 +78,7 @@ export class ScheduleListPresenter {
8278
});
8379

8480
//get all possible scheduled tasks
85-
const possibleTasks = await this.#prismaClient.backgroundWorkerTask.findMany({
81+
const possibleTasks = await this._replica.backgroundWorkerTask.findMany({
8682
distinct: ["slug"],
8783
where: {
8884
projectId: project.id,
@@ -93,7 +89,7 @@ export class ScheduleListPresenter {
9389
//do this here to protect against SQL injection
9490
search = search && search !== "" ? `%${search}%` : undefined;
9591

96-
const totalCount = await this.#prismaClient.taskSchedule.count({
92+
const totalCount = await this._replica.taskSchedule.count({
9793
where: {
9894
projectId: project.id,
9995
taskIdentifier: tasks ? { in: tasks } : undefined,
@@ -135,7 +131,7 @@ export class ScheduleListPresenter {
135131
},
136132
});
137133

138-
const rawSchedules = await this.#prismaClient.taskSchedule.findMany({
134+
const rawSchedules = await this._replica.taskSchedule.findMany({
139135
select: {
140136
id: true,
141137
friendlyId: true,
@@ -199,7 +195,7 @@ export class ScheduleListPresenter {
199195

200196
const latestRuns =
201197
rawSchedules.length > 0
202-
? await this.#prismaClient.$queryRaw<{ scheduleId: string; createdAt: Date }[]>`
198+
? await this._replica.$queryRaw<{ scheduleId: string; createdAt: Date }[]>`
203199
SELECT t."scheduleId", t."createdAt"
204200
FROM (
205201
SELECT "scheduleId", MAX("createdAt") as "LatestRun"

apps/webapp/app/routes/api.v2.events.$eventId.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
22
import { json } from "@remix-run/server-runtime";
33
import { GetEvent } from "@trigger.dev/core";
44
import { z } from "zod";
5-
import { prisma } from "~/db.server";
5+
import { $replica } from "~/db.server";
66
import { authenticateApiRequest } from "~/services/apiAuth.server";
77
import { apiCors } from "~/utils/apiCors";
88

@@ -59,7 +59,7 @@ function toJSON(eventRecord: FoundEventRecord): GetEvent {
5959
type FoundEventRecord = NonNullable<Awaited<ReturnType<typeof findEventRecord>>>;
6060

6161
async function findEventRecord(eventId: string, environmentId: string) {
62-
return await prisma.eventRecord.findUnique({
62+
return await $replica.eventRecord.findUnique({
6363
select: {
6464
eventId: true,
6565
name: true,

apps/webapp/app/services/billing.server.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { BillingClient, SetPlanBody } from "@trigger.dev/billing";
2-
import { PrismaClient, prisma } from "~/db.server";
2+
import { $replica, PrismaClient, PrismaReplicaClient, prisma } from "~/db.server";
33
import { env } from "~/env.server";
44
import { logger } from "~/services/logger.server";
55
import { organizationBillingPath } from "~/utils/pathBuilder";
66

77
export class BillingService {
88
#billingClient: BillingClient | undefined;
99
#prismaClient: PrismaClient;
10+
#replica: PrismaReplicaClient;
1011

11-
constructor(isManagedCloud: boolean, prismaClient: PrismaClient = prisma) {
12+
constructor(isManagedCloud: boolean, prismaClient: PrismaClient = prisma, replica: PrismaReplicaClient = $replica) {
1213
this.#prismaClient = prismaClient;
14+
this.#replica = replica;
1315
if (isManagedCloud && process.env.BILLING_API_URL && process.env.BILLING_API_KEY) {
1416
this.#billingClient = new BillingClient({
1517
url: process.env.BILLING_API_URL,
@@ -35,7 +37,7 @@ export class BillingService {
3537
firstDayOfNextMonth.setMonth(firstDayOfNextMonth.getMonth() + 1);
3638
firstDayOfNextMonth.setHours(0, 0, 0, 0);
3739

38-
const currentRunCount = await this.#prismaClient.jobRun.count({
40+
const currentRunCount = await this.#replica.jobRun.count({
3941
where: {
4042
organizationId: orgId,
4143
createdAt: {

apps/webapp/app/v3/eventRepository.server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,14 +334,14 @@ export class EventRepository {
334334
}
335335

336336
async queryEvents(queryOptions: QueryOptions): Promise<TaskEventRecord[]> {
337-
return await this.db.taskEvent.findMany({
337+
return await this.readReplica.taskEvent.findMany({
338338
where: queryOptions,
339339
});
340340
}
341341

342342
async queryIncompleteEvents(queryOptions: QueryOptions) {
343343
// First we will find all the events that match the query options (selecting minimal data).
344-
const taskEvents = await this.db.taskEvent.findMany({
344+
const taskEvents = await this.readReplica.taskEvent.findMany({
345345
where: queryOptions,
346346
select: {
347347
spanId: true,

0 commit comments

Comments
 (0)