Skip to content

Commit 5d7a8ef

Browse files
authored
Revert "Add AftersynchronizedProcessing Time as continuation trigger in Pytho…" (#35963)
This reverts commit 47eb9da.
1 parent 01feaea commit 5d7a8ef

4 files changed

Lines changed: 4 additions & 196 deletions

File tree

sdks/python/apache_beam/transforms/core.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,18 +3280,6 @@ def infer_output_type(self, input_type):
32803280
return typehints.KV[
32813281
key_type, typehints.WindowedValue[value_type]] # type: ignore[misc]
32823282

3283-
def get_windowing(self, inputs):
3284-
# Switch to the continuation trigger associated with the current trigger.
3285-
windowing = inputs[0].windowing
3286-
triggerfn = windowing.triggerfn.get_continuation_trigger()
3287-
return Windowing(
3288-
windowfn=windowing.windowfn,
3289-
triggerfn=triggerfn,
3290-
accumulation_mode=windowing.accumulation_mode,
3291-
timestamp_combiner=windowing.timestamp_combiner,
3292-
allowed_lateness=windowing.allowed_lateness,
3293-
environment_id=windowing.environment_id)
3294-
32953283
def expand(self, pcoll):
32963284
from apache_beam.transforms.trigger import DataLossReason
32973285
from apache_beam.transforms.trigger import DefaultTrigger

sdks/python/apache_beam/transforms/ptransform_test.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
from apache_beam.metrics import Metrics
4545
from apache_beam.metrics.metric import MetricsFilter
4646
from apache_beam.options.pipeline_options import PipelineOptions
47-
from apache_beam.options.pipeline_options import StandardOptions
4847
from apache_beam.options.pipeline_options import TypeOptions
4948
from apache_beam.portability import common_urns
5049
from apache_beam.testing.test_pipeline import TestPipeline
@@ -58,9 +57,6 @@
5857
from apache_beam.transforms.display import DisplayData
5958
from apache_beam.transforms.display import DisplayDataItem
6059
from apache_beam.transforms.ptransform import PTransform
61-
from apache_beam.transforms.trigger import AccumulationMode
62-
from apache_beam.transforms.trigger import AfterProcessingTime
63-
from apache_beam.transforms.trigger import _AfterSynchronizedProcessingTime
6460
from apache_beam.transforms.window import TimestampedValue
6561
from apache_beam.typehints import with_input_types
6662
from apache_beam.typehints import with_output_types
@@ -510,21 +506,6 @@ def test_group_by_key_unbounded_global_default_trigger(self):
510506
with TestPipeline(options=test_options) as pipeline:
511507
pipeline | TestStream() | beam.GroupByKey()
512508

513-
def test_group_by_key_trigger(self):
514-
options = PipelineOptions(['--allow_unsafe_triggers'])
515-
options.view_as(StandardOptions).streaming = True
516-
with TestPipeline(runner='BundleBasedDirectRunner',
517-
options=options) as pipeline:
518-
pcoll = pipeline | 'Start' >> beam.Create([(0, 0)])
519-
triggered = pcoll | 'Trigger' >> beam.WindowInto(
520-
window.GlobalWindows(),
521-
trigger=AfterProcessingTime(1),
522-
accumulation_mode=AccumulationMode.DISCARDING)
523-
output = triggered | 'Gbk' >> beam.GroupByKey()
524-
self.assertTrue(
525-
isinstance(
526-
output.windowing.triggerfn, _AfterSynchronizedProcessingTime))
527-
528509
def test_group_by_key_unsafe_trigger(self):
529510
test_options = PipelineOptions()
530511
test_options.view_as(TypeOptions).allow_unsafe_triggers = False

sdks/python/apache_beam/transforms/trigger.py

Lines changed: 4 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ def from_runner_api(proto, context):
304304
'after_each': AfterEach,
305305
'after_end_of_window': AfterWatermark,
306306
'after_processing_time': AfterProcessingTime,
307-
'after_synchronized_processing_time': _AfterSynchronizedProcessingTime,
307+
# after_processing_time, after_synchronized_processing_time
308308
'always': Always,
309309
'default': DefaultTrigger,
310310
'element_count': AfterCount,
@@ -317,17 +317,6 @@ def from_runner_api(proto, context):
317317
def to_runner_api(self, unused_context):
318318
pass
319319

320-
@abstractmethod
321-
def get_continuation_trigger(self):
322-
"""Returns:
323-
Trigger to use after a GroupBy to preserve the intention of this
324-
trigger. Specifically, triggers that are time based and intended
325-
to provide speculative results should continue providing speculative
326-
results. Triggers that fire once (or multiple times) should
327-
continue firing once (or multiple times).
328-
"""
329-
pass
330-
331320

332321
class DefaultTrigger(TriggerFn):
333322
"""Semantically Repeatedly(AfterWatermark()), but more optimized."""
@@ -377,9 +366,6 @@ def to_runner_api(self, unused_context):
377366
def has_ontime_pane(self):
378367
return True
379368

380-
def get_continuation_trigger(self):
381-
return self
382-
383369

384370
class AfterProcessingTime(TriggerFn):
385371
"""Fire exactly once after a specified delay from processing time."""
@@ -432,11 +418,6 @@ def to_runner_api(self, context):
432418
after_processing_time=beam_runner_api_pb2.Trigger.AfterProcessingTime(
433419
timestamp_transforms=[delay_proto]))
434420

435-
def get_continuation_trigger(self):
436-
# The continuation of an AfterProcessingTime trigger is an
437-
# _AfterSynchronizedProcessingTime trigger.
438-
return _AfterSynchronizedProcessingTime()
439-
440421
def has_ontime_pane(self):
441422
return False
442423

@@ -485,9 +466,6 @@ def to_runner_api(self, context):
485466
return beam_runner_api_pb2.Trigger(
486467
always=beam_runner_api_pb2.Trigger.Always())
487468

488-
def get_continuation_trigger(self):
489-
return self
490-
491469

492470
class _Never(TriggerFn):
493471
"""A trigger that never fires.
@@ -540,9 +518,6 @@ def to_runner_api(self, context):
540518
return beam_runner_api_pb2.Trigger(
541519
never=beam_runner_api_pb2.Trigger.Never())
542520

543-
def get_continuation_trigger(self):
544-
return self
545-
546521

547522
class AfterWatermark(TriggerFn):
548523
"""Fire exactly once when the watermark passes the end of the window.
@@ -556,19 +531,9 @@ class AfterWatermark(TriggerFn):
556531
LATE_TAG = _CombiningValueStateTag('is_late', any)
557532

558533
def __init__(self, early=None, late=None):
559-
self.early = self._wrap_if_not_repeatedly(early)
560-
self.late = self._wrap_if_not_repeatedly(late)
561-
562-
@staticmethod
563-
def _wrap_if_not_repeatedly(trigger):
564-
if trigger and not isinstance(trigger, Repeatedly):
565-
return Repeatedly(trigger)
566-
return trigger
567-
568-
def get_continuation_trigger(self):
569-
return AfterWatermark(
570-
self.early.get_continuation_trigger() if self.early else None,
571-
self.late.get_continuation_trigger() if self.late else None)
534+
# TODO(zhoufek): Maybe don't wrap early/late if they are already Repeatedly
535+
self.early = Repeatedly(early) if early else None
536+
self.late = Repeatedly(late) if late else None
572537

573538
def __repr__(self):
574539
qualifiers = []
@@ -708,9 +673,6 @@ def should_fire(self, time_domain, watermark, window, context):
708673
def on_fire(self, watermark, window, context):
709674
return True
710675

711-
def get_continuation_trigger(self):
712-
return AfterCount(1)
713-
714676
def reset(self, window, context):
715677
context.clear_state(self.COUNT_TAG)
716678

@@ -779,9 +741,6 @@ def to_runner_api(self, context):
779741
def has_ontime_pane(self):
780742
return self.underlying.has_ontime_pane()
781743

782-
def get_continuation_trigger(self):
783-
return Repeatedly(self.underlying.get_continuation_trigger())
784-
785744

786745
class _ParallelTriggerFn(TriggerFn, metaclass=ABCMeta):
787746
def __init__(self, *triggers):
@@ -801,12 +760,6 @@ def __hash__(self):
801760
def combine_op(self, trigger_results):
802761
pass
803762

804-
def get_continuation_trigger(self):
805-
return self.__class__(
806-
*(
807-
subtrigger.get_continuation_trigger()
808-
for subtrigger in self.triggers))
809-
810763
def on_element(self, element, window, context):
811764
for ix, trigger in enumerate(self.triggers):
812765
trigger.on_element(element, window, self._sub_context(context, ix))
@@ -944,13 +897,6 @@ def on_fire(self, watermark, window, context):
944897
context.add_state(self.INDEX_TAG, ix)
945898
return ix == len(self.triggers)
946899

947-
def get_continuation_trigger(self):
948-
return Repeatedly(
949-
AfterAny(
950-
*(
951-
subtrigger.get_continuation_trigger()
952-
for subtrigger in self.triggers)))
953-
954900
def reset(self, window, context):
955901
context.clear_state(self.INDEX_TAG)
956902
for ix, trigger in enumerate(self.triggers):
@@ -1697,60 +1643,3 @@ def __repr__(self):
16971643
state_str = '\n'.join(
16981644
'%s: %s' % (key, dict(state)) for key, state in self.state.items())
16991645
return 'timers: %s\nstate: %s' % (dict(self.timers), state_str)
1700-
1701-
1702-
class _AfterSynchronizedProcessingTime(TriggerFn):
1703-
"""A "runner's-discretion" trigger downstream of a GroupByKey
1704-
with AfterProcessingTime trigger.
1705-
1706-
In runners that directly execute this
1707-
Python code, the trigger currently always fires,
1708-
but this behavior is neither guaranteed nor
1709-
required by runners, regardless of whether they
1710-
execute triggers via Python.
1711-
1712-
_AfterSynchronizedProcessingTime is experimental
1713-
and internal-only. No backwards compatibility
1714-
guarantees.
1715-
"""
1716-
def __init__(self):
1717-
pass
1718-
1719-
def __repr__(self):
1720-
return '_AfterSynchronizedProcessingTime()'
1721-
1722-
def __eq__(self, other):
1723-
return type(self) == type(other)
1724-
1725-
def __hash__(self):
1726-
return hash(type(self))
1727-
1728-
def on_element(self, _element, _window, _context):
1729-
pass
1730-
1731-
def on_merge(self, _to_be_merged, _merge_result, _context):
1732-
pass
1733-
1734-
def should_fire(self, _time_domain, _timestamp, _window, _context):
1735-
return True
1736-
1737-
def on_fire(self, _timestamp, _window, _context):
1738-
return False
1739-
1740-
def reset(self, _window, _context):
1741-
pass
1742-
1743-
@staticmethod
1744-
def from_runner_api(_proto, _context):
1745-
return _AfterSynchronizedProcessingTime()
1746-
1747-
def to_runner_api(self, _context):
1748-
return beam_runner_api_pb2.Trigger(
1749-
after_synchronized_processing_time=beam_runner_api_pb2.Trigger.
1750-
AfterSynchronizedProcessingTime())
1751-
1752-
def has_ontime_pane(self):
1753-
return False
1754-
1755-
def get_continuation_trigger(self):
1756-
return self

sdks/python/apache_beam/transforms/trigger_test.py

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -554,56 +554,6 @@ def test_trigger_encoding(self):
554554
TriggerFn.from_runner_api(trigger_fn.to_runner_api(context), context))
555555

556556

557-
class ContinuationTriggerTest(unittest.TestCase):
558-
def test_after_all(self):
559-
self.assertEqual(
560-
AfterAll(AfterCount(2), AfterCount(5)).get_continuation_trigger(),
561-
AfterAll(AfterCount(1), AfterCount(1)))
562-
563-
def test_after_any(self):
564-
self.assertEqual(
565-
AfterAny(AfterCount(2), AfterCount(5)).get_continuation_trigger(),
566-
AfterAny(AfterCount(1), AfterCount(1)))
567-
568-
def test_after_count(self):
569-
self.assertEqual(AfterCount(1).get_continuation_trigger(), AfterCount(1))
570-
self.assertEqual(AfterCount(100).get_continuation_trigger(), AfterCount(1))
571-
572-
def test_after_each(self):
573-
self.assertEqual(
574-
AfterEach(AfterCount(2), AfterCount(5)).get_continuation_trigger(),
575-
Repeatedly(AfterAny(AfterCount(1), AfterCount(1))))
576-
577-
def test_after_processing_time(self):
578-
from apache_beam.transforms.trigger import _AfterSynchronizedProcessingTime
579-
self.assertEqual(
580-
AfterProcessingTime(10).get_continuation_trigger(),
581-
_AfterSynchronizedProcessingTime())
582-
583-
def test_after_watermark(self):
584-
self.assertEqual(
585-
AfterWatermark().get_continuation_trigger(), AfterWatermark())
586-
self.assertEqual(
587-
AfterWatermark(early=AfterCount(10),
588-
late=AfterCount(20)).get_continuation_trigger(),
589-
AfterWatermark(early=AfterCount(1), late=AfterCount(1)))
590-
591-
def test_always(self):
592-
self.assertEqual(Always().get_continuation_trigger(), Always())
593-
594-
def test_default(self):
595-
self.assertEqual(
596-
DefaultTrigger().get_continuation_trigger(), DefaultTrigger())
597-
598-
def test_never(self):
599-
self.assertEqual(_Never().get_continuation_trigger(), _Never())
600-
601-
def test_repeatedly(self):
602-
self.assertEqual(
603-
Repeatedly(AfterCount(10)).get_continuation_trigger(),
604-
Repeatedly(AfterCount(1)))
605-
606-
607557
class TriggerPipelineTest(unittest.TestCase):
608558
def test_after_processing_time(self):
609559
test_options = PipelineOptions(

0 commit comments

Comments
 (0)