@@ -809,9 +809,12 @@ export function makeInterruptibleAsyncInterval(
809809 options ?: Partial < InterruptibleAsyncIntervalOptions >
810810) : InterruptibleAsyncInterval {
811811 let timerId : NodeJS . Timeout | undefined ;
812- let lastCallTime : number ;
813- let cannotBeExpedited = false ;
812+ // let lastCallTime: number;
813+ // let lastWakeTime = 0 ;
814814 let stopped = false ;
815+ let lastExecutionEnded = 0 ;
816+ let executionInProgress = false ;
817+ let expeditedCheckIsScheduled = false ;
815818
816819 options = options ?? { } ;
817820 const interval = options . interval || 1000 ;
@@ -821,35 +824,56 @@ export function makeInterruptibleAsyncInterval(
821824
822825 function wake ( ) {
823826 const currentTime = clock ( ) ;
824- const nextScheduledCallTime = lastCallTime + interval ;
825- const timeUntilNextCall = nextScheduledCallTime - currentTime ;
826-
827- // For the streaming protocol: there is nothing obviously stopping this
828- // interval from being woken up again while we are waiting "infinitely"
829- // for `fn` to be called again`. Since the function effectively
830- // never completes, the `timeUntilNextCall` will continue to grow
831- // negatively unbounded, so it will never trigger a reschedule here.
832-
833- // This is possible in virtualized environments like AWS Lambda where our
834- // clock is unreliable. In these cases the timer is "running" but never
835- // actually completes, so we want to execute immediately and then attempt
836- // to reschedule.
837- if ( timeUntilNextCall < 0 ) {
838- executeAndReschedule ( ) ;
839- return ;
840- }
827+ const timeSinceLastExecutionEnded = currentTime - lastExecutionEnded ;
841828
842- // debounce multiple calls to wake within the `minInterval`
843- if ( cannotBeExpedited ) {
829+ // spec
830+ if ( executionInProgress ) {
844831 return ;
845832 }
846833
847- // reschedule a call as soon as possible, ensuring the call never happens
848- // faster than the `minInterval`
849- if ( timeUntilNextCall > minInterval ) {
834+ if ( timeSinceLastExecutionEnded < minInterval ) {
835+ if ( expeditedCheckIsScheduled ) {
836+ return ;
837+ }
838+ expeditedCheckIsScheduled = true ;
850839 reschedule ( minInterval ) ;
851- cannotBeExpedited = true ;
840+ return ;
852841 }
842+
843+ // otherwise
844+ executeAndReschedule ( ) ;
845+
846+ // ---------
847+
848+ // const timeSinceLastWake = currentTime - lastWakeTime;
849+ // const timeSinceLastCall = currentTime - lastCallTime;
850+ // const timeUntilNextCall = interval - timeSinceLastCall;
851+ // lastWakeTime = currentTime;
852+
853+ // // For the streaming protocol: there is nothing obviously stopping this
854+ // // interval from being woken up again while we are waiting "infinitely"
855+ // // for `fn` to be called again`. Since the function effectively
856+ // // never completes, the `timeUntilNextCall` will continue to grow
857+ // // negatively unbounded, so it will never trigger a reschedule here.
858+
859+ // // debounce multiple calls to wake within the `minInterval`
860+ // if (timeSinceLastWake < minInterval) {
861+ // return;
862+ // }
863+
864+ // // reschedule a call as soon as possible, ensuring the call never happens
865+ // // faster than the `minInterval`
866+ // if (timeUntilNextCall > minInterval) {
867+ // reschedule(minInterval);
868+ // }
869+
870+ // // This is possible in virtualized environments like AWS Lambda where our
871+ // // clock is unreliable. In these cases the timer is "running" but never
872+ // // actually completes, so we want to execute immediately and then attempt
873+ // // to reschedule.
874+ // if (timeUntilNextCall < 0) {
875+ // executeAndReschedule();
876+ // }
853877 }
854878
855879 function stop ( ) {
@@ -859,34 +883,42 @@ export function makeInterruptibleAsyncInterval(
859883 timerId = undefined ;
860884 }
861885
862- lastCallTime = 0 ;
863- cannotBeExpedited = false ;
886+ // lastCallTime = 0;
887+ // lastWakeTime = 0 ;
864888 }
865889
866- function reschedule ( ms ? : number ) {
890+ function reschedule ( ms : number ) {
867891 if ( stopped ) return ;
868892 if ( timerId ) {
869893 clearTimeout ( timerId ) ;
870894 }
871895
872- timerId = setTimeout ( executeAndReschedule , ms || interval ) ;
896+ timerId = setTimeout ( executeAndReschedule , ms ) ;
873897 }
874898
875899 function executeAndReschedule ( ) {
876- cannotBeExpedited = false ;
877- lastCallTime = clock ( ) ;
900+ // lastWakeTime = 0;
901+ // lastCallTime = clock();
902+
903+ if ( timerId ) {
904+ clearTimeout ( timerId ) ;
905+ }
906+
907+ executionInProgress = true ;
908+ fn ( ( ) => {
909+ executionInProgress = false ;
910+ expeditedCheckIsScheduled = false ;
911+ lastExecutionEnded = clock ( ) ;
878912
879- fn ( err => {
880- if ( err ) throw err ;
881913 reschedule ( interval ) ;
882914 } ) ;
883915 }
884916
885917 if ( immediate ) {
886918 executeAndReschedule ( ) ;
887919 } else {
888- lastCallTime = clock ( ) ;
889- reschedule ( undefined ) ;
920+ // lastCallTime = clock();
921+ reschedule ( interval ) ;
890922 }
891923
892924 return { wake, stop } ;
0 commit comments