@@ -507,6 +507,132 @@ export async function recreateRun(
507507 }
508508}
509509
510+ /**
511+ * Re-enqueue a workflow run.
512+ *
513+ * This re-enqueues the workflow orchestration layer. It's a no-op unless the workflow
514+ * got stuck due to an implementation issue in the World. Useful for debugging custom Worlds.
515+ */
516+ export async function reenqueueRun (
517+ worldEnv : EnvMap ,
518+ runId : string
519+ ) : Promise < ServerActionResult < void > > {
520+ try {
521+ const world = getWorldFromEnv ( { ...worldEnv } ) ;
522+ const run = await world . runs . get ( runId ) ;
523+ const deploymentId = run . deploymentId ;
524+
525+ await world . queue (
526+ `__wkf_workflow_${ run . workflowName } ` ,
527+ {
528+ runId,
529+ } ,
530+ {
531+ deploymentId,
532+ }
533+ ) ;
534+
535+ return createResponse ( undefined ) ;
536+ } catch ( error ) {
537+ return createServerActionError < void > ( error , 'reenqueueRun' , { runId } ) ;
538+ }
539+ }
540+
541+ export interface StopSleepResult {
542+ /** Number of pending sleeps that were stopped */
543+ stoppedCount : number ;
544+ }
545+
546+ export interface StopSleepOptions {
547+ /**
548+ * Optional list of specific correlation IDs to target.
549+ * If provided, only these sleep calls will be interrupted.
550+ * If not provided, all pending sleep calls will be interrupted.
551+ */
552+ correlationIds ?: string [ ] ;
553+ }
554+
555+ /**
556+ * Wake up a workflow run by interrupting pending sleep() calls.
557+ *
558+ * This finds wait_created events without matching wait_completed events,
559+ * creates wait_completed events for them, and then re-enqueues the run.
560+ *
561+ * @param worldEnv - Environment configuration for the World
562+ * @param runId - The run ID to wake up
563+ * @param options - Optional settings to narrow down targeting (specific correlation IDs)
564+ */
565+ export async function wakeUpRun (
566+ worldEnv : EnvMap ,
567+ runId : string ,
568+ options ?: StopSleepOptions
569+ ) : Promise < ServerActionResult < StopSleepResult > > {
570+ try {
571+ const world = getWorldFromEnv ( { ...worldEnv } ) ;
572+ const run = await world . runs . get ( runId ) ;
573+ const deploymentId = run . deploymentId ;
574+
575+ // Fetch all events for the run
576+ const eventsResult = await world . events . list ( {
577+ runId,
578+ pagination : { limit : 1000 } ,
579+ resolveData : 'none' ,
580+ } ) ;
581+
582+ // Find wait_created events without matching wait_completed events
583+ const waitCreatedEvents = eventsResult . data . filter (
584+ ( e ) => e . eventType === 'wait_created'
585+ ) ;
586+ const waitCompletedCorrelationIds = new Set (
587+ eventsResult . data
588+ . filter ( ( e ) => e . eventType === 'wait_completed' )
589+ . map ( ( e ) => e . correlationId )
590+ ) ;
591+
592+ let pendingWaits = waitCreatedEvents . filter (
593+ ( e ) => ! waitCompletedCorrelationIds . has ( e . correlationId )
594+ ) ;
595+
596+ // If specific correlation IDs are provided, filter to only those
597+ if ( options ?. correlationIds && options . correlationIds . length > 0 ) {
598+ const targetCorrelationIds = new Set ( options . correlationIds ) ;
599+ pendingWaits = pendingWaits . filter (
600+ ( e ) => e . correlationId && targetCorrelationIds . has ( e . correlationId )
601+ ) ;
602+ }
603+
604+ // Create wait_completed events for each pending wait
605+ for ( const waitEvent of pendingWaits ) {
606+ if ( waitEvent . correlationId ) {
607+ await world . events . create ( runId , {
608+ eventType : 'wait_completed' ,
609+ correlationId : waitEvent . correlationId ,
610+ } ) ;
611+ }
612+ }
613+
614+ // Re-enqueue the run to wake it up
615+ if ( pendingWaits . length > 0 ) {
616+ await world . queue (
617+ `__wkf_workflow_${ run . workflowName } ` ,
618+ {
619+ runId,
620+ } ,
621+ {
622+ deploymentId,
623+ }
624+ ) ;
625+ }
626+
627+ return createResponse ( { stoppedCount : pendingWaits . length } ) ;
628+ } catch ( error ) {
629+ return createServerActionError < StopSleepResult > ( error , 'wakeUpRun' , {
630+ runId,
631+ correlationIds : options ?. correlationIds ,
632+ } ) ;
633+ }
634+ }
635+
510636export async function readStreamServerAction (
511637 env : EnvMap ,
512638 streamId : string ,
0 commit comments