Skip to content

Commit c6ba568

Browse files
Batch delete resources
1 parent 1ade3bf commit c6ba568

File tree

2 files changed

+36
-16
lines changed

2 files changed

+36
-16
lines changed

apps/sim/background/cleanup-soft-deletes.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,36 @@ async function cleanupTable(
5656

5757
while (hasMore && batchesProcessed < MAX_BATCHES_PER_TABLE) {
5858
try {
59-
const deleted = await db
60-
.delete(tableDef)
59+
// SELECT with LIMIT first to avoid unbounded DELETE
60+
const batch = await db
61+
.select({ id: sql<string>`id` })
62+
.from(tableDef)
6163
.where(
6264
and(
6365
inArray(workspaceIdCol, workspaceIds),
6466
isNotNull(softDeleteCol),
6567
lt(softDeleteCol, retentionDate)
6668
)
6769
)
70+
.limit(BATCH_SIZE)
71+
72+
if (batch.length === 0) {
73+
logger.info(`[${tableName}] No expired soft-deleted rows found`)
74+
hasMore = false
75+
break
76+
}
77+
78+
const ids = batch.map((r) => r.id)
79+
const deleted = await db
80+
.delete(tableDef)
81+
.where(inArray(sql`id`, ids))
6882
.returning({ id: sql`id` })
6983

7084
result.deleted += deleted.length
71-
hasMore = deleted.length === BATCH_SIZE
85+
hasMore = batch.length === BATCH_SIZE
7286
batchesProcessed++
7387

74-
if (deleted.length > 0) {
75-
logger.info(`[${tableName}] Batch ${batchesProcessed}: deleted ${deleted.length} rows`)
76-
} else {
77-
logger.info(`[${tableName}] No expired soft-deleted rows found`)
78-
}
88+
logger.info(`[${tableName}] Batch ${batchesProcessed}: deleted ${deleted.length} rows`)
7989
} catch (error) {
8090
result.failed++
8191
logger.error(`[${tableName}] Batch delete failed:`, { error })

apps/sim/background/cleanup-tasks.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ interface TableCleanupResult {
3333
async function cleanupTable(
3434
tableDef: PgTable,
3535
workspaceIdCol: PgColumn,
36-
createdAtCol: PgColumn,
36+
timestampCol: PgColumn,
3737
workspaceIds: string[],
3838
retentionDate: Date,
3939
tableName: string
@@ -46,20 +46,30 @@ async function cleanupTable(
4646

4747
while (hasMore && batchesProcessed < MAX_BATCHES_PER_TABLE) {
4848
try {
49+
// SELECT with LIMIT first to avoid unbounded DELETE
50+
const batch = await db
51+
.select({ id: sql<string>`id` })
52+
.from(tableDef)
53+
.where(and(inArray(workspaceIdCol, workspaceIds), lt(timestampCol, retentionDate)))
54+
.limit(BATCH_SIZE)
55+
56+
if (batch.length === 0) {
57+
logger.info(`[${tableName}] No expired rows found`)
58+
hasMore = false
59+
break
60+
}
61+
62+
const ids = batch.map((r) => r.id)
4963
const deleted = await db
5064
.delete(tableDef)
51-
.where(and(inArray(workspaceIdCol, workspaceIds), lt(createdAtCol, retentionDate)))
65+
.where(inArray(sql`id`, ids))
5266
.returning({ id: sql`id` })
5367

5468
result.deleted += deleted.length
55-
hasMore = deleted.length === BATCH_SIZE
69+
hasMore = batch.length === BATCH_SIZE
5670
batchesProcessed++
5771

58-
if (deleted.length > 0) {
59-
logger.info(`[${tableName}] Batch ${batchesProcessed}: deleted ${deleted.length} rows`)
60-
} else {
61-
logger.info(`[${tableName}] No expired rows found`)
62-
}
72+
logger.info(`[${tableName}] Batch ${batchesProcessed}: deleted ${deleted.length} rows`)
6373
} catch (error) {
6474
result.failed++
6575
logger.error(`[${tableName}] Batch delete failed:`, { error })

0 commit comments

Comments
 (0)