@@ -72,6 +72,11 @@ export class Context extends RpcTarget {
7272 }
7373
7474 const status = await this . #engine. getStatus ( ) ;
75+
76+ if ( status === InstanceStatus . Paused ) {
77+ throw new Error ( ABORT_REASONS . USER_PAUSE ) ;
78+ }
79+
7580 if ( status === InstanceStatus . WaitingForPause ) {
7681 await this . #state. storage . put ( PAUSE_DATETIME , new Date ( ) ) ;
7782 const metadata =
@@ -83,7 +88,7 @@ export class Context extends RpcTarget {
8388 InstanceStatus . Paused
8489 ) ;
8590 }
86- await this . #engine . abort ( ABORT_REASONS . USER_PAUSE ) ;
91+ throw new Error ( ABORT_REASONS . USER_PAUSE ) ;
8792 }
8893 }
8994
@@ -511,8 +516,34 @@ export class Context extends RpcTarget {
511516 type : "retry" ,
512517 } ) ;
513518 await this . #engine. timeoutHandler . release ( this . #engine) ;
514- // this may never finish because of the grace period - but waker will take of it
515- await scheduler . wait ( durationMs ) ;
519+ // Race retry wait against the pause signal so pause
520+ // takes effect immediately during retries
521+ {
522+ const retryPauseSignal = this . #engine. pauseController . signal ;
523+ let pausedDuringRetry = false ;
524+ await Promise . race ( [
525+ scheduler . wait ( durationMs ) ,
526+ new Promise < void > ( ( resolve ) => {
527+ if ( retryPauseSignal . aborted ) {
528+ resolve ( ) ;
529+ return ;
530+ }
531+ retryPauseSignal . addEventListener ( "abort" , ( ) => resolve ( ) , {
532+ once : true ,
533+ } ) ;
534+ } ) ,
535+ ] ) ;
536+ const retryStatus = await this . #engine. getStatus ( ) ;
537+ if (
538+ retryStatus === InstanceStatus . Paused ||
539+ retryStatus === InstanceStatus . WaitingForPause
540+ ) {
541+ pausedDuringRetry = true ;
542+ }
543+ if ( pausedDuringRetry ) {
544+ throw new Error ( ABORT_REASONS . USER_PAUSE ) ;
545+ }
546+ }
516547
517548 // if it ever reaches here, we can try to remove it from the priority queue since it's no longer useful
518549 // @ts -expect-error priorityQueue is initiated in init
@@ -634,8 +665,37 @@ export class Context extends RpcTarget {
634665 type : "sleep" ,
635666 } ) ;
636667
637- // this probably will never finish except if sleep is less than the grace period
638- await scheduler . wait ( disableSleep ? 0 : duration ) ;
668+ // Race the sleep against the pause signal
669+ const pauseSignal = this . #engine. pauseController . signal ;
670+ const sleepDuration = disableSleep ? 0 : duration ;
671+
672+ let pausedDuringSleep = false ;
673+ await Promise . race ( [
674+ scheduler . wait ( sleepDuration ) ,
675+ new Promise < void > ( ( resolve ) => {
676+ if ( pauseSignal . aborted ) {
677+ resolve ( ) ;
678+ return ;
679+ }
680+ pauseSignal . addEventListener ( "abort" , ( ) => resolve ( ) , {
681+ once : true ,
682+ } ) ;
683+ } ) ,
684+ ] ) ;
685+
686+ // Check if we were paused during the sleep
687+ const statusAfterSleep = await this . #engine. getStatus ( ) ;
688+ if (
689+ statusAfterSleep === InstanceStatus . Paused ||
690+ statusAfterSleep === InstanceStatus . WaitingForPause
691+ ) {
692+ pausedDuringSleep = true ;
693+ }
694+
695+ if ( pausedDuringSleep ) {
696+ // Throw pause error
697+ throw new Error ( ABORT_REASONS . USER_PAUSE ) ;
698+ }
639699
640700 this . #engine. writeLog (
641701 InstanceEvent . SLEEP_COMPLETE ,
@@ -806,11 +866,27 @@ export class Context extends RpcTarget {
806866 this . #engine. waiters . set ( options . type , callbacks ) ;
807867 } ) ;
808868
869+ // Race event, timeout, and pause signal. If paused during waitForEvent,
870+ // throw a pause error so the workflow stops cleanly via init()'s catch
871+ const pauseSignal = this . #engine. pauseController . signal ;
872+ const pausePromise = new Promise < never > ( ( _ , reject ) => {
873+ if ( pauseSignal . aborted ) {
874+ reject ( new Error ( ABORT_REASONS . USER_PAUSE ) ) ;
875+ return ;
876+ }
877+ pauseSignal . addEventListener (
878+ "abort" ,
879+ ( ) => reject ( new Error ( ABORT_REASONS . USER_PAUSE ) ) ,
880+ { once : true }
881+ ) ;
882+ } ) ;
883+
809884 const result = await Promise . race ( [
810885 eventPromise ,
811886 timeoutEntryPQ !== undefined
812887 ? timeoutPromise ( timeoutEntryPQ . targetTimestamp - Date . now ( ) , false )
813888 : timeoutPromise ( ms ( options . timeout ) , true ) ,
889+ pausePromise ,
814890 ] )
815891 . then ( async ( event ) => {
816892 this . #engine. writeLog (
@@ -823,6 +899,14 @@ export class Context extends RpcTarget {
823899 return event ;
824900 } )
825901 . catch ( async ( error ) => {
902+ // Pause errors propagate directly to init()'s catch —
903+ // don't log them as timeouts or persist to storage
904+ if (
905+ error instanceof Error &&
906+ error . message === ABORT_REASONS . USER_PAUSE
907+ ) {
908+ throw error ;
909+ }
826910 this . #engine. writeLog (
827911 InstanceEvent . WAIT_TIMED_OUT ,
828912 cacheKey ,
0 commit comments