MCPcopy Create free account
hub / github.com/simstudioai/sim / runCleanupSoftDeletes

Function runCleanupSoftDeletes

apps/sim/background/cleanup-soft-deletes.ts:252–359  ·  view source on GitHub ↗
(payload: CleanupJobPayload)

Source from the content-addressed store, hash-verified

250}
251
252export async function runCleanupSoftDeletes(payload: CleanupJobPayload): Promise<void> {
253 const startTime = Date.now()
254 const { workspaceIds, retentionHours, label } = payload
255
256 if (workspaceIds.length === 0) {
257 logger.info(`[${label}] No workspaces to process`)
258 return
259 }
260
261 const retentionDate = new Date(Date.now() - retentionHours * 60 * 60 * 1000)
262 logger.info(
263 `[${label}] Processing ${workspaceIds.length} workspaces, cutoff: ${retentionDate.toISOString()}`
264 )
265
266 // Select workflows + files once. These sets drive BOTH external cleanup
267 // (chats + S3) AND the DB deletes below — selecting twice could return
268 // different subsets above the LIMIT cap and orphan or prematurely purge data.
269 const [doomedWorkflows, fileScope] = await Promise.all([
270 selectRowsByIdChunks(workspaceIds, (chunkIds, chunkLimit) =>
271 db
272 .select({ id: workflow.id })
273 .from(workflow)
274 .where(
275 and(
276 inArray(workflow.workspaceId, chunkIds),
277 isNotNull(workflow.archivedAt),
278 lt(workflow.archivedAt, retentionDate)
279 )
280 )
281 .limit(chunkLimit)
282 ),
283 selectExpiredWorkspaceFiles(workspaceIds, retentionDate),
284 ])
285
286 const doomedWorkflowIds = doomedWorkflows.map((w) => w.id)
287 let chatCleanup: { execute: () => Promise<void> } | null = null
288
289 if (doomedWorkflowIds.length > 0) {
290 const doomedChats = await selectRowsByIdChunks(doomedWorkflowIds, (chunkIds, chunkLimit) =>
291 db
292 .select({ id: copilotChats.id })
293 .from(copilotChats)
294 .where(inArray(copilotChats.workflowId, chunkIds))
295 .limit(chunkLimit)
296 )
297
298 const doomedChatIds = doomedChats.map((c) => c.id)
299 if (doomedChatIds.length > 0) {
300 chatCleanup = await prepareChatCleanup(doomedChatIds, label)
301 }
302 }
303
304 const fileStats = await cleanupWorkspaceFileStorage(fileScope)
305
306 let totalDeleted = 0
307
308 // Delete the workflow + file rows using the exact IDs we already selected.
309 const workflowResult = await deleteRowsById(

Callers 1

Calls 9

selectRowsByIdChunksFunction · 0.90
prepareChatCleanupFunction · 0.90
deleteRowsByIdFunction · 0.90
infoMethod · 0.80
executeMethod · 0.65

Tested by

no test coverage detected