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

   …estStream
   
   Problem:
   In stageState.bundleReady 
(sdks/go/pkg/beam/runners/prism/internal/engine/elementmanager.go), a stateful 
stage whose upstream watermark has not changed is marked ready only after a 
stage has emitted a self-checkpointing residual:
   
       case isStatefulStage && len(ss.sides) == 0 && em.sawResidual.Load() && 
ss.hasBuildableDataLocked(upstreamW):
       case inputW == upstreamW && previousInputW == inputW:
           return mtime.MinTimestamp, false, ptimeEventsReady, injectedReady
   
   PersistBundle also skips tracking changedConsumers when 
em.sawResidual.Load() is false. When TestStream emits elements with 
AddElementEvent without advancing the watermark, upstreamW, inputW, and 
previousInputW all stay at MinTimestamp and em.sawResidual is false. Prism 
leaves the stateful stage unscheduled, decides the pipeline is quiescent, and 
runs the next TestStream AdvanceProcessingTime event before the DoFn processes 
the elements and sets its processing-time timer. In addition, 
makeTestStreamHandler (teststream.go) leaves processingTime at the zero 
time.Time instead of initializing it as its comment states.
   
   Fix:
   Add ElementManager.canHoldWatermark (true when sawResidual is set or 
testStreamHandler is present) and use it in PersistBundle and 
stageState.bundleReady so stateful stages with no side inputs and buildable 
pending data run before TestStream advances processing time. Initialize 
processingTime in makeTestStreamHandler, and add unit and pipeline tests in 
teststream_test.go and engine_test.go.
   
   Reproduction (Python SDK on PrismRunner):
   ```python
   import time
   
   import apache_beam as beam
   from apache_beam.coders import VarIntCoder
   from apache_beam.options.pipeline_options import PipelineOptions
   from apache_beam.testing.test_stream import TestStream
   from apache_beam.testing.util import assert_that, equal_to
   from apache_beam.transforms.timeutil import TimeDomain
   from apache_beam.transforms.userstate import BagStateSpec, TimerSpec, 
on_timer
   
   class BufferWithTimeoutDoFn(beam.DoFn):
       BUF = BagStateSpec("buf", VarIntCoder())
       FLUSH = TimerSpec("flush", TimeDomain.REAL_TIME)
   
       def process(
           self,
           element,
           buf=beam.DoFn.StateParam(BUF),
           flush=beam.DoFn.TimerParam(FLUSH),
       ):
           _, val = element
           if not list(buf.read()):
               flush.set(int(time.time()) + 10)
           buf.add(val)
   
       @on_timer(FLUSH)
       def on_flush(self, key=beam.DoFn.KeyParam, 
buf=beam.DoFn.StateParam(BUF)):
           vals = sorted(buf.read())
           if vals:
               buf.clear()
               yield (key, vals)
   
   if __name__ == "__main__":
       options = PipelineOptions(["--runner=PrismRunner", 
"--environment_type=LOOPBACK"])
       with beam.Pipeline(options=options) as p:
           out = (
               p
               | TestStream()
               .add_elements([("k", 1), ("k", 2)])
               .advance_processing_time(60)
               .add_elements([("k", 3)])
               .advance_processing_time(60)
               .advance_watermark_to_infinity()
               | beam.ParDo(BufferWithTimeoutDoFn())
           )
           assert_that(out, equal_to([("k", [1, 2]), ("k", [3])]))
   ```
   
   Before the fix: Prism runs `advance_processing_time(60)` before `process`, 
emits `[('k', [1, 2, 3])]`, and `assert_that` fails.
   After the fix: Prism emits `[('k', [1, 2]), ('k', [3])]`.
   
   <!--
   
   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