feat(workflow): added cancellation after launching manual execution (#796)

* feat(worfklow): added cancellation after launching manual execution

* fix build error

* ack PR comments

---------

Co-authored-by: waleedlatif <waleedlatif@waleedlatifs-MacBook-Pro.local>
This commit is contained in:
Waleed Latif
2025-07-26 12:54:08 -07:00
committed by GitHub
parent 4964495abb
commit 727e5e8763
4 changed files with 189 additions and 6 deletions

View File

@@ -70,6 +70,7 @@ export class Executor {
private isDebugging = false
private contextExtensions: any = {}
private actualWorkflow: SerializedWorkflow
private isCancelled = false
constructor(
private workflowParam:
@@ -163,6 +164,15 @@ export class Executor {
this.isDebugging = useGeneralStore.getState().isDebugModeEnabled
}
/**
* Cancels the current workflow execution.
* Sets the cancellation flag to stop further execution.
*/
public cancel(): void {
logger.info('Workflow execution cancelled')
this.isCancelled = true
}
/**
* Executes the workflow and returns the result.
*
@@ -201,7 +211,7 @@ export class Executor {
let iteration = 0
const maxIterations = 100 // Safety limit for infinite loops
while (hasMoreLayers && iteration < maxIterations) {
while (hasMoreLayers && iteration < maxIterations && !this.isCancelled) {
const nextLayer = this.getNextExecutionLayer(context)
if (this.isDebugging) {
@@ -414,6 +424,24 @@ export class Executor {
iteration++
}
// Handle cancellation
if (this.isCancelled) {
trackWorkflowTelemetry('workflow_execution_cancelled', {
workflowId,
duration: Date.now() - startTime.getTime(),
blockCount: this.actualWorkflow.blocks.length,
executedBlockCount: context.executedBlocks.size,
startTime: startTime.toISOString(),
})
return {
success: false,
output: finalOutput,
error: 'Workflow execution was cancelled',
logs: context.blockLogs,
}
}
const endTime = new Date()
context.metadata.endTime = endTime.toISOString()
const duration = endTime.getTime() - startTime.getTime()
@@ -478,6 +506,16 @@ export class Executor {
const { setPendingBlocks } = useExecutionStore.getState()
let finalOutput: NormalizedBlockOutput = {}
// Check for cancellation
if (this.isCancelled) {
return {
success: false,
output: finalOutput,
error: 'Workflow execution was cancelled',
logs: context.blockLogs,
}
}
try {
// Execute the current layer - using the original context, not a clone
const outputs = await this.executeLayer(blockIds, context)