apache_beam.io.watch module
Experimental Watch transform for the Python SDK.
Watch continuously watches a growing set of outputs for each input element,
calling a user poll function on an interval until a per-input termination
condition fires. It is the engine behind periodic file-discovery and any
periodic polling source.
For every input element the transform runs an independent loop:
poll -> keep never-seen-before outputs -> emit them (timestamped) ->
update watermark -> check termination -> wait(poll_interval) -> poll -> ...
The output is an unbounded PCollection of (input, output) pairs. Each
output carries the event time the poll function first reported it. Dedup
hashes each output’s key: the output itself by default, or
output_key_fn(output) when one is given. The key coder is inferred when
not passed explicitly and converted to its deterministic form, so equal keys
hash equally across workers and restarts.
By default, the Watch transform internally stores the hash of all items
seen. If the incremental items returned by the poll function guarantee
monotonic timestamp growth (new items on the next poll have timestamps
larger than the largest of the previous poll), consider setting
timestamp_cursor=True for better performance, as it replaces the hash
dedup with an O(1) event-time cursor; see Watch.
Example:
from apache_beam.io.watch import Watch, PollResult, after_total_of
from apache_beam.transforms.window import TimestampedValue
from apache_beam.utils.timestamp import Duration, Timestamp
def poll(prefix) -> PollResult[str]:
now = Timestamp.now()
outputs = [TimestampedValue(prefix + str(i), now) for i in range(3)]
return PollResult.complete(outputs)
watched = inputs | Watch(
poll,
poll_interval=Duration(seconds=5),
termination=after_total_of(60))
This API is experimental and may change in backwards-incompatible ways.
- class apache_beam.io.watch.Watch(poll_fn: Callable[[Any], PollResult], poll_interval, termination: TerminationCondition | None = None, output_coder: Coder | None = None, output_key_fn: Callable[[Any], Any] | None = None, output_key_coder: Coder | None = None, timestamp_cursor: bool = False, now_fn: Callable[[], float] | None = None)[source]
Bases:
PTransformWatches a growing set of outputs per input via a periodic poll function.
The output is an unbounded
PCollectionof(input, output)pairs.- Parameters:
poll_fn – callable
input -> PollResult, invoked once per poll round.poll_interval – delay between two poll rounds for one input, as a
Durationor in seconds.termination – per-input stop policy; defaults to
never().output_coder – coder for the poll outputs, used to keep them in the restriction state. Inferred when omitted: from a
PollFn’sdefault_output_coder(), else from the registered coder for theVof aPollResult[V]return annotation onpoll_fn.output_key_fn – derives the dedup key from an output; an output is emitted only when its key was never seen before. Defaults to the output itself.
output_key_coder – coder whose encoding of the key is hashed for dedup; inferred like
output_coderwhen omitted. It is converted withas_deterministic_coderso equal keys always hash equally; a coder with no deterministic form is rejected.timestamp_cursor – dedup by event time instead of by key. Each round emits only outputs strictly past the greatest event time already emitted, so the per-input state is a single timestamp. Requires every new output to carry an event time strictly greater than all previously emitted ones; re-listed old outputs at or below the cursor are dropped as already seen. For sources whose new outputs can arrive at or below the cursor, keep the default hash dedup. Incompatible with
output_key_fnandoutput_key_coder.now_fn – clock used for termination decisions; tests can inject one.
- class apache_beam.io.watch.PollResult(outputs: tuple[TimestampedValue, ...], watermark: Timestamp | None = None)[source]
Bases:
Generic[OutputT]Outputs produced by one poll, plus an optional explicit watermark.
watermarkofNonelets the transform infer the watermark from the earliest new output. A watermark ofMAX_TIMESTAMP(set bycomplete()) marks the input finished, so polling stops.The
OutputTtype parameter can annotate a poll function’s return type, as in-> PollResult[str]; the transform infers the output coder from it.- outputs: tuple[TimestampedValue, ...]
- static incomplete(outputs: Iterable, timestamp=None) PollResult[source]
Reports outputs and expects more; the transform infers the watermark.
A raw (non-
TimestampedValue) output is stamped withtimestampwhen given, else with the current processing time. The inferred watermark is safe only for non-decreasing event-time enumerations; out-of-order sources should callwith_watermark().
- static complete(outputs: Iterable, timestamp=None) PollResult[source]
Reports the final outputs for an input, after which polling stops.
A raw (non-
TimestampedValue) output is stamped withtimestampwhen given, else with the current processing time. The watermark is released toMAX_TIMESTAMPso downstream event-time windows close.
- with_watermark(watermark) PollResult[source]
Sets an explicit watermark, a promise that no future output for this input will have an event time below
watermark.
- class apache_beam.io.watch.PollFn[source]
Bases:
objectOptional base for a poll function
input -> PollResult.Any callable with that signature works; subclass only to attach an output coder hint via
default_output_coder():from apache_beam import coders class ListFiles(PollFn): def __call__(self, prefix): return PollResult.incomplete(list_files(prefix)) def default_output_coder(self): return coders.StrUtf8Coder()
A plain function can instead annotate its return type as
PollResult[V]and have the output coder inferred fromV.
- class apache_beam.io.watch.TerminationCondition[source]
Bases:
objectPer-input stop policy with immutable, encodable state.
Hooks follow the lifecycle of one input’s polling loop.
stateflows fromfor_new_input()through the per-round hooks and is serialized withstate_coder().
- apache_beam.io.watch.never() TerminationCondition[source]
Polls until
PollResult.complete().
- apache_beam.io.watch.after_total_of(duration) TerminationCondition[source]
Stops polling an input after
duration(aDurationor seconds) has elapsed since it was first seen.