@@ -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 ) []element ) (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+ toProcess = processTimerFn (e , toProcess , holdsInBundle )
20342033 }
20352034
20362035 nextTime = ss .processingTimeTimers .Peek ()
@@ -2054,83 +2053,40 @@ 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 ) []element {
2058+ holdsInBundle [e .holdTimestamp ]++
2059+ // We're going to process this timer!
2060+ toProcess = append (toProcess , e )
2061+ return toProcess
2062+ })
20602063}
20612064
20622065func (* 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- }
2113- }
2114-
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 )
2066+ return handleProcessingTimeTimer (ss , em , emNow , func (e element , toProcess []element , holdsInBundle map [mtime.Time ]int ) []element {
2067+ // TODO: how to deal with watermark holds for this implicit processing time timer
2068+ // holdsInBundle[e.holdTimestamp]++
2069+ state := ss .state [LinkID {}][e .window ][string (e .keyBytes )]
2070+ endOfWindowReached := e .window .MaxTimestamp () < ss .input
2071+ ready := ss .strat .IsTriggerReady (triggerInput {
2072+ newElementCount : 0 ,
2073+ endOfWindowReached : endOfWindowReached ,
2074+ emNow : emNow ,
2075+ }, & state )
2076+
2077+ if ready {
2078+ // We're going to process this trigger!
2079+ elems , _ := ss .buildTriggeredBundle (em , string (e .keyBytes ), e .window )
2080+ toProcess = append (toProcess , elems ... )
2081+ }
2082+
2083+ return toProcess
2084+ })
2085+ }
21322086
2133- return toProcess , minTs , newKeys , holdsInBundle , stillSchedulable
2087+ func (* ordinaryStageKind ) buildProcessingTimeBundle (ss * stageState , em * ElementManager , emNow mtime.Time ) (elementHeap , mtime.Time , set [string ], map [mtime.Time ]int , bool ) {
2088+ slog .Error ("ordinary stages can't have processing time elements" )
2089+ return nil , mtime .MinTimestamp , nil , nil , false
21342090}
21352091
21362092// makeInProgressBundle is common code to store a set of elements as a bundle in progress.
0 commit comments