Skip to content

Commit b377b57

Browse files
authored
db efficiency improvements (#1657)
- remove calls to findUnique, especially when including/selecting relations - add some missing indexes - add spans to $transaction calls to help track down long running txs
1 parent b67ea9a commit b377b57

File tree

53 files changed

+237
-160
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+237
-160
lines changed

apps/webapp/app/db.server.ts

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { logger } from "./services/logger.server";
1313
import { isValidDatabaseUrl } from "./utils/db";
1414
import { singleton } from "./utils/singleton";
1515
import { $transaction as transac } from "@trigger.dev/database";
16+
import { startActiveSpan } from "./v3/tracer.server";
17+
import { Span } from "@opentelemetry/api";
1618

1719
export type {
1820
PrismaTransactionClient,
@@ -21,25 +23,76 @@ export type {
2123
PrismaReplicaClient,
2224
};
2325

26+
export async function $transaction<R>(
27+
prisma: PrismaClientOrTransaction,
28+
name: string,
29+
fn: (prisma: PrismaTransactionClient, span?: Span) => Promise<R>,
30+
options?: PrismaTransactionOptions
31+
): Promise<R | undefined>;
2432
export async function $transaction<R>(
2533
prisma: PrismaClientOrTransaction,
2634
fn: (prisma: PrismaTransactionClient) => Promise<R>,
2735
options?: PrismaTransactionOptions
36+
): Promise<R | undefined>;
37+
export async function $transaction<R>(
38+
prisma: PrismaClientOrTransaction,
39+
fnOrName: ((prisma: PrismaTransactionClient) => Promise<R>) | string,
40+
fnOrOptions?: ((prisma: PrismaTransactionClient) => Promise<R>) | PrismaTransactionOptions,
41+
options?: PrismaTransactionOptions
2842
): Promise<R | undefined> {
29-
return transac(
30-
prisma,
31-
fn,
32-
(error) => {
33-
logger.error("prisma.$transaction error", {
34-
code: error.code,
35-
meta: error.meta,
36-
stack: error.stack,
37-
message: error.message,
38-
name: error.name,
39-
});
40-
},
41-
options
42-
);
43+
if (typeof fnOrName === "string") {
44+
return await startActiveSpan(fnOrName, async (span) => {
45+
span.setAttribute("$transaction", true);
46+
47+
if (options?.isolationLevel) {
48+
span.setAttribute("isolation_level", options.isolationLevel);
49+
}
50+
51+
if (options?.timeout) {
52+
span.setAttribute("timeout", options.timeout);
53+
}
54+
55+
if (options?.maxWait) {
56+
span.setAttribute("max_wait", options.maxWait);
57+
}
58+
59+
if (options?.swallowPrismaErrors) {
60+
span.setAttribute("swallow_prisma_errors", options.swallowPrismaErrors);
61+
}
62+
63+
const fn = fnOrOptions as (prisma: PrismaTransactionClient, span: Span) => Promise<R>;
64+
65+
return transac(
66+
prisma,
67+
(client) => fn(client, span),
68+
(error) => {
69+
logger.error("prisma.$transaction error", {
70+
code: error.code,
71+
meta: error.meta,
72+
stack: error.stack,
73+
message: error.message,
74+
name: error.name,
75+
});
76+
},
77+
options
78+
);
79+
});
80+
} else {
81+
return transac(
82+
prisma,
83+
fnOrName,
84+
(error) => {
85+
logger.error("prisma.$transaction error", {
86+
code: error.code,
87+
meta: error.meta,
88+
stack: error.stack,
89+
message: error.message,
90+
name: error.name,
91+
});
92+
},
93+
typeof fnOrOptions === "function" ? undefined : fnOrOptions
94+
);
95+
}
4396
}
4497

4598
export { Prisma };

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export class ApiBatchResultsPresenter extends BasePresenter {
99
env: AuthenticatedEnvironment
1010
): Promise<BatchTaskRunExecutionResult | undefined> {
1111
return this.traceWithEnv("call", env, async (span) => {
12-
const batchRun = await this._prisma.batchTaskRun.findUnique({
12+
const batchRun = await this._prisma.batchTaskRun.findFirst({
1313
where: {
1414
friendlyId,
1515
runtimeEnvironmentId: env.id,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export class ApiRunResultPresenter extends BasePresenter {
99
env: AuthenticatedEnvironment
1010
): Promise<TaskRunExecutionResult | undefined> {
1111
return this.traceWithEnv("call", env, async (span) => {
12-
const taskRun = await this._prisma.taskRun.findUnique({
12+
const taskRun = await this._prisma.taskRun.findFirst({
1313
where: {
1414
friendlyId,
1515
runtimeEnvironmentId: env.id,

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,10 @@ export class DeploymentPresenter {
5353
},
5454
});
5555

56-
const deployment = await this.#prismaClient.workerDeployment.findUniqueOrThrow({
56+
const deployment = await this.#prismaClient.workerDeployment.findFirstOrThrow({
5757
where: {
58-
projectId_shortCode: {
59-
projectId: project.id,
60-
shortCode: deploymentShortCode,
61-
},
58+
projectId: project.id,
59+
shortCode: deploymentShortCode,
6260
},
6361
select: {
6462
id: true,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class EnvironmentVariablesPresenter {
1515
}
1616

1717
public async call({ userId, projectSlug }: { userId: User["id"]; projectSlug: Project["slug"] }) {
18-
const project = await this.#prismaClient.project.findUnique({
18+
const project = await this.#prismaClient.project.findFirst({
1919
select: {
2020
id: true,
2121
},

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { WebClient } from "@slack/web-api";
88

99
export class NewAlertChannelPresenter extends BasePresenter {
1010
public async call(projectId: string) {
11-
const project = await this._prisma.project.findUniqueOrThrow({
11+
const project = await this._prisma.project.findFirstOrThrow({
1212
where: {
1313
id: projectId,
1414
},

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export class RunListPresenter extends BasePresenter {
131131

132132
//bulk id
133133
if (bulkId) {
134-
const bulkAction = await this._replica.bulkActionGroup.findUnique({
134+
const bulkAction = await this._replica.bulkActionGroup.findFirst({
135135
select: {
136136
items: {
137137
select: {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class RunStreamPresenter {
2121
request: Request;
2222
runFriendlyId: TaskRun["friendlyId"];
2323
}) {
24-
const run = await this.#prismaClient.taskRun.findUnique({
24+
const run = await this.#prismaClient.taskRun.findFirst({
2525
where: {
2626
friendlyId: runFriendlyId,
2727
},

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class SpanPresenter extends BasePresenter {
2929
spanId: string;
3030
runFriendlyId: string;
3131
}) {
32-
const project = await this._replica.project.findUnique({
32+
const project = await this._replica.project.findFirst({
3333
where: {
3434
slug: projectSlug,
3535
},

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class TasksStreamPresenter {
3333
projectSlug: string;
3434
userId: string;
3535
}) {
36-
const project = await this.#prismaClient.project.findUnique({
36+
const project = await this.#prismaClient.project.findFirst({
3737
where: {
3838
slug: projectSlug,
3939
organization: {

apps/webapp/app/routes/api.v1.deployments.$deploymentId.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
2727

2828
const { deploymentId } = parsedParams.data;
2929

30-
const deployment = await prisma.workerDeployment.findUnique({
30+
const deployment = await prisma.workerDeployment.findFirst({
3131
where: {
3232
friendlyId: deploymentId,
3333
environmentId: authenticatedEnv.id,

apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
2626

2727
const { projectRef } = parsedParams.data;
2828

29-
const project = await prisma.project.findUnique({
29+
const project = await prisma.project.findFirst({
3030
where: {
3131
externalRef: projectRef,
3232
environments: {

apps/webapp/app/routes/api.v1.projects.$projectRef.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
2727

2828
const { projectRef } = parsedParams.data;
2929

30-
const project = await prisma.project.findUnique({
30+
const project = await prisma.project.findFirst({
3131
where: {
3232
externalRef: projectRef,
3333
organization: {

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import Redis, { RedisOptions } from "ioredis";
2-
import {
3-
$transaction,
4-
Prisma,
5-
PrismaClientOrTransaction,
6-
PrismaTransactionOptions,
7-
prisma,
8-
} from "~/db.server";
2+
import { Prisma, PrismaClientOrTransaction, PrismaTransactionOptions, prisma } from "~/db.server";
93
import { env } from "~/env.server";
104
import { singleton } from "~/utils/singleton";
115

apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class EnvironmentVariablesRepository implements Repository {
5757
}[];
5858
}
5959
): Promise<CreateResult> {
60-
const project = await this.prismaClient.project.findUnique({
60+
const project = await this.prismaClient.project.findFirst({
6161
where: {
6262
id: projectId,
6363
deletedAt: null,
@@ -136,7 +136,7 @@ export class EnvironmentVariablesRepository implements Repository {
136136

137137
try {
138138
for (const variable of values) {
139-
const result = await $transaction(this.prismaClient, async (tx) => {
139+
const result = await $transaction(this.prismaClient, "create env var", async (tx) => {
140140
const environmentVariable = await tx.environmentVariable.upsert({
141141
where: {
142142
projectId_key: {
@@ -227,7 +227,7 @@ export class EnvironmentVariablesRepository implements Repository {
227227
keepEmptyValues?: boolean;
228228
}
229229
): Promise<Result> {
230-
const project = await this.prismaClient.project.findUnique({
230+
const project = await this.prismaClient.project.findFirst({
231231
where: {
232232
id: projectId,
233233
deletedAt: null,
@@ -266,7 +266,7 @@ export class EnvironmentVariablesRepository implements Repository {
266266
}
267267
}
268268

269-
const environmentVariable = await this.prismaClient.environmentVariable.findUnique({
269+
const environmentVariable = await this.prismaClient.environmentVariable.findFirst({
270270
select: {
271271
id: true,
272272
key: true,
@@ -280,20 +280,18 @@ export class EnvironmentVariablesRepository implements Repository {
280280
}
281281

282282
try {
283-
await $transaction(this.prismaClient, async (tx) => {
283+
await $transaction(this.prismaClient, "edit env var", async (tx) => {
284284
const secretStore = getSecretStore("DATABASE", {
285285
prismaClient: tx,
286286
});
287287

288288
//create the secret values and references
289289
for (const value of values) {
290290
const key = secretKey(projectId, value.environmentId, environmentVariable.key);
291-
const existingValue = await tx.environmentVariableValue.findUnique({
291+
const existingValue = await tx.environmentVariableValue.findFirst({
292292
where: {
293-
variableId_environmentId: {
294-
variableId: environmentVariable.id,
295-
environmentId: value.environmentId,
296-
},
293+
variableId: environmentVariable.id,
294+
environmentId: value.environmentId,
297295
},
298296
});
299297

@@ -356,7 +354,7 @@ export class EnvironmentVariablesRepository implements Repository {
356354
}
357355

358356
async getProject(projectId: string): Promise<ProjectEnvironmentVariable[]> {
359-
const project = await this.prismaClient.project.findUnique({
357+
const project = await this.prismaClient.project.findFirst({
360358
where: {
361359
id: projectId,
362360
deletedAt: null,
@@ -429,7 +427,7 @@ export class EnvironmentVariablesRepository implements Repository {
429427
}
430428

431429
async getEnvironment(projectId: string, environmentId: string): Promise<EnvironmentVariable[]> {
432-
const project = await this.prismaClient.project.findUnique({
430+
const project = await this.prismaClient.project.findFirst({
433431
where: {
434432
id: projectId,
435433
deletedAt: null,
@@ -483,7 +481,7 @@ export class EnvironmentVariablesRepository implements Repository {
483481
}
484482

485483
async delete(projectId: string, options: DeleteEnvironmentVariable): Promise<Result> {
486-
const project = await this.prismaClient.project.findUnique({
484+
const project = await this.prismaClient.project.findFirst({
487485
where: {
488486
id: projectId,
489487
deletedAt: null,
@@ -501,7 +499,7 @@ export class EnvironmentVariablesRepository implements Repository {
501499
return { success: false as const, error: "Project not found" };
502500
}
503501

504-
const environmentVariable = await this.prismaClient.environmentVariable.findUnique({
502+
const environmentVariable = await this.prismaClient.environmentVariable.findFirst({
505503
select: {
506504
id: true,
507505
key: true,
@@ -526,7 +524,7 @@ export class EnvironmentVariablesRepository implements Repository {
526524
}
527525

528526
try {
529-
await $transaction(this.prismaClient, async (tx) => {
527+
await $transaction(this.prismaClient, "delete env var", async (tx) => {
530528
await tx.environmentVariable.delete({
531529
where: {
532530
id: options.id,
@@ -564,7 +562,7 @@ export class EnvironmentVariablesRepository implements Repository {
564562
}
565563

566564
async deleteValue(projectId: string, options: DeleteEnvironmentVariableValue): Promise<Result> {
567-
const project = await this.prismaClient.project.findUnique({
565+
const project = await this.prismaClient.project.findFirst({
568566
where: {
569567
id: projectId,
570568
deletedAt: null,
@@ -582,7 +580,7 @@ export class EnvironmentVariablesRepository implements Repository {
582580
return { success: false as const, error: "Project not found" };
583581
}
584582

585-
const environmentVariable = await this.prismaClient.environmentVariable.findUnique({
583+
const environmentVariable = await this.prismaClient.environmentVariable.findFirst({
586584
select: {
587585
id: true,
588586
key: true,
@@ -619,7 +617,7 @@ export class EnvironmentVariablesRepository implements Repository {
619617
}
620618

621619
try {
622-
await $transaction(this.prismaClient, async (tx) => {
620+
await $transaction(this.prismaClient, "delete env var value", async (tx) => {
623621
const secretStore = getSecretStore("DATABASE", {
624622
prismaClient: tx,
625623
});

apps/webapp/app/v3/marqs/devQueueConsumer.server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export class DevQueueConsumer {
8181
}
8282

8383
public async registerBackgroundWorker(id: string, inProgressRuns: string[] = []) {
84-
const backgroundWorker = await prisma.backgroundWorker.findUnique({
84+
const backgroundWorker = await prisma.backgroundWorker.findFirst({
8585
where: { friendlyId: id, runtimeEnvironmentId: this.env.id },
8686
include: {
8787
tasks: true,
@@ -170,7 +170,7 @@ export class DevQueueConsumer {
170170
public async taskHeartbeat(workerId: string, id: string) {
171171
logger.debug("[DevQueueConsumer] taskHeartbeat()", { id });
172172

173-
const taskRunAttempt = await prisma.taskRunAttempt.findUnique({
173+
const taskRunAttempt = await prisma.taskRunAttempt.findFirst({
174174
where: { friendlyId: id },
175175
});
176176

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { TaskRunErrorCodes } from "@trigger.dev/core/v3";
1111

1212
export class RequeueTaskRunService extends BaseService {
1313
public async call(runId: string) {
14-
const taskRun = await this._prisma.taskRun.findUnique({
14+
const taskRun = await this._prisma.taskRun.findFirst({
1515
where: {
1616
id: runId,
1717
},

0 commit comments

Comments
 (0)