fix(copilot): honor workflow group cancellation commit

This commit is contained in:
Justin Blumencranz
2026-08-26 21:46:59 -07:00
parent b4617935e2
commit e6781960a5
2 changed files with 49 additions and 6 deletions
@@ -1221,6 +1221,42 @@ describe('POST /api/workflows/[id]/executions/[executionId]/cancel', () => {
expect(mockCancelByExecution).not.toHaveBeenCalled()
})
it('finishes workflow-group reconciliation when abort arrives during its durable commit', async () => {
const controller = new AbortController()
dbChainMockFns.limit.mockResolvedValueOnce([
{
executionDeadlineAt: null,
executionOrigin: 'workflow_group',
status: 'cancelled',
workspaceId: 'workspace-1',
},
])
mockCancelWorkflowGroupExecution.mockImplementationOnce(async () => {
controller.abort()
return {
kind: 'already_cancelled',
tableId: 'table-1',
rowId: 'row-1',
groupId: 'group-1',
}
})
mockStagePausedCancellation.mockResolvedValue({ kind: 'idle' })
mockCompletePausedCancellation.mockResolvedValue(true)
const response = await cancelWorkflowExecutionPostAuth({
workflowId: 'wf-1',
executionId: 'ex-1',
userId: 'user-1',
abortSignal: controller.signal,
})
expect(response.status).toBe(200)
await expect(response.json()).resolves.toMatchObject({ success: true, pausedCancelled: true })
expect(mockClearPausedCancellationIntent).not.toHaveBeenCalled()
expect(mockPublishWorkflowGroupCancellationEvent).toHaveBeenCalledOnce()
expect(mockCompletePausedCancellation).toHaveBeenCalledWith('ex-1', 'wf-1')
})
it('does not finalize an already-cancelled group retry until exact stop is accepted', async () => {
dbChainMockFns.limit.mockResolvedValueOnce([
{
@@ -489,7 +489,11 @@ export async function cancelWorkflowExecutionPostAuth({
if (execution.status === 'cancelled') {
let groupCancellationToPublish: PublishableWorkflowGroupCancellation | null = null
let groupCancellationCommitted = false
if (isWorkflowGroupExecution) {
const preGroupCancellationAbort = cancellationAbortedResponse(abortSignal)
if (preGroupCancellationAbort) return preGroupCancellationAbort
const workflowGroupCancellation = await cancelWorkflowGroupExecution({
workspaceId: execution.workspaceId,
workflowId,
@@ -514,6 +518,7 @@ export async function cancelWorkflowExecutionPostAuth({
workflowGroupCancellation.kind === 'already_cancelled'
) {
groupCancellationToPublish = workflowGroupCancellation
groupCancellationCommitted = true
}
}
@@ -523,12 +528,14 @@ export async function cancelWorkflowExecutionPostAuth({
executionId,
workflowId
)
const postStageAbort = await rollbackPausedCancellationAfterAbort({
stage: pausedCancellationStage,
workflowId,
executionId,
abortSignal,
})
const postStageAbort = groupCancellationCommitted
? null
: await rollbackPausedCancellationAfterAbort({
stage: pausedCancellationStage,
workflowId,
executionId,
abortSignal,
})
if (postStageAbort) return postStageAbort
const hasPausedCancellation = isPausedCancellationStage(pausedCancellationStage)