Skip to content

Commit 6247f42

Browse files
improvement(queries): add workspaceId to execution logs, added missing indexes based on query insights (#2471)
* improvement(queries): added missing indexes * add workspaceId to execution logs * remove migration to prep merge * regen migration --------- Co-authored-by: Vikhyath Mondreti <[email protected]>
1 parent 6385d82 commit 6247f42

File tree

22 files changed

+8427
-71
lines changed

22 files changed

+8427
-71
lines changed

apps/sim/app/api/chat/[identifier]/route.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { randomUUID } from 'crypto'
22
import { db } from '@sim/db'
3-
import { chat } from '@sim/db/schema'
3+
import { chat, workflow } from '@sim/db/schema'
44
import { eq } from 'drizzle-orm'
55
import { type NextRequest, NextResponse } from 'next/server'
66
import { z } from 'zod'
@@ -94,6 +94,21 @@ export async function POST(
9494
if (!deployment.isActive) {
9595
logger.warn(`[${requestId}] Chat is not active: ${identifier}`)
9696

97+
const [workflowRecord] = await db
98+
.select({ workspaceId: workflow.workspaceId })
99+
.from(workflow)
100+
.where(eq(workflow.id, deployment.workflowId))
101+
.limit(1)
102+
103+
const workspaceId = workflowRecord?.workspaceId
104+
if (!workspaceId) {
105+
logger.warn(`[${requestId}] Cannot log: workflow ${deployment.workflowId} has no workspace`)
106+
return addCorsHeaders(
107+
createErrorResponse('This chat is currently unavailable', 403),
108+
request
109+
)
110+
}
111+
97112
const executionId = randomUUID()
98113
const loggingSession = new LoggingSession(
99114
deployment.workflowId,
@@ -104,7 +119,7 @@ export async function POST(
104119

105120
await loggingSession.safeStart({
106121
userId: deployment.userId,
107-
workspaceId: '', // Will be resolved if needed
122+
workspaceId,
108123
variables: {},
109124
})
110125

@@ -169,7 +184,14 @@ export async function POST(
169184

170185
const { actorUserId, workflowRecord } = preprocessResult
171186
const workspaceOwnerId = actorUserId!
172-
const workspaceId = workflowRecord?.workspaceId || ''
187+
const workspaceId = workflowRecord?.workspaceId
188+
if (!workspaceId) {
189+
logger.error(`[${requestId}] Workflow ${deployment.workflowId} has no workspaceId`)
190+
return addCorsHeaders(
191+
createErrorResponse('Workflow has no associated workspace', 500),
192+
request
193+
)
194+
}
173195

174196
try {
175197
const selectedOutputs: string[] = []

apps/sim/app/api/logs/export/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export async function GET(request: NextRequest) {
5757
workflowName: workflow.name,
5858
}
5959

60-
let conditions: SQL | undefined = eq(workflow.workspaceId, params.workspaceId)
60+
let conditions: SQL | undefined = eq(workflowExecutionLogs.workspaceId, params.workspaceId)
6161

6262
if (params.level && params.level !== 'all') {
6363
const levels = params.level.split(',').filter(Boolean)
@@ -134,7 +134,7 @@ export async function GET(request: NextRequest) {
134134
permissions,
135135
and(
136136
eq(permissions.entityType, 'workspace'),
137-
eq(permissions.entityId, workflow.workspaceId),
137+
eq(permissions.entityId, workflowExecutionLogs.workspaceId),
138138
eq(permissions.userId, userId)
139139
)
140140
)

apps/sim/app/api/logs/route.ts

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ export async function GET(request: NextRequest) {
130130
deploymentVersionName: sql<null>`NULL`,
131131
}
132132

133+
const workspaceFilter = eq(workflowExecutionLogs.workspaceId, params.workspaceId)
134+
133135
const baseQuery = db
134136
.select(selectColumns)
135137
.from(workflowExecutionLogs)
@@ -141,18 +143,12 @@ export async function GET(request: NextRequest) {
141143
workflowDeploymentVersion,
142144
eq(workflowDeploymentVersion.id, workflowExecutionLogs.deploymentVersionId)
143145
)
144-
.innerJoin(
145-
workflow,
146-
and(
147-
eq(workflowExecutionLogs.workflowId, workflow.id),
148-
eq(workflow.workspaceId, params.workspaceId)
149-
)
150-
)
146+
.innerJoin(workflow, eq(workflowExecutionLogs.workflowId, workflow.id))
151147
.innerJoin(
152148
permissions,
153149
and(
154150
eq(permissions.entityType, 'workspace'),
155-
eq(permissions.entityId, workflow.workspaceId),
151+
eq(permissions.entityId, workflowExecutionLogs.workspaceId),
156152
eq(permissions.userId, userId)
157153
)
158154
)
@@ -300,7 +296,7 @@ export async function GET(request: NextRequest) {
300296
}
301297

302298
const logs = await baseQuery
303-
.where(conditions)
299+
.where(and(workspaceFilter, conditions))
304300
.orderBy(desc(workflowExecutionLogs.startedAt))
305301
.limit(params.limit)
306302
.offset(params.offset)
@@ -312,22 +308,16 @@ export async function GET(request: NextRequest) {
312308
pausedExecutions,
313309
eq(pausedExecutions.executionId, workflowExecutionLogs.executionId)
314310
)
315-
.innerJoin(
316-
workflow,
317-
and(
318-
eq(workflowExecutionLogs.workflowId, workflow.id),
319-
eq(workflow.workspaceId, params.workspaceId)
320-
)
321-
)
311+
.innerJoin(workflow, eq(workflowExecutionLogs.workflowId, workflow.id))
322312
.innerJoin(
323313
permissions,
324314
and(
325315
eq(permissions.entityType, 'workspace'),
326-
eq(permissions.entityId, workflow.workspaceId),
316+
eq(permissions.entityId, workflowExecutionLogs.workspaceId),
327317
eq(permissions.userId, userId)
328318
)
329319
)
330-
.where(conditions)
320+
.where(and(eq(workflowExecutionLogs.workspaceId, params.workspaceId), conditions))
331321

332322
const countResult = await countQuery
333323

apps/sim/app/api/logs/triggers/route.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { db } from '@sim/db'
2-
import { permissions, workflow, workflowExecutionLogs } from '@sim/db/schema'
2+
import { permissions, workflowExecutionLogs } from '@sim/db/schema'
33
import { and, eq, isNotNull, sql } from 'drizzle-orm'
44
import { type NextRequest, NextResponse } from 'next/server'
55
import { z } from 'zod'
@@ -42,23 +42,17 @@ export async function GET(request: NextRequest) {
4242
trigger: workflowExecutionLogs.trigger,
4343
})
4444
.from(workflowExecutionLogs)
45-
.innerJoin(
46-
workflow,
47-
and(
48-
eq(workflowExecutionLogs.workflowId, workflow.id),
49-
eq(workflow.workspaceId, params.workspaceId)
50-
)
51-
)
5245
.innerJoin(
5346
permissions,
5447
and(
5548
eq(permissions.entityType, 'workspace'),
56-
eq(permissions.entityId, workflow.workspaceId),
49+
eq(permissions.entityId, workflowExecutionLogs.workspaceId),
5750
eq(permissions.userId, userId)
5851
)
5952
)
6053
.where(
6154
and(
55+
eq(workflowExecutionLogs.workspaceId, params.workspaceId),
6256
isNotNull(workflowExecutionLogs.trigger),
6357
sql`${workflowExecutionLogs.trigger} NOT IN ('api', 'manual', 'webhook', 'chat', 'schedule')`
6458
)

apps/sim/app/api/v1/logs/filters.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ export interface LogFilters {
2525
export function buildLogFilters(filters: LogFilters): SQL<unknown> {
2626
const conditions: SQL<unknown>[] = []
2727

28-
// Required: workspace and permissions check
29-
conditions.push(eq(workflow.workspaceId, filters.workspaceId))
28+
conditions.push(eq(workflowExecutionLogs.workspaceId, filters.workspaceId))
3029

3130
// Cursor-based pagination
3231
if (filters.cursor) {

apps/sim/app/api/v1/logs/route.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ export async function GET(request: NextRequest) {
105105
const conditions = buildLogFilters(filters)
106106
const orderBy = getOrderBy(params.order)
107107

108-
// Build and execute query
109108
const baseQuery = db
110109
.select({
111110
id: workflowExecutionLogs.id,
@@ -124,13 +123,7 @@ export async function GET(request: NextRequest) {
124123
workflowDescription: workflow.description,
125124
})
126125
.from(workflowExecutionLogs)
127-
.innerJoin(
128-
workflow,
129-
and(
130-
eq(workflowExecutionLogs.workflowId, workflow.id),
131-
eq(workflow.workspaceId, params.workspaceId)
132-
)
133-
)
126+
.innerJoin(workflow, eq(workflowExecutionLogs.workflowId, workflow.id))
134127
.innerJoin(
135128
permissions,
136129
and(
@@ -197,11 +190,8 @@ export async function GET(request: NextRequest) {
197190
return result
198191
})
199192

200-
// Get user's workflow execution limits and usage
201193
const limits = await getUserLimits(userId)
202194

203-
// Create response with limits information
204-
// The rateLimit object from checkRateLimit is for THIS API endpoint's rate limits
205195
const response = createApiResponse(
206196
{
207197
data: formattedLogs,

apps/sim/app/api/workflows/[id]/execute/route.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,16 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
409409
const actorUserId = preprocessResult.actorUserId!
410410
const workflow = preprocessResult.workflowRecord!
411411

412+
if (!workflow.workspaceId) {
413+
logger.error(`[${requestId}] Workflow ${workflowId} has no workspaceId`)
414+
return NextResponse.json({ error: 'Workflow has no associated workspace' }, { status: 500 })
415+
}
416+
const workspaceId = workflow.workspaceId
417+
412418
logger.info(`[${requestId}] Preprocessing passed`, {
413419
workflowId,
414420
actorUserId,
415-
workspaceId: workflow.workspaceId,
421+
workspaceId,
416422
})
417423

418424
if (isAsyncMode) {
@@ -460,7 +466,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
460466
)
461467

462468
const executionContext = {
463-
workspaceId: workflow.workspaceId || '',
469+
workspaceId,
464470
workflowId,
465471
executionId,
466472
}
@@ -478,7 +484,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
478484

479485
await loggingSession.safeStart({
480486
userId: actorUserId,
481-
workspaceId: workflow.workspaceId || '',
487+
workspaceId,
482488
variables: {},
483489
})
484490

@@ -507,7 +513,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
507513
requestId,
508514
executionId,
509515
workflowId,
510-
workspaceId: workflow.workspaceId ?? undefined,
516+
workspaceId,
511517
userId: actorUserId,
512518
sessionUserId: isClientSession ? userId : undefined,
513519
workflowUserId: workflow.userId,
@@ -589,7 +595,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
589595
workflow: {
590596
id: workflow.id,
591597
userId: actorUserId,
592-
workspaceId: workflow.workspaceId,
598+
workspaceId,
593599
isDeployed: workflow.isDeployed,
594600
variables: (workflow as any).variables,
595601
},
@@ -775,7 +781,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
775781
requestId,
776782
executionId,
777783
workflowId,
778-
workspaceId: workflow.workspaceId ?? undefined,
784+
workspaceId,
779785
userId: actorUserId,
780786
sessionUserId: isClientSession ? userId : undefined,
781787
workflowUserId: workflow.userId,

apps/sim/app/api/workflows/[id]/log/route.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
7070
const loggingSession = new LoggingSession(id, executionId, triggerType, requestId)
7171

7272
const userId = accessValidation.workflow.userId
73-
const workspaceId = accessValidation.workflow.workspaceId || ''
73+
const workspaceId = accessValidation.workflow.workspaceId
74+
if (!workspaceId) {
75+
logger.error(`[${requestId}] Workflow ${id} has no workspaceId`)
76+
return createErrorResponse('Workflow has no associated workspace', 500)
77+
}
7478

7579
await loggingSession.safeStart({
7680
userId,

apps/sim/background/schedule-execution.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,16 @@ async function runWorkflowExecution({
209209

210210
const mergedStates = mergeSubblockState(blocks)
211211

212+
const workspaceId = workflowRecord.workspaceId
213+
if (!workspaceId) {
214+
throw new Error(`Workflow ${payload.workflowId} has no associated workspace`)
215+
}
216+
212217
const personalEnvUserId = workflowRecord.userId
213218

214219
const { personalEncrypted, workspaceEncrypted } = await getPersonalAndWorkspaceEnv(
215220
personalEnvUserId,
216-
workflowRecord.workspaceId || undefined
221+
workspaceId
217222
)
218223

219224
const variables = EnvVarsSchema.parse({
@@ -232,7 +237,7 @@ async function runWorkflowExecution({
232237

233238
await loggingSession.safeStart({
234239
userId: actorUserId,
235-
workspaceId: workflowRecord.workspaceId || '',
240+
workspaceId,
236241
variables: variables || {},
237242
deploymentVersionId,
238243
})
@@ -241,7 +246,7 @@ async function runWorkflowExecution({
241246
requestId,
242247
executionId,
243248
workflowId: payload.workflowId,
244-
workspaceId: workflowRecord.workspaceId || '',
249+
workspaceId,
245250
userId: actorUserId,
246251
sessionUserId: undefined,
247252
workflowUserId: workflowRecord.userId,

0 commit comments

Comments
 (0)