prodriguezdefino opened a new pull request, #41073:
URL: https://github.com/apache/beam/pull/41073

   Problem:
   In decodeTimerIter 
(sdks/go/pkg/beam/runners/prism/internal/engine/timers.go), a timer with 
clear=true decodes to an element with sequence -1, timestamp 0, and 
holdTimestamp 0. statefulStageKind.addPending handles sequence < 0 for 
event-time timers by deleting the pending timer. Processing-time timers go 
through ElementManager.triageTimers (elementmanager.go) and 
timerHandler.Persist (timers.go), and neither function checks sequence < 0:
   
       timers := th.timers(timer)
       key := timerKey{family: timer.family, tag: timer.tag, window: 
timer.window}
       newTimer := fireElement{firing: fire, timer: timer}
       if oldTimer, ok := timers[key]; ok {
           timers[key] = newTimer
           th.replace(key, oldTimer, newTimer)
           ...
           return 0
       }
       timers[key] = newTimer
       th.add(key, newTimer)
       holdChanges[newTimer.timer.holdTimestamp] += 1
       return 1
   
   When an SDK clears a processing-time timer (for example in process or inside 
another timer's callback), triageTimers rebases timestamp 0 into the past and 
schedules an immediate refresh. If a timer was pending, Persist replaces it 
with the clear element (returning 0 instead of -1), so Prism fires the cleared 
timer at once. If no timer was pending, Persist schedules a new entry 
(returning 1) and fires a timer that was never set.
   
   Fix:
   Check elm.sequence < 0 in triageTimers and timerHandler.Persist. Skip 
rebasing and stageRefreshTimes insertion for clear elements, unschedule any 
active timer from nextFiring, toFire, and order, decrement its watermark hold, 
and return -1 when an active timer was removed (or 0 when none existed). Add 
unit tests in timers_test.go and an ElementManager test in 
elementmanager_test.go.
   
   Reproduction (Python SDK on PrismRunner):
   ```python
   import time
   
   import apache_beam as beam
   from apache_beam.options.pipeline_options import PipelineOptions
   from apache_beam.testing.util import assert_that, equal_to
   from apache_beam.transforms.timeutil import TimeDomain
   from apache_beam.transforms.userstate import TimerSpec, on_timer
   from apache_beam.transforms.window import TimestampedValue
   
   class ClearProcessingTimerDoFn(beam.DoFn):
       EVENT_TIMER = TimerSpec("et", TimeDomain.WATERMARK)
       PROC_TIMER = TimerSpec("pt", TimeDomain.REAL_TIME)
   
       def process(
           self,
           element,
           et=beam.DoFn.TimerParam(EVENT_TIMER),
           pt=beam.DoFn.TimerParam(PROC_TIMER),
       ):
           et.set(10)
           pt.set(int(time.time()) + 3600)
   
       @on_timer(EVENT_TIMER)
       def on_event(self, pt=beam.DoFn.TimerParam(PROC_TIMER)):
           pt.clear()
           yield "event_fired"
   
       @on_timer(PROC_TIMER)
       def on_proc(self):
           yield "proc_fired_after_clear"
   
   if __name__ == "__main__":
       options = PipelineOptions(["--runner=PrismRunner", 
"--environment_type=LOOPBACK"])
       with beam.Pipeline(options=options) as p:
           out = (
               p
               | beam.Create([TimestampedValue(("k", 1), 1)])
               | beam.ParDo(ClearProcessingTimerDoFn())
           )
           assert_that(out, equal_to(["event_fired"]))
   ```
   
   Before the fix: Prism outputs `['event_fired', 'proc_fired_after_clear']`, 
and `assert_that` fails.
   After the fix: Prism outputs `['event_fired']`.
   
   <!--
   
   Thank you for your contribution! Follow this checklist to help us 
incorporate your contribution quickly and easily:
   
    - [ ] If this contribution is large, please file an Apache [Individual 
Contributor License Agreement](https://www.apache.org/licenses/icla.pdf).
    - [ ] Replace these instructions with a description of your change and why 
you have made it.
    - [ ] Mention the appropriate issue in your description (for example: 
`addresses #123` or `fixes #456`).
    - [ ] Update `CHANGES.md` with noteworthy changes.
   
   See [CONTRIBUTING.md]() for more details.
   
   -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to