Skip to content

Commit a12f159

Browse files
committed
fix tests
1 parent 9e1a395 commit a12f159

3 files changed

Lines changed: 54 additions & 5 deletions

File tree

sdks/java/core/src/main/java/org/apache/beam/sdk/fn/data/BeamFnDataOutboundAggregator.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.beam.sdk.fn.data;
1919

2020
import static org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.Preconditions.checkNotNull;
21+
import static org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.Preconditions.checkState;
2122

2223
import java.io.IOException;
2324
import java.util.Collections;
@@ -98,15 +99,31 @@ public void prepareForInstruction(
9899
String instructionId, StreamObserver<Elements> outboundObserver) {
99100
if (timeLimit > 0) {
100101
synchronized (flushLock) {
102+
checkState(this.instructionId == null && this.outboundObserver == null);
101103
this.instructionId = instructionId;
102104
this.outboundObserver = outboundObserver;
103105
}
104106
} else {
107+
checkState(this.instructionId == null && this.outboundObserver == null);
105108
this.instructionId = instructionId;
106109
this.outboundObserver = outboundObserver;
107110
}
108111
}
109112

113+
public void finishInstruction() {
114+
if (timeLimit > 0) {
115+
synchronized (flushLock) {
116+
checkState(this.instructionId != null && this.outboundObserver != null);
117+
this.instructionId = null;
118+
this.outboundObserver = null;
119+
}
120+
} else {
121+
checkState(this.instructionId != null && this.outboundObserver != null);
122+
this.instructionId = null;
123+
this.outboundObserver = null;
124+
}
125+
}
126+
110127
/** Starts the flushing daemon thread if data_buffer_time_limit_ms is set. */
111128
public void start() {
112129
if (timeLimit > 0 && this.flushFuture == null) {
@@ -198,7 +215,6 @@ public Elements sendOrCollectBufferedDataAndFinishOutboundStreams() {
198215
} else {
199216
bufferedElements = convertBufferForTransmission();
200217
}
201-
checkNotNull(instructionId);
202218
LOG.debug(
203219
"Closing streams for instruction {} and outbound data {} and timers {}.",
204220
instructionId,
@@ -224,13 +240,10 @@ public Elements sendOrCollectBufferedDataAndFinishOutboundStreams() {
224240
entry.getValue().resetStats();
225241
}
226242
// This is the end of the bundle so we reset state to prepare for future bundles.
227-
instructionId = null;
228243
if (collectElementsIfNoFlushes && !hasFlushedForBundle) {
229-
outboundObserver = null;
230244
return bufferedElements.build();
231245
}
232246
checkNotNull(outboundObserver).onNext(bufferedElements.build());
233-
outboundObserver = null;
234247
hasFlushedForBundle = false;
235248
return null;
236249
}
@@ -247,7 +260,6 @@ public void discard() {
247260
}
248261

249262
private Elements.Builder convertBufferForTransmission() {
250-
checkNotNull(instructionId);
251263
Elements.Builder bufferedElements = Elements.newBuilder();
252264
for (Map.Entry<String, Receiver<?>> entry : outputDataReceivers.entrySet()) {
253265
if (!entry.getValue().hasBufferedOutput()) {

sdks/java/core/src/test/java/org/apache/beam/sdk/fn/data/BeamFnDataOutboundAggregatorTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.hamcrest.Matchers.empty;
2121
import static org.junit.Assert.assertEquals;
2222
import static org.junit.Assert.assertFalse;
23+
import static org.junit.Assert.assertThrows;
2324
import static org.junit.Assert.fail;
2425

2526
import java.io.IOException;
@@ -323,6 +324,37 @@ public void testConfiguredBufferLimitMultipleEndpoints() throws Exception {
323324
checkEqualInAnyOrder(builder.build(), values.get(1));
324325
}
325326

327+
@Test
328+
public void testInstructionLifecycle() {
329+
BeamFnDataOutboundAggregator aggregator =
330+
new BeamFnDataOutboundAggregator(PipelineOptionsFactory.create(), false);
331+
assertThrows(
332+
NullPointerException.class, () -> aggregator.sendElements(Elements.getDefaultInstance()));
333+
aggregator.prepareForInstruction(
334+
"testInstruction",
335+
TestStreams.withOnNext(
336+
(Consumer<Elements>)
337+
e -> {
338+
throw new RuntimeException("");
339+
})
340+
.build());
341+
assertThrows(
342+
IllegalStateException.class,
343+
() ->
344+
aggregator.prepareForInstruction(
345+
"testInstruction",
346+
TestStreams.withOnNext(
347+
(Consumer<Elements>)
348+
e -> {
349+
throw new RuntimeException("");
350+
})
351+
.build()));
352+
aggregator.finishInstruction();
353+
assertThrows(
354+
NullPointerException.class, () -> aggregator.sendElements(Elements.getDefaultInstance()));
355+
assertThrows(IllegalStateException.class, aggregator::finishInstruction);
356+
}
357+
326358
private void checkEqualInAnyOrder(Elements first, Elements second) {
327359
MatcherAssert.assertThat(
328360
first.getDataList(), Matchers.containsInAnyOrder(second.getDataList().toArray()));

sdks/java/harness/src/main/java/org/apache/beam/fn/harness/control/ProcessBundleHandler.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,10 @@ private void embedOutboundElementsIfApplicable(
637637
collectedElements.add(elements);
638638
}
639639
if (!hasFlushedAggregator) {
640+
for (BeamFnDataOutboundAggregator aggregator :
641+
bundleProcessor.getOutboundAggregators().values()) {
642+
aggregator.finishInstruction();
643+
}
640644
Elements.Builder elementsToEmbed = Elements.newBuilder();
641645
for (Elements collectedElement : collectedElements) {
642646
elementsToEmbed.mergeFrom(collectedElement);
@@ -653,6 +657,7 @@ private void embedOutboundElementsIfApplicable(
653657
if (elements != null) {
654658
aggregator.sendElements(elements);
655659
}
660+
aggregator.finishInstruction();
656661
}
657662
}
658663
}

0 commit comments

Comments
 (0)