Skip to content

Commit 4bd0e2a

Browse files
committed
fix(copilot): honor workflow group cancellation commit
1 parent e36ddf6 commit 4bd0e2a

2 files changed

Lines changed: 49 additions & 6 deletions

File tree

apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,42 @@ describe('POST /api/workflows/[id]/executions/[executionId]/cancel', () => {
12211221
expect(mockCancelByExecution).not.toHaveBeenCalled()
12221222
})
12231223

1224+
it('finishes workflow-group reconciliation when abort arrives during its durable commit', async () => {
1225+
const controller = new AbortController()
1226+
dbChainMockFns.limit.mockResolvedValueOnce([
1227+
{
1228+
executionDeadlineAt: null,
1229+
executionOrigin: 'workflow_group',
1230+
status: 'cancelled',
1231+
workspaceId: 'workspace-1',
1232+
},
1233+
])
1234+
mockCancelWorkflowGroupExecution.mockImplementationOnce(async () => {
1235+
controller.abort()
1236+
return {
1237+
kind: 'already_cancelled',
1238+
tableId: 'table-1',
1239+
rowId: 'row-1',
1240+
groupId: 'group-1',
1241+
}
1242+
})
1243+
mockStagePausedCancellation.mockResolvedValue({ kind: 'idle' })
1244+
mockCompletePausedCancellation.mockResolvedValue(true)
1245+
1246+
const response = await cancelWorkflowExecutionPostAuth({
1247+
workflowId: 'wf-1',
1248+
executionId: 'ex-1',
1249+
userId: 'user-1',
1250+
abortSignal: controller.signal,
1251+
})
1252+
1253+
expect(response.status).toBe(200)
1254+
await expect(response.json()).resolves.toMatchObject({ success: true, pausedCancelled: true })
1255+
expect(mockClearPausedCancellationIntent).not.toHaveBeenCalled()
1256+
expect(mockPublishWorkflowGroupCancellationEvent).toHaveBeenCalledOnce()
1257+
expect(mockCompletePausedCancellation).toHaveBeenCalledWith('ex-1', 'wf-1')
1258+
})
1259+
12241260
it('does not finalize an already-cancelled group retry until exact stop is accepted', async () => {
12251261
dbChainMockFns.limit.mockResolvedValueOnce([
12261262
{

apps/sim/lib/execution/cancel-workflow-execution-post-auth.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,11 @@ export async function cancelWorkflowExecutionPostAuth({
489489

490490
if (execution.status === 'cancelled') {
491491
let groupCancellationToPublish: PublishableWorkflowGroupCancellation | null = null
492+
let groupCancellationCommitted = false
492493
if (isWorkflowGroupExecution) {
494+
const preGroupCancellationAbort = cancellationAbortedResponse(abortSignal)
495+
if (preGroupCancellationAbort) return preGroupCancellationAbort
496+
493497
const workflowGroupCancellation = await cancelWorkflowGroupExecution({
494498
workspaceId: execution.workspaceId,
495499
workflowId,
@@ -514,6 +518,7 @@ export async function cancelWorkflowExecutionPostAuth({
514518
workflowGroupCancellation.kind === 'already_cancelled'
515519
) {
516520
groupCancellationToPublish = workflowGroupCancellation
521+
groupCancellationCommitted = true
517522
}
518523
}
519524

@@ -523,12 +528,14 @@ export async function cancelWorkflowExecutionPostAuth({
523528
executionId,
524529
workflowId
525530
)
526-
const postStageAbort = await rollbackPausedCancellationAfterAbort({
527-
stage: pausedCancellationStage,
528-
workflowId,
529-
executionId,
530-
abortSignal,
531-
})
531+
const postStageAbort = groupCancellationCommitted
532+
? null
533+
: await rollbackPausedCancellationAfterAbort({
534+
stage: pausedCancellationStage,
535+
workflowId,
536+
executionId,
537+
abortSignal,
538+
})
532539
if (postStageAbort) return postStageAbort
533540

534541
const hasPausedCancellation = isPausedCancellationStage(pausedCancellationStage)

0 commit comments

Comments
 (0)