@@ -384,6 +384,7 @@ func (em *ElementManager) Bundles(ctx context.Context, upstreamCancelFn context.
384384 defer func () {
385385 // In case of panics in bundle generation, fail and cancel the job.
386386 if e := recover (); e != nil {
387+ slog .Error ("panic in ElementManager.Bundles watermark evaluation goroutine" , "error" , e , "traceback" , string (debug .Stack ()))
387388 upstreamCancelFn (fmt .Errorf ("panic in ElementManager.Bundles watermark evaluation goroutine: %v\n %v" , e , string (debug .Stack ())))
388389 }
389390 }()
@@ -1366,7 +1367,9 @@ func (ss *stageState) injectTriggeredBundlesIfReady(em *ElementManager, window t
13661367 // TODO: how to deal with watermark holds for this implicit processing time timer
13671368 // ss.watermarkHolds.Add(timer.holdTimestamp, 1)
13681369 ss .processingTimeTimers .Persist (firingTime , timer , notYetHolds )
1370+ em .refreshCond .L .Lock ()
13691371 em .processTimeEvents .Schedule (firingTime , ss .ID )
1372+ em .refreshCond .L .Unlock ()
13701373 em .wakeUpAt (firingTime )
13711374 }
13721375 }
@@ -1566,6 +1569,13 @@ func (ss *stageState) savePanes(bundID string, panesInBundle []bundlePane) {
15661569func (ss * stageState ) buildTriggeredBundle (em * ElementManager , key string , win typex.Window ) ([]element , int ) {
15671570 var toProcess []element
15681571 dnt := ss .pendingByKeys [key ]
1572+ if dnt == nil {
1573+ // If we set an after-processing-time trigger, but some other triggers fire or
1574+ // the end of window is reached before the first trigger could fire, then
1575+ // the pending elements are processed in other bundles, leaving a nil when
1576+ // we try to build this triggered bundle.
1577+ return toProcess , 0
1578+ }
15691579 var notYet []element
15701580
15711581 // Look at all elements for this key, and only for this window.
0 commit comments