Files
sim/apps/sim/executor/handlers/wait/wait-handler.ts
Vikhyath Mondreti 47a259b428 feat(byok): byok for hosted model capabilities (#2574)
* feat(byok): byok for hosted model capabilities

* fix type

* add ignore lint

* accidentally added feature flags

* centralize byok fetch for LLM calls

* remove feature flags ts

* fix tests

* update docs
2025-12-24 18:20:54 -08:00

114 lines
3.0 KiB
TypeScript

import { isExecutionCancelled, isRedisCancellationEnabled } from '@/lib/execution/cancellation'
import { BlockType } from '@/executor/constants'
import type { BlockHandler, ExecutionContext } from '@/executor/types'
import type { SerializedBlock } from '@/serializer/types'
const CANCELLATION_CHECK_INTERVAL_MS = 500
interface SleepOptions {
signal?: AbortSignal
executionId?: string
}
const sleep = async (ms: number, options: SleepOptions = {}): Promise<boolean> => {
const { signal, executionId } = options
const useRedis = isRedisCancellationEnabled() && !!executionId
if (!useRedis && signal?.aborted) {
return false
}
return new Promise((resolve) => {
// biome-ignore lint/style/useConst: needs to be declared before cleanup() but assigned later
let mainTimeoutId: NodeJS.Timeout | undefined
let checkIntervalId: NodeJS.Timeout | undefined
let resolved = false
const cleanup = () => {
if (mainTimeoutId) clearTimeout(mainTimeoutId)
if (checkIntervalId) clearInterval(checkIntervalId)
if (!useRedis && signal) signal.removeEventListener('abort', onAbort)
}
const onAbort = () => {
if (resolved) return
resolved = true
cleanup()
resolve(false)
}
if (useRedis) {
checkIntervalId = setInterval(async () => {
if (resolved) return
try {
const cancelled = await isExecutionCancelled(executionId!)
if (cancelled) {
resolved = true
cleanup()
resolve(false)
}
} catch {}
}, CANCELLATION_CHECK_INTERVAL_MS)
} else if (signal) {
signal.addEventListener('abort', onAbort, { once: true })
}
mainTimeoutId = setTimeout(() => {
if (resolved) return
resolved = true
cleanup()
resolve(true)
}, ms)
})
}
/**
* Handler for Wait blocks that pause workflow execution for a time delay
*/
export class WaitBlockHandler implements BlockHandler {
canHandle(block: SerializedBlock): boolean {
return block.metadata?.id === BlockType.WAIT
}
async execute(
ctx: ExecutionContext,
block: SerializedBlock,
inputs: Record<string, any>
): Promise<any> {
const timeValue = Number.parseInt(inputs.timeValue || '10', 10)
const timeUnit = inputs.timeUnit || 'seconds'
if (Number.isNaN(timeValue) || timeValue <= 0) {
throw new Error('Wait amount must be a positive number')
}
let waitMs = timeValue * 1000
if (timeUnit === 'minutes') {
waitMs = timeValue * 60 * 1000
}
const maxWaitMs = 10 * 60 * 1000
if (waitMs > maxWaitMs) {
const maxDisplay = timeUnit === 'minutes' ? '10 minutes' : '600 seconds'
throw new Error(`Wait time exceeds maximum of ${maxDisplay}`)
}
const completed = await sleep(waitMs, {
signal: ctx.abortSignal,
executionId: ctx.executionId,
})
if (!completed) {
return {
waitDuration: waitMs,
status: 'cancelled',
}
}
return {
waitDuration: waitMs,
status: 'completed',
}
}
}