@@ -62,6 +62,7 @@ class EventQueueProcessorBase {
6262 this . #eventType = eventType ;
6363 this . #eventSubType = eventSubType ;
6464 this . #eventConfig = config ?? { } ;
65+ this . #eventConfig. selectedDelayedEventIds ??= [ ] ;
6566 this . __parallelEventProcessing = this . #eventConfig. parallelEventProcessing ?? DEFAULT_PARALLEL_EVENT_PROCESSING ;
6667 if ( this . __parallelEventProcessing > LIMIT_PARALLEL_EVENT_PROCESSING ) {
6768 this . __parallelEventProcessing = LIMIT_PARALLEL_EVENT_PROCESSING ;
@@ -664,45 +665,49 @@ class EventQueueProcessorBase {
664665 const baseDate = Date . now ( ) ;
665666 const refDateStartAfter = new Date ( baseDate + this . #config. runInterval * 1.2 ) ;
666667 await executeInNewTransaction ( this . __baseContext , "eventQueue-getQueueEntriesAndSetToInProgress" , async ( tx ) => {
667- const entries = await tx . run (
668- SELECT . from ( this . #config. tableNameEventQueue )
669- . forUpdate ( { wait : this . #config. forUpdateTimeout } )
670- . limit ( this . selectMaxChunkSize )
671- . where (
672- "type =" ,
673- this . #eventType,
674- "AND subType=" ,
675- this . #eventSubType,
676- "AND namespace =" ,
677- this . #namespace,
678- "AND ( startAfter IS NULL OR startAfter <=" ,
679- refDateStartAfter . toISOString ( ) ,
680- " ) AND ( status =" ,
681- EventProcessingStatus . Open ,
682- "AND ( lastAttemptTimestamp <=" ,
683- this . startTime . toISOString ( ) ,
684- ...( this . isPeriodicEvent
685- ? [
686- "OR lastAttemptTimestamp IS NULL ) OR ( status =" ,
687- EventProcessingStatus . InProgress ,
688- "AND lastAttemptTimestamp <=" ,
689- new Date ( baseDate - this . #eventConfig. keepAliveMaxInProgressTime * 1000 ) . toISOString ( ) ,
690- ") )" ,
691- ]
692- : [
693- "OR lastAttemptTimestamp IS NULL ) OR ( status =" ,
694- EventProcessingStatus . Error ,
695- "AND lastAttemptTimestamp <=" ,
696- this . startTime . toISOString ( ) ,
697- ") OR ( status =" ,
698- EventProcessingStatus . InProgress ,
699- "AND lastAttemptTimestamp <=" ,
700- new Date ( baseDate - this . #eventConfig. keepAliveMaxInProgressTime * 1000 ) . toISOString ( ) ,
701- ") )" ,
702- ] )
703- )
704- . orderBy ( "createdAt" , "ID" )
705- ) ;
668+ const cqn = SELECT . from ( this . #config. tableNameEventQueue )
669+ . forUpdate ( { wait : this . #config. forUpdateTimeout } )
670+ . limit ( this . selectMaxChunkSize )
671+ . where (
672+ "type =" ,
673+ this . #eventType,
674+ "AND subType=" ,
675+ this . #eventSubType,
676+ "AND namespace =" ,
677+ this . #namespace,
678+ "AND ( startAfter IS NULL OR startAfter <=" ,
679+ refDateStartAfter . toISOString ( ) ,
680+ " ) AND ( status =" ,
681+ EventProcessingStatus . Open ,
682+ "AND ( lastAttemptTimestamp <=" ,
683+ this . startTime . toISOString ( ) ,
684+ ...( this . isPeriodicEvent
685+ ? [
686+ "OR lastAttemptTimestamp IS NULL ) OR ( status =" ,
687+ EventProcessingStatus . InProgress ,
688+ "AND lastAttemptTimestamp <=" ,
689+ new Date ( baseDate - this . #eventConfig. keepAliveMaxInProgressTime * 1000 ) . toISOString ( ) ,
690+ ") ) " ,
691+ ]
692+ : [
693+ "OR lastAttemptTimestamp IS NULL ) OR ( status =" ,
694+ EventProcessingStatus . Error ,
695+ "AND lastAttemptTimestamp <=" ,
696+ this . startTime . toISOString ( ) ,
697+ ") OR ( status =" ,
698+ EventProcessingStatus . InProgress ,
699+ "AND lastAttemptTimestamp <=" ,
700+ new Date ( baseDate - this . #eventConfig. keepAliveMaxInProgressTime * 1000 ) . toISOString ( ) ,
701+ ") )" ,
702+ ] )
703+ )
704+ . orderBy ( "createdAt" , "ID" ) ;
705+
706+ if ( this . #eventConfig. selectedDelayedEventIds ) {
707+ cqn . where ( "ID NOT IN" , this . #eventConfig. selectedDelayedEventIds ) ;
708+ }
709+
710+ const entries = await tx . run ( cqn ) ;
706711
707712 if ( ! entries . length ) {
708713 this . logger . debug ( "no entries available for processing" , {
@@ -756,7 +761,9 @@ class EventQueueProcessorBase {
756761 }
757762
758763 if ( ! eventsForProcessing . length ) {
759- this . __emptyChunkSelected = true ;
764+ if ( ! entries . length ) {
765+ this . __emptyChunkSelected = true ;
766+ }
760767 return ;
761768 }
762769
@@ -806,8 +813,11 @@ class EventQueueProcessorBase {
806813 return entry . lastAttemptsTs ;
807814 }
808815
809- #handleDelayedEvents( delayedEvents ) {
816+ #handleDelayedEvents( delayedEvents , { skipExcludeDelayedEventIds = false } = { } ) {
810817 for ( const delayedEvent of delayedEvents ) {
818+ if ( ! skipExcludeDelayedEventIds ) {
819+ this . #eventConfig. selectedDelayedEventIds . push ( delayedEvent . ID ) ;
820+ }
811821 this . #eventSchedulerInstance. scheduleEvent (
812822 this . __context . tenant ,
813823 this . #eventType,
@@ -1107,6 +1117,7 @@ class EventQueueProcessorBase {
11071117 }
11081118
11091119 const newEvent = {
1120+ ID : cds . utils . uuid ( ) ,
11101121 type : this . #eventType,
11111122 subType : this . #eventSubType,
11121123 namespace : this . #eventConfig. namespace ,
@@ -1131,16 +1142,16 @@ class EventQueueProcessorBase {
11311142 } ) ;
11321143 }
11331144
1134- this . tx . _skipEventQueueBroadcase = true ;
1145+ this . tx . _skipEventQueueBroadcast = true ;
11351146 await this . tx . run (
11361147 INSERT . into ( this . #config. tableNameEventQueue ) . entries ( {
11371148 ...newEvent ,
11381149 startAfter : newEvent . startAfter . toISOString ( ) ,
11391150 } )
11401151 ) ;
1141- this . tx . _skipEventQueueBroadcase = false ;
1152+ this . tx . _skipEventQueueBroadcast = false ;
11421153 if ( intervalInMs < this . #config. runInterval * 1.5 ) {
1143- this . #handleDelayedEvents( [ newEvent ] ) ;
1154+ this . #handleDelayedEvents( [ newEvent ] , { skipExcludeDelayedEventIds : true } ) ;
11441155 const { relative : relativeAfterSchedule } = this . #eventSchedulerInstance. calculateOffset (
11451156 this . #eventType,
11461157 this . #eventSubType,
0 commit comments