Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,13 @@ public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT>
"Cannot access OnTimerContext outside of @OnTimer methods.");
}

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
"Cannot access OnWindowExpirationContext outside of @OnWindowExpiration methods.");
}

@Override
public RestrictionTracker<?, ?> restrictionTracker() {
throw new UnsupportedOperationException("RestrictionTracker parameters are not supported.");
Expand Down Expand Up @@ -958,6 +965,13 @@ public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT>
return this;
}

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
"Cannot access OnWindowExpirationContext outside of @OnWindowExpiration methods.");
}

@Override
public RestrictionTracker<?, ?> restrictionTracker() {
throw new UnsupportedOperationException("RestrictionTracker parameters are not supported.");
Expand Down Expand Up @@ -1299,6 +1313,12 @@ public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT>
throw new UnsupportedOperationException("OnTimerContext parameters are not supported.");
}

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
return this;
}

@Override
public RestrictionTracker<?, ?> restrictionTracker() {
throw new UnsupportedOperationException("RestrictionTracker parameters are not supported.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ class ByteBuddyDoFnInvokerFactory implements DoFnInvokerFactory {
public static final String OUTPUT_PARAMETER_METHOD = "outputReceiver";
public static final String TAGGED_OUTPUT_PARAMETER_METHOD = "taggedOutputReceiver";
public static final String ON_TIMER_CONTEXT_PARAMETER_METHOD = "onTimerContext";
public static final String ON_WINDOW_EXPIRATION_CONTEXT_PARAMETER_METHOD =
"onWindowExpirationContext";
public static final String WINDOW_PARAMETER_METHOD = "window";
public static final String PANE_INFO_PARAMETER_METHOD = "paneInfo";
public static final String PIPELINE_OPTIONS_PARAMETER_METHOD = "pipelineOptions";
Expand Down Expand Up @@ -1170,6 +1172,16 @@ public StackManipulation dispatch(OnTimerContextParameter p) {
ON_TIMER_CONTEXT_PARAMETER_METHOD, DoFn.class)));
}

@Override
public StackManipulation dispatch(
DoFnSignature.Parameter.OnWindowExpirationContextParameter p) {
return new StackManipulation.Compound(
pushDelegate,
MethodInvocation.invoke(
getExtraContextFactoryMethodDescription(
ON_WINDOW_EXPIRATION_CONTEXT_PARAMETER_METHOD, DoFn.class)));
}

@Override
public StackManipulation dispatch(WindowParameter p) {
return new StackManipulation.Compound(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ interface ArgumentProvider<InputT, OutputT> {
/** Provide a {@link DoFn.OnTimerContext} to use with the given {@link DoFn}. */
DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT> doFn);

/** Provide a {@link DoFn.OnWindowExpirationContext} to use with the given {@link DoFn}. */
DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn);

/** Provide a reference to the input element. */
InputT element(DoFn<InputT, OutputT> doFn);

Expand Down Expand Up @@ -447,6 +451,13 @@ public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT>
String.format("OnTimerContext unsupported in %s", getErrorContext()));
}

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("OnWindowExpirationContext unsupported in %s", getErrorContext()));
}

@Override
public State state(String stateId, boolean alwaysFetched) {
throw new UnsupportedOperationException(
Expand Down Expand Up @@ -538,6 +549,12 @@ public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT>
return delegate.onTimerContext(doFn);
}

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
return delegate.onWindowExpirationContext(doFn);
}

@Override
public InputT element(DoFn<InputT, OutputT> doFn) {
return delegate.element(doFn);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ public <ResultT> ResultT match(Cases<ResultT> cases) {
return cases.dispatch((ProcessContextParameter) this);
} else if (this instanceof OnTimerContextParameter) {
return cases.dispatch((OnTimerContextParameter) this);
} else if (this instanceof OnWindowExpirationContextParameter) {
return cases.dispatch((OnWindowExpirationContextParameter) this);
} else if (this instanceof WindowParameter) {
return cases.dispatch((WindowParameter) this);
} else if (this instanceof PaneInfoParameter) {
Expand Down Expand Up @@ -391,6 +393,8 @@ public interface Cases<ResultT> {

ResultT dispatch(OnTimerContextParameter p);

ResultT dispatch(OnWindowExpirationContextParameter p);

ResultT dispatch(WindowParameter p);

ResultT dispatch(PaneInfoParameter p);
Expand Down Expand Up @@ -498,6 +502,11 @@ public ResultT dispatch(OnTimerContextParameter p) {
return dispatchDefault(p);
}

@Override
public ResultT dispatch(OnWindowExpirationContextParameter p) {
return dispatchDefault(p);
}

@Override
public ResultT dispatch(WindowParameter p) {
return dispatchDefault(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ private DoFnSignatures() {}
Parameter.StateParameter.class,
Parameter.TimestampParameter.class,
Parameter.KeyParameter.class,
Parameter.SideInputParameter.class);
Parameter.SideInputParameter.class,
Parameter.OnWindowExpirationContextParameter.class);

private static final Collection<Class<? extends Parameter>>
ALLOWED_GET_INITIAL_RESTRICTION_PARAMETERS =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,12 @@ public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT>
throw new IllegalStateException();
}

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
throw new IllegalStateException();
}

@Override
public InputT element(DoFn<InputT, OutputT> doFn) {
return element;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7335,11 +7335,15 @@ public void onTimer(
@OnWindowExpiration
public void onWindowExpiration(
@AlwaysFetched @StateId(stateId) ValueState<Integer> state,
BoundedWindow window,
@Key String key,
OnWindowExpirationContext context,
OutputReceiver<Integer> r) {
Integer currentValue = MoreObjects.firstNonNull(state.read(), 0);
// verify state
assertEquals(1, (int) currentValue);
Preconditions.checkNotNull(context);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In unit tests, it is more idiomatic to use JUnit's assertNotNull instead of Guava's Preconditions.checkNotNull. Preconditions.checkNotNull throws a NullPointerException (which JUnit treats as an unexpected error), whereas assertNotNull throws an AssertionError (which JUnit treats as a test failure), providing better integration with test runners and clearer test results.

Suggested change
Preconditions.checkNotNull(context);
assertNotNull(context);

assertEquals(window, context.window());
// To check output is received from OnWindowExpiration
r.output(currentValue);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1422,16 +1422,20 @@ public void bar(
@StateId("foo") ValueState<Integer> s,
PipelineOptions p,
OutputReceiver<String> o,
MultiOutputReceiver m) {}
MultiOutputReceiver m,
OnWindowExpirationContext c) {}
}.getClass());

List<Parameter> params = sig.onWindowExpiration().extraParameters();
assertThat(params.size(), equalTo(5));
assertThat(params.size(), equalTo(6));
assertThat(params.get(0), instanceOf(WindowParameter.class));
assertThat(params.get(1), instanceOf(StateParameter.class));
assertThat(params.get(2), instanceOf(PipelineOptionsParameter.class));
assertThat(params.get(3), instanceOf(OutputReceiverParameter.class));
assertThat(params.get(4), instanceOf(TaggedOutputReceiverParameter.class));
assertThat(
params.get(5),
instanceOf(DoFnSignature.Parameter.OnWindowExpirationContextParameter.class));
}

private interface FeatureTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2250,6 +2250,13 @@ public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT>
"Cannot access OnTimerContext outside of @OnTimer methods.");
}

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
"Cannot access OnWindowExpirationContext outside of @OnWindowExpiration methods.");
}

@Override
public RestrictionTracker<?, ?> restrictionTracker() {
return currentTracker;
Expand Down Expand Up @@ -2469,6 +2476,12 @@ private void checkOnWindowExpirationTimestamp(Instant timestamp) {
private final OnWindowExpirationContext.Context context =
new OnWindowExpirationContext.Context();

@Override
public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
DoFn<InputT, OutputT> doFn) {
return context;
}

@Override
public BoundedWindow window() {
return currentWindow;
Expand Down
Loading