Skip to content

Commit f31d9c2

Browse files
fix(db): keep cleanup-invoked helpers and snapshot reads on their role pools
Route markLargeValuesDeleted / pruneLargeValueMetadata (optional dbClient) and chat-cleanup's file collection through the cleanup pool, and getSnapshot through the exec pool, so the cleanup and inline-execution workloads stop borrowing the process-wide pool for these queries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NNy9Fzpfc1FdHAzYyb6Ycy
1 parent 1a8784f commit f31d9c2

5 files changed

Lines changed: 41 additions & 19 deletions

File tree

apps/sim/background/cleanup-logs.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ describe('cleanup logs worker', () => {
260260
workspaceIds: ['workspace-1'],
261261
})
262262

263-
expect(mockMarkLargeValuesDeleted).toHaveBeenCalledWith([largeValueKey])
263+
expect(mockMarkLargeValuesDeleted).toHaveBeenCalledWith([largeValueKey], expect.anything())
264264
expect(mockDeleteFileMetadata).toHaveBeenCalledTimes(2)
265265
})
266266

apps/sim/background/cleanup-logs.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async function deleteLargeValueKeys(keys: string[]): Promise<{ deleted: number;
110110

111111
if (deletedKeys.length > 0) {
112112
try {
113-
await markLargeValuesDeleted(deletedKeys)
113+
await markLargeValuesDeleted(deletedKeys, cleanupDb)
114114
} catch (error) {
115115
logger.error('Failed to mark large execution values as deleted:', { error })
116116
return { deleted: 0, failed: result.failed.length + deletedKeys.length }
@@ -356,7 +356,11 @@ async function cleanupLargeValueMetadata(workspaceIds: string[], label: string):
356356
const tombstonesDeletedBefore = new Date(
357357
Date.now() - LARGE_VALUE_TOMBSTONE_RETENTION_HOURS * 60 * 60 * 1000
358358
)
359-
const result = await pruneLargeValueMetadata({ workspaceIds, tombstonesDeletedBefore })
359+
const result = await pruneLargeValueMetadata({
360+
workspaceIds,
361+
tombstonesDeletedBefore,
362+
dbClient: cleanupDb,
363+
})
360364
logger.info(
361365
`[${label}/execution_large_value_metadata] Pruned ${result.referencesDeleted} stale references, ${result.dependenciesDeleted} dependencies, ${result.tombstonesDeleted} tombstones`
362366
)

apps/sim/lib/cleanup/chat-cleanup.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { db } from '@sim/db'
1+
import { dbFor } from '@sim/db'
22
import { copilotMessages, workspaceFiles } from '@sim/db/schema'
33
import { createLogger } from '@sim/logger'
44
import { and, inArray, isNull } from 'drizzle-orm'
@@ -10,6 +10,9 @@ import { isUsingCloudStorage, StorageService } from '@/lib/uploads'
1010

1111
const logger = createLogger('ChatCleanup')
1212

13+
/** Chat cleanup only ever runs from cleanup jobs, so its reads use the cleanup pool. */
14+
const cleanupDb = dbFor('cleanup')
15+
1316
const COPILOT_CLEANUP_BATCH_SIZE = 1000
1417
/** Bounds how many chats' `copilot_messages` rows are scanned per query. */
1518
const CHAT_FILE_COLLECT_CHUNK_SIZE = 500
@@ -41,7 +44,7 @@ export async function collectChatFiles(chatIds: string[]): Promise<FileRef[]> {
4144

4245
for (const chunk of chunkArray(chatIds, CHAT_FILE_COLLECT_CHUNK_SIZE)) {
4346
const [linkedFiles, messageRows] = await Promise.all([
44-
db
47+
cleanupDb
4548
.select({ key: workspaceFiles.key, context: workspaceFiles.context })
4649
.from(workspaceFiles)
4750
.where(
@@ -53,7 +56,7 @@ export async function collectChatFiles(chatIds: string[]): Promise<FileRef[]> {
5356
),
5457
// Scan every message row for the chat (no deleted_at filter): this is a
5558
// deletion path collecting blob keys, so attachments on any row count.
56-
db
59+
cleanupDb
5760
.select({ content: copilotMessages.content })
5861
.from(copilotMessages)
5962
.where(inArray(copilotMessages.chatId, chunk)),

apps/sim/lib/execution/payloads/large-value-metadata.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ interface PruneLargeValueMetadataOptions {
5454
tombstonesDeletedBefore: Date
5555
batchSize?: number
5656
maxRowsPerTable?: number
57+
/** Client the prune DELETEs run on. Defaults to the global pool; cleanup jobs pass `dbFor('cleanup')`. */
58+
dbClient?: LargeValueMetadataClient
5759
}
5860

5961
function parseLargeValueStorageKey(key: string): LargeValueStorageKeyParts | null {
@@ -368,19 +370,26 @@ export async function replaceLargeValueReferences(
368370
})
369371
}
370372

371-
export async function markLargeValuesDeleted(keys: string[]): Promise<void> {
373+
export async function markLargeValuesDeleted(
374+
keys: string[],
375+
dbClient: LargeValueMetadataClient = db
376+
): Promise<void> {
372377
if (keys.length === 0) {
373378
return
374379
}
375380

376-
await db
381+
await dbClient
377382
.update(executionLargeValues)
378383
.set({ deletedAt: new Date() })
379384
.where(inArray(executionLargeValues.key, keys))
380385
}
381386

382-
async function pruneStaleReferences(workspaceIds: string[], batchSize: number): Promise<number> {
383-
const rows = await db.execute<{ count: number }>(sql`
387+
async function pruneStaleReferences(
388+
workspaceIds: string[],
389+
batchSize: number,
390+
dbClient: LargeValueMetadataClient
391+
): Promise<number> {
392+
const rows = await dbClient.execute<{ count: number }>(sql`
384393
WITH deleted AS (
385394
DELETE FROM ${executionLargeValueReferences} AS ref
386395
WHERE ref.ctid IN (
@@ -418,9 +427,10 @@ async function pruneStaleReferences(workspaceIds: string[], batchSize: number):
418427

419428
async function pruneDeletedParentDependencies(
420429
workspaceIds: string[],
421-
batchSize: number
430+
batchSize: number,
431+
dbClient: LargeValueMetadataClient
422432
): Promise<number> {
423-
const rows = await db.execute<{ count: number }>(sql`
433+
const rows = await dbClient.execute<{ count: number }>(sql`
424434
WITH deleted AS (
425435
DELETE FROM ${executionLargeValueDependencies} AS dependency
426436
WHERE dependency.ctid IN (
@@ -452,9 +462,10 @@ async function pruneDeletedParentDependencies(
452462
async function pruneDeletedLargeValueTombstones(
453463
workspaceIds: string[],
454464
deletedBefore: Date,
455-
batchSize: number
465+
batchSize: number,
466+
dbClient: LargeValueMetadataClient
456467
): Promise<number> {
457-
const rows = await db.execute<{ count: number }>(sql`
468+
const rows = await dbClient.execute<{ count: number }>(sql`
458469
WITH deleted AS (
459470
DELETE FROM ${executionLargeValues} AS value
460471
WHERE value.ctid IN (
@@ -482,6 +493,7 @@ export async function pruneLargeValueMetadata({
482493
tombstonesDeletedBefore,
483494
batchSize = LARGE_VALUE_METADATA_PRUNE_BATCH_SIZE,
484495
maxRowsPerTable = LARGE_VALUE_METADATA_PRUNE_MAX_ROWS_PER_TABLE,
496+
dbClient = db,
485497
}: PruneLargeValueMetadataOptions): Promise<LargeValueMetadataPruneResult> {
486498
const result: LargeValueMetadataPruneResult = {
487499
referencesDeleted: 0,
@@ -498,15 +510,17 @@ export async function pruneLargeValueMetadata({
498510
if (referencesRemaining > 0) {
499511
result.referencesDeleted += await pruneStaleReferences(
500512
workspaceChunk,
501-
Math.min(batchSize, referencesRemaining)
513+
Math.min(batchSize, referencesRemaining),
514+
dbClient
502515
)
503516
}
504517

505518
const dependenciesRemaining = maxRowsPerTable - result.dependenciesDeleted
506519
if (dependenciesRemaining > 0) {
507520
result.dependenciesDeleted += await pruneDeletedParentDependencies(
508521
workspaceChunk,
509-
Math.min(batchSize, dependenciesRemaining)
522+
Math.min(batchSize, dependenciesRemaining),
523+
dbClient
510524
)
511525
}
512526

@@ -515,7 +529,8 @@ export async function pruneLargeValueMetadata({
515529
result.tombstonesDeleted += await pruneDeletedLargeValueTombstones(
516530
workspaceChunk,
517531
tombstonesDeletedBefore,
518-
Math.min(batchSize, tombstonesRemaining)
532+
Math.min(batchSize, tombstonesRemaining),
533+
dbClient
519534
)
520535
}
521536

apps/sim/lib/logs/execution/snapshot/service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { db, dbFor } from '@sim/db'
1+
import { dbFor } from '@sim/db'
22
import { workflowExecutionLogs, workflowExecutionSnapshots } from '@sim/db/schema'
33
import { createLogger } from '@sim/logger'
44
import { sha256Hex } from '@sim/security/hash'
@@ -81,7 +81,7 @@ export class SnapshotService implements ISnapshotService {
8181
}
8282

8383
async getSnapshot(id: string): Promise<WorkflowExecutionSnapshot | null> {
84-
const [snapshot] = await db
84+
const [snapshot] = await dbFor('exec')
8585
.select()
8686
.from(workflowExecutionSnapshots)
8787
.where(eq(workflowExecutionSnapshots.id, id))

0 commit comments

Comments
 (0)