Skip to content

Commit 8fa7231

Browse files
committed
address comments
1 parent f1005dd commit 8fa7231

6 files changed

Lines changed: 32 additions & 14 deletions

File tree

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/fork-activity-panel/fork-activity-panel.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ function jobReport(job: BackgroundWorkItem): JobReport {
139139
if (m.failed && m.failed > 0) {
140140
notes.push({ value: `${plural(m.failed, 'resource')} failed to copy`, warning: true })
141141
}
142+
if (m.clearingFailed) {
143+
notes.push({ value: 'Reference cleanup incomplete', warning: true })
144+
}
142145
return { groups, notes }
143146
}
144147

apps/sim/lib/api/contracts/workspace-fork.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ describe('forkMappableResourceTypeSchema', () => {
1212
expect(forkMappableResourceTypeSchema.safeParse('workflow').success).toBe(false)
1313
})
1414

15+
it('rejects knowledge_document (a document follows its parent knowledge base)', () => {
16+
expect(forkMappableResourceTypeSchema.safeParse('knowledge_document').success).toBe(false)
17+
})
18+
1519
it('accepts user-mappable resource types', () => {
1620
for (const type of [
1721
'oauth_credential',
1822
'service_account_credential',
1923
'env_var',
2024
'table',
2125
'knowledge_base',
22-
'knowledge_document',
2326
'file',
2427
'mcp_server',
2528
'custom_tool',

apps/sim/lib/api/contracts/workspace-fork.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,8 @@ export const backgroundWorkMetadataSchema = z
521521
failed: z.number().int().optional(),
522522
/** Count of failed resources whose dangling references were cleared post-fork (U8). */
523523
clearedReferences: z.number().int().optional(),
524+
/** True when a reference-clear phase threw, so cleanup is incomplete (placeholders not dropped). */
525+
clearingFailed: z.boolean().optional(),
524526
/** Names of the resources a fork copied, by kind, for the report breakdown. */
525527
workflowNames: z.array(z.string()).optional(),
526528
tableNames: z.array(z.string()).optional(),

apps/sim/lib/workspaces/fork/copy/cleanup-failed.test.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ describe('cleanup-failed', () => {
334334
requestId: 'test',
335335
})
336336

337-
expect(cleaned).toBe(1)
337+
expect(cleaned).toEqual({ cleared: 1, clearingFailed: false })
338338
// One draft block update + one deployed version update (only the referencing version).
339339
const updatedTables = dbMock.updates.map((u) => u.table)
340340
expect(updatedTables).toEqual([workflowBlocks, workflowDeploymentVersion])
@@ -355,7 +355,7 @@ describe('cleanup-failed', () => {
355355
requestId: 'test',
356356
})
357357

358-
expect(cleaned).toBe(1)
358+
expect(cleaned).toEqual({ cleared: 1, clearingFailed: false })
359359
// No draft block referenced the failed id AND no deployed targets were threaded, so the
360360
// deployed sweep is skipped entirely.
361361
expect(dbMock.updates).toHaveLength(0)
@@ -380,7 +380,7 @@ describe('cleanup-failed', () => {
380380
requestId: 'test',
381381
})
382382

383-
expect(cleaned).toBe(1)
383+
expect(cleaned).toEqual({ cleared: 1, clearingFailed: false })
384384
expect(dbMock.updates.map((u) => u.table)).toContain(workflowDeploymentVersion)
385385
expect(mockInvalidateDeployedStateCache).toHaveBeenCalledWith('dv-1')
386386
// Clearing succeeded, so the placeholder is dropped.
@@ -397,7 +397,7 @@ describe('cleanup-failed', () => {
397397
requestId: 'test',
398398
})
399399

400-
expect(cleaned).toBe(1)
400+
expect(cleaned).toEqual({ cleared: 1, clearingFailed: false })
401401
expect(dbMock.updates).toHaveLength(1)
402402
expect(dbMock.updates[0].table).toBe(workflowBlocks)
403403
const cleared = dbMock.updates[0].values.subBlocks as Record<string, { value: unknown }>
@@ -406,7 +406,7 @@ describe('cleanup-failed', () => {
406406
expect(dbMock.deletes).toHaveLength(0)
407407
})
408408

409-
it('skips the placeholder drop when a reference-clear phase throws', async () => {
409+
it('reports cleared:0 + clearingFailed and skips the placeholder drop when a clear phase throws', async () => {
410410
// A clear-phase failure must not drop the placeholder: that would turn an empty placeholder
411411
// into a dangling reference to a deleted row. Make the draft block UPDATE throw.
412412
dbMock.queueRead(workflow, [{ id: 'wf-1' }])
@@ -421,7 +421,8 @@ describe('cleanup-failed', () => {
421421
failures: [{ kind: 'knowledge-base', childId: 'failed-kb', documentChildIds: [] }],
422422
requestId: 'test',
423423
})
424-
expect(cleaned).toBe(1)
424+
// The count must NOT overstate: nothing was cleared and the flag marks cleanup incomplete.
425+
expect(cleaned).toEqual({ cleared: 0, clearingFailed: true })
425426
} finally {
426427
dbMock.db.update = originalUpdate
427428
}

apps/sim/lib/workspaces/fork/copy/cleanup-failed.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,21 @@ function clearFailedSubBlockReferences(
7070
* a cleanup error never aborts the others. The placeholder drop is SKIPPED when a reference-clear
7171
* phase threw - dropping it then would turn an empty placeholder into a dangling reference to a
7272
* deleted row; leaving it keeps the reference resolvable (to empty content) until a later retry.
73-
* Returns the number of failed resources cleaned, for the fork activity report.
73+
*
74+
* Returns `{ cleared, clearingFailed }` for the fork activity metadata. `clearingFailed` is true
75+
* when a reference-clear phase threw - placeholders were then NOT dropped - and `cleared` is 0 in
76+
* that case, so the report never claims references it did not actually clear. On success `cleared`
77+
* is the count of failed resources whose references were cleared.
7478
*/
7579
export async function clearFailedForkResourceReferences(params: {
7680
childWorkspaceId: string
7781
failures: ForkFailedResource[]
7882
/** Target workflows this sync deployed; their deployed versions are swept regardless of draft. */
7983
deployedTargetWorkflowIds?: string[]
8084
requestId?: string
81-
}): Promise<number> {
85+
}): Promise<{ cleared: number; clearingFailed: boolean }> {
8286
const { childWorkspaceId, failures, requestId = 'unknown' } = params
83-
if (failures.length === 0) return 0
87+
if (failures.length === 0) return { cleared: 0, clearingFailed: false }
8488

8589
const failedByKind = new Map<ForkRemapKind, Set<string>>()
8690
const markFailed = (kind: ForkRemapKind, id: string) => {
@@ -166,7 +170,7 @@ export async function clearFailedForkResourceReferences(params: {
166170
documents: docIds.length,
167171
}
168172
)
169-
return failures.length
173+
return { cleared: 0, clearingFailed: true }
170174
}
171175
try {
172176
if (tableIds.length > 0) {
@@ -185,7 +189,7 @@ export async function clearFailedForkResourceReferences(params: {
185189
})
186190
}
187191

188-
return failures.length
192+
return { cleared: failures.length, clearingFailed: false }
189193
}
190194

191195
/**

apps/sim/lib/workspaces/fork/copy/content-copy-runner.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export async function runForkContentCopy(payload: ForkContentCopyPayload): Promi
117117
kind: 'file',
118118
childKey,
119119
}))
120-
const clearedReferences = await clearFailedForkResourceReferences({
120+
const { cleared, clearingFailed } = await clearFailedForkResourceReferences({
121121
childWorkspaceId: contentPlan.childWorkspaceId,
122122
failures: [...resourceCounts.failures, ...fileFailures],
123123
deployedTargetWorkflowIds: payload.deployedTargetWorkflowIds,
@@ -132,7 +132,12 @@ export async function runForkContentCopy(payload: ForkContentCopyPayload): Promi
132132
failed > 0
133133
? `Copied ${copied} item${copied === 1 ? '' : 's'}; ${failed} could not be copied`
134134
: `Copied ${copied} item${copied === 1 ? '' : 's'}`,
135-
metadata: { copied, failed, clearedReferences },
135+
metadata: {
136+
copied,
137+
failed,
138+
clearedReferences: cleared,
139+
...(clearingFailed ? { clearingFailed: true } : {}),
140+
},
136141
})
137142
}
138143
} catch (error) {

0 commit comments

Comments
 (0)