@@ -1985,7 +1985,8 @@ func (ss *stageState) startProcessingTimeBundle(em *ElementManager, emNow mtime.
19851985 return bundID , true , stillSchedulable
19861986}
19871987
1988- func (* statefulStageKind ) buildProcessingTimeBundle (ss * stageState , em * ElementManager , emNow mtime.Time ) (elementHeap , mtime.Time , set [string ], map [mtime.Time ]int , bool ) {
1988+ func handleProcessingTimeTimer (ss * stageState , em * ElementManager , emNow mtime.Time ,
1989+ processTimerFn func (e element , toProcess []element , holdsInBundle map [mtime.Time ]int )) (elementHeap , mtime.Time , set [string ], map [mtime.Time ]int , bool ) {
19891990 // TODO: Determine if it's possible and a good idea to treat all EventTime processing as a MinTime
19901991 // Special Case for ProcessingTime handling.
19911992 // Eg. Always queue EventTime elements at minTime.
@@ -2027,10 +2028,8 @@ func (*statefulStageKind) buildProcessingTimeBundle(ss *stageState, em *ElementM
20272028 if e .timestamp < minTs {
20282029 minTs = e .timestamp
20292030 }
2030- holdsInBundle [e .holdTimestamp ]++
20312031
2032- // We're going to process this timer!
2033- toProcess = append (toProcess , e )
2032+ processTimerFn (e , toProcess , holdsInBundle )
20342033 }
20352034
20362035 nextTime = ss .processingTimeTimers .Peek ()
@@ -2054,83 +2053,37 @@ func (*statefulStageKind) buildProcessingTimeBundle(ss *stageState, em *ElementM
20542053 return toProcess , minTs , newKeys , holdsInBundle , stillSchedulable
20552054}
20562055
2057- func (* ordinaryStageKind ) buildProcessingTimeBundle (ss * stageState , em * ElementManager , emNow mtime.Time ) (elementHeap , mtime.Time , set [string ], map [mtime.Time ]int , bool ) {
2058- slog .Error ("ordinary stages can't have processing time elements" )
2059- return nil , mtime .MinTimestamp , nil , nil , false
2056+ func (* statefulStageKind ) buildProcessingTimeBundle (ss * stageState , em * ElementManager , emNow mtime.Time ) (elementHeap , mtime.Time , set [string ], map [mtime.Time ]int , bool ) {
2057+ return handleProcessingTimeTimer (ss , em , emNow , func (e element , toProcess []element , holdsInBundle map [mtime.Time ]int ) {
2058+ holdsInBundle [e .holdTimestamp ]++
2059+ // We're going to process this timer!
2060+ toProcess = append (toProcess , e )
2061+ })
20602062}
20612063
20622064func (* aggregateStageKind ) buildProcessingTimeBundle (ss * stageState , em * ElementManager , emNow mtime.Time ) (elementHeap , mtime.Time , set [string ], map [mtime.Time ]int , bool ) {
2063- var toProcess []element
2064- minTs := mtime .MaxTimestamp
2065- holdsInBundle := map [mtime.Time ]int {}
2066-
2067- var notYet []fireElement
2068-
2069- nextTime := ss .processingTimeTimers .Peek ()
2070- keyCounts := map [string ]int {}
2071- newKeys := set [string ]{}
2072-
2073- for nextTime <= emNow {
2074- elems := ss .processingTimeTimers .FireAt (nextTime )
2075- for _ , e := range elems {
2076- // Check if we're already executing this timer's key.
2077- if ss .inprogressKeys .present (string (e .keyBytes )) {
2078- notYet = append (notYet , fireElement {firing : nextTime , timer : e })
2079- continue
2080- }
2081-
2082- // If we are set to have OneKeyPerBundle, and we already have a key for this bundle, we process it later.
2083- if len (keyCounts ) > 0 && OneKeyPerBundle {
2084- notYet = append (notYet , fireElement {firing : nextTime , timer : e })
2085- continue
2086- }
2087- // If we are set to have OneElementPerKey, and we already have an element for this key we set this to process later.
2088- if v := keyCounts [string (e .keyBytes )]; v > 0 && OneElementPerKey {
2089- notYet = append (notYet , fireElement {firing : nextTime , timer : e })
2090- continue
2091- }
2092- keyCounts [string (e .keyBytes )]++
2093- newKeys .insert (string (e .keyBytes ))
2094- if e .timestamp < minTs {
2095- minTs = e .timestamp
2096- }
2097- // TODO: how to deal with watermark holds for this implicit processing time timer
2098- // holdsInBundle[e.holdTimestamp]++
2099-
2100- state := ss .state [LinkID {}][e .window ][string (e .keyBytes )]
2101- endOfWindowReached := e .window .MaxTimestamp () < ss .input
2102- ready := ss .strat .IsTriggerReady (triggerInput {
2103- newElementCount : 0 ,
2104- endOfWindowReached : endOfWindowReached ,
2105- emNow : emNow ,
2106- }, & state )
2107-
2108- if ready {
2109- // We're going to process this trigger!
2110- elems , _ := ss .buildTriggeredBundle (em , string (e .keyBytes ), e .window )
2111- toProcess = append (toProcess , elems ... )
2112- }
2065+ return handleProcessingTimeTimer (ss , em , emNow , func (e element , toProcess []element , holdsInBundle map [mtime.Time ]int ) {
2066+ // TODO: how to deal with watermark holds for this implicit processing time timer
2067+ // holdsInBundle[e.holdTimestamp]++
2068+ state := ss .state [LinkID {}][e .window ][string (e .keyBytes )]
2069+ endOfWindowReached := e .window .MaxTimestamp () < ss .input
2070+ ready := ss .strat .IsTriggerReady (triggerInput {
2071+ newElementCount : 0 ,
2072+ endOfWindowReached : endOfWindowReached ,
2073+ emNow : emNow ,
2074+ }, & state )
2075+
2076+ if ready {
2077+ // We're going to process this trigger!
2078+ elems , _ := ss .buildTriggeredBundle (em , string (e .keyBytes ), e .window )
2079+ toProcess = append (toProcess , elems ... )
21132080 }
2081+ })
2082+ }
21142083
2115- nextTime = ss .processingTimeTimers .Peek ()
2116- if nextTime == mtime .MaxTimestamp {
2117- // Escape the loop if there are no more events.
2118- break
2119- }
2120- }
2121-
2122- // Reschedule unfired timers.
2123- notYetHolds := map [mtime.Time ]int {}
2124- for _ , v := range notYet {
2125- ss .processingTimeTimers .Persist (v .firing , v .timer , notYetHolds )
2126- em .processTimeEvents .Schedule (v .firing , ss .ID )
2127- em .wakeUpAt (v .firing )
2128- }
2129-
2130- // Add a refresh if there are still processing time events to process.
2131- stillSchedulable := (nextTime < emNow && nextTime != mtime .MaxTimestamp || len (notYet ) > 0 )
2132-
2133- return toProcess , minTs , newKeys , holdsInBundle , stillSchedulable
2084+ func (* ordinaryStageKind ) buildProcessingTimeBundle (ss * stageState , em * ElementManager , emNow mtime.Time ) (elementHeap , mtime.Time , set [string ], map [mtime.Time ]int , bool ) {
2085+ slog .Error ("ordinary stages can't have processing time elements" )
2086+ return nil , mtime .MinTimestamp , nil , nil , false
21342087}
21352088
21362089// makeInProgressBundle is common code to store a set of elements as a bundle in progress.
0 commit comments