Search in sources :

Example 6 with Elements

use of org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements in project beam by apache.

the class BeamFnDataOutboundAggregatorTest method testConfiguredBufferLimit.

@Test
public void testConfiguredBufferLimit() throws Exception {
    List<BeamFnApi.Elements> values = new ArrayList<>();
    AtomicBoolean onCompletedWasCalled = new AtomicBoolean();
    PipelineOptions options = PipelineOptionsFactory.create();
    options.as(ExperimentalOptions.class).setExperiments(Arrays.asList("data_buffer_size_limit=100"));
    BeamFnDataOutboundAggregator aggregator = new BeamFnDataOutboundAggregator(options, endpoint::getInstructionId, TestStreams.<Elements>withOnNext(values::add).withOnCompleted(() -> onCompletedWasCalled.set(true)).build(), false);
    // Test that nothing is emitted till the default buffer size is surpassed.
    FnDataReceiver<byte[]> dataReceiver = registerOutputLocation(aggregator, endpoint, CODER);
    aggregator.start();
    dataReceiver.accept(new byte[51]);
    assertThat(values, empty());
    // Test that when we cross the buffer, we emit.
    dataReceiver.accept(new byte[49]);
    assertEquals(messageWithData(new byte[51], new byte[49]), values.get(0));
    Receiver<?> receiver;
    if (endpoint.isTimer()) {
        receiver = Iterables.getOnlyElement(aggregator.outputTimersReceivers.values());
    } else {
        receiver = Iterables.getOnlyElement(aggregator.outputDataReceivers.values());
    }
    assertEquals(0L, receiver.getOutput().size());
    assertEquals(102L, receiver.getByteCount());
    assertEquals(2L, receiver.getElementCount());
    // Test that when we close we empty the value, and then send the stream terminator as part
    // of the same message
    dataReceiver.accept(new byte[1]);
    aggregator.sendOrCollectBufferedDataAndFinishOutboundStreams();
    // Test that receiver stats have been reset after
    // sendOrCollectBufferedDataAndFinishOutboundStreams.
    assertEquals(0L, receiver.getOutput().size());
    assertEquals(0L, receiver.getByteCount());
    assertEquals(0L, receiver.getElementCount());
    BeamFnApi.Elements.Builder builder = messageWithDataBuilder(new byte[1]);
    if (endpoint.isTimer()) {
        builder.addTimers(BeamFnApi.Elements.Timers.newBuilder().setInstructionId(endpoint.getInstructionId()).setTransformId(endpoint.getTransformId()).setTimerFamilyId(endpoint.getTimerFamilyId()).setIsLast(true));
    } else {
        builder.addData(BeamFnApi.Elements.Data.newBuilder().setInstructionId(endpoint.getInstructionId()).setTransformId(endpoint.getTransformId()).setIsLast(true));
    }
    assertEquals(builder.build(), values.get(1));
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) PipelineOptions(org.apache.beam.sdk.options.PipelineOptions) ExperimentalOptions(org.apache.beam.sdk.options.ExperimentalOptions) ArrayList(java.util.ArrayList) Elements(org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements) Test(org.junit.Test)

Example 7 with Elements

use of org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements in project beam by apache.

the class BeamFnDataOutboundAggregatorTest method testConfiguredBufferLimitMultipleEndpoints.

@Test
public void testConfiguredBufferLimitMultipleEndpoints() throws Exception {
    List<BeamFnApi.Elements> values = new ArrayList<>();
    AtomicBoolean onCompletedWasCalled = new AtomicBoolean();
    PipelineOptions options = PipelineOptionsFactory.create();
    options.as(ExperimentalOptions.class).setExperiments(Arrays.asList("data_buffer_size_limit=100"));
    BeamFnDataOutboundAggregator aggregator = new BeamFnDataOutboundAggregator(options, endpoint::getInstructionId, TestStreams.<Elements>withOnNext(values::add).withOnCompleted(() -> onCompletedWasCalled.set(true)).build(), false);
    // Test that nothing is emitted till the default buffer size is surpassed.
    LogicalEndpoint additionalEndpoint = LogicalEndpoint.data(endpoint.getInstructionId(), "additional:" + endpoint.getTransformId());
    FnDataReceiver<byte[]> dataReceiver = registerOutputLocation(aggregator, endpoint, CODER);
    FnDataReceiver<byte[]> additionalDataReceiver = registerOutputLocation(aggregator, additionalEndpoint, CODER);
    aggregator.start();
    dataReceiver.accept(new byte[51]);
    assertThat(values, empty());
    // Test that when we cross the buffer, we emit.
    additionalDataReceiver.accept(new byte[49]);
    checkEqualInAnyOrder(messageWithDataBuilder(new byte[51]).mergeFrom(messageWithDataBuilder(additionalEndpoint, new byte[49]).build()).build(), values.get(0));
    // Test that when we close we empty the value, and then the stream terminator as part
    // of the same message
    dataReceiver.accept(new byte[1]);
    aggregator.sendOrCollectBufferedDataAndFinishOutboundStreams();
    BeamFnApi.Elements.Builder builder = messageWithDataBuilder(new byte[1]);
    if (endpoint.isTimer()) {
        builder.addTimers(BeamFnApi.Elements.Timers.newBuilder().setInstructionId(endpoint.getInstructionId()).setTransformId(endpoint.getTransformId()).setTimerFamilyId(endpoint.getTimerFamilyId()).setIsLast(true));
    } else {
        builder.addData(BeamFnApi.Elements.Data.newBuilder().setInstructionId(endpoint.getInstructionId()).setTransformId(endpoint.getTransformId()).setIsLast(true));
    }
    builder.addData(BeamFnApi.Elements.Data.newBuilder().setInstructionId(additionalEndpoint.getInstructionId()).setTransformId(additionalEndpoint.getTransformId()).setIsLast(true));
    checkEqualInAnyOrder(builder.build(), values.get(1));
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) PipelineOptions(org.apache.beam.sdk.options.PipelineOptions) ExperimentalOptions(org.apache.beam.sdk.options.ExperimentalOptions) ArrayList(java.util.ArrayList) Elements(org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements) Test(org.junit.Test)

Example 8 with Elements

use of org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements in project beam by apache.

the class BeamFnDataOutboundAggregator method sendOrCollectBufferedDataAndFinishOutboundStreams.

/**
 * Closes the streams for all registered outbound endpoints. Should be called at the end of each
 * bundle. Returns the buffered Elements if the BeamFnDataOutboundAggregator started with
 * collectElementsIfNoFlushes=true, and there was no previous flush in this bundle, otherwise
 * returns null.
 */
public Elements sendOrCollectBufferedDataAndFinishOutboundStreams() {
    if (outputTimersReceivers.isEmpty() && outputDataReceivers.isEmpty()) {
        return null;
    }
    Elements.Builder bufferedElements;
    if (timeLimit > 0) {
        synchronized (flushLock) {
            bufferedElements = convertBufferForTransmission();
        }
    } else {
        bufferedElements = convertBufferForTransmission();
    }
    LOG.debug("Closing streams for instruction {} and outbound data {} and timers {}.", processBundleRequestIdSupplier.get(), outputDataReceivers, outputTimersReceivers);
    for (Map.Entry<String, Receiver<?>> entry : outputDataReceivers.entrySet()) {
        String pTransformId = entry.getKey();
        bufferedElements.addDataBuilder().setInstructionId(processBundleRequestIdSupplier.get()).setTransformId(pTransformId).setIsLast(true);
        entry.getValue().resetStats();
    }
    for (Map.Entry<TimerEndpoint, Receiver<?>> entry : outputTimersReceivers.entrySet()) {
        TimerEndpoint timerKey = entry.getKey();
        bufferedElements.addTimersBuilder().setInstructionId(processBundleRequestIdSupplier.get()).setTransformId(timerKey.pTransformId).setTimerFamilyId(timerKey.timerFamilyId).setIsLast(true);
        entry.getValue().resetStats();
    }
    if (collectElementsIfNoFlushes && !hasFlushedForBundle) {
        return bufferedElements.build();
    }
    outboundObserver.onNext(bufferedElements.build());
    // This is now at the end of a bundle, so we reset hasFlushedForBundle to prepare for new
    // bundles.
    hasFlushedForBundle = false;
    return null;
}
Also used : ByteString(org.apache.beam.vendor.grpc.v1p43p2.com.google.protobuf.ByteString) Elements(org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements) HashMap(java.util.HashMap) Map(java.util.Map)

Example 9 with Elements

use of org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements in project beam by apache.

the class BeamFnDataInboundObserver2 method multiplexElements.

/**
 * Dispatches the data and timers from the elements to corresponding receivers. Returns true if
 * all the endpoints are done after elements dispatching.
 */
public boolean multiplexElements(Elements elements) throws Exception {
    for (BeamFnApi.Elements.Data data : elements.getDataList()) {
        EndpointStatus<DataEndpoint<?>> endpoint = transformIdToDataEndpoint.get(data.getTransformId());
        if (endpoint == null) {
            throw new IllegalStateException(String.format("Unable to find inbound data receiver for instruction %s and transform %s.", data.getInstructionId(), data.getTransformId()));
        } else if (endpoint.isDone) {
            throw new IllegalStateException(String.format("Received data after inbound data receiver is done for instruction %s and transform %s.", data.getInstructionId(), data.getTransformId()));
        }
        InputStream inputStream = data.getData().newInput();
        Coder<Object> coder = (Coder<Object>) endpoint.endpoint.getCoder();
        FnDataReceiver<Object> receiver = (FnDataReceiver<Object>) endpoint.endpoint.getReceiver();
        while (inputStream.available() > 0) {
            receiver.accept(coder.decode(inputStream));
        }
        if (data.getIsLast()) {
            endpoint.isDone = true;
            numEndpointsThatAreIncomplete -= 1;
        }
    }
    for (BeamFnApi.Elements.Timers timers : elements.getTimersList()) {
        Map<String, EndpointStatus<TimerEndpoint<?>>> timerFamilyIdToEndpoints = transformIdToTimerFamilyIdToTimerEndpoint.get(timers.getTransformId());
        if (timerFamilyIdToEndpoints == null) {
            throw new IllegalStateException(String.format("Unable to find inbound timer receiver for instruction %s, transform %s, and timer family %s.", timers.getInstructionId(), timers.getTransformId(), timers.getTimerFamilyId()));
        }
        EndpointStatus<TimerEndpoint<?>> endpoint = timerFamilyIdToEndpoints.get(timers.getTimerFamilyId());
        if (endpoint == null) {
            throw new IllegalStateException(String.format("Unable to find inbound timer receiver for instruction %s, transform %s, and timer family %s.", timers.getInstructionId(), timers.getTransformId(), timers.getTimerFamilyId()));
        } else if (endpoint.isDone) {
            throw new IllegalStateException(String.format("Received timer after inbound timer receiver is done for instruction %s, transform %s, and timer family %s.", timers.getInstructionId(), timers.getTransformId(), timers.getTimerFamilyId()));
        }
        InputStream inputStream = timers.getTimers().newInput();
        Coder<Object> coder = (Coder<Object>) endpoint.endpoint.getCoder();
        FnDataReceiver<Object> receiver = (FnDataReceiver<Object>) endpoint.endpoint.getReceiver();
        while (inputStream.available() > 0) {
            receiver.accept(coder.decode(inputStream));
        }
        if (timers.getIsLast()) {
            endpoint.isDone = true;
            numEndpointsThatAreIncomplete -= 1;
        }
    }
    return numEndpointsThatAreIncomplete == 0;
}
Also used : Coder(org.apache.beam.sdk.coders.Coder) InputStream(java.io.InputStream) Elements(org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements)

Example 10 with Elements

use of org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements in project beam by apache.

the class BeamFnDataGrpcServiceTest method testMessageReceivedBySingleClientWhenThereAreMultipleClients.

@Test
public void testMessageReceivedBySingleClientWhenThereAreMultipleClients() throws Exception {
    BlockingQueue<Elements> clientInboundElements = new LinkedBlockingQueue<>();
    ExecutorService executorService = Executors.newCachedThreadPool();
    CountDownLatch waitForInboundElements = new CountDownLatch(1);
    int numberOfClients = 3;
    for (int client = 0; client < numberOfClients; ++client) {
        executorService.submit(() -> {
            ManagedChannel channel = ManagedChannelFactory.createDefault().withInterceptors(Arrays.asList(AddHarnessIdInterceptor.create(WORKER_ID))).forDescriptor(service.getApiServiceDescriptor());
            StreamObserver<BeamFnApi.Elements> outboundObserver = BeamFnDataGrpc.newStub(channel).data(TestStreams.withOnNext(clientInboundElements::add).build());
            waitForInboundElements.await();
            outboundObserver.onCompleted();
            return null;
        });
    }
    for (int i = 0; i < 3; ++i) {
        CloseableFnDataReceiver<WindowedValue<String>> consumer = service.getDataService(WORKER_ID).send(LogicalEndpoint.data(Integer.toString(i), TRANSFORM_ID), CODER);
        consumer.accept(valueInGlobalWindow("A" + i));
        consumer.accept(valueInGlobalWindow("B" + i));
        consumer.accept(valueInGlobalWindow("C" + i));
        consumer.close();
    }
    // Specifically copy the elements to a new list so we perform blocking calls on the queue
    // to ensure the elements arrive.
    List<Elements> copy = new ArrayList<>();
    for (int i = 0; i < numberOfClients; ++i) {
        copy.add(clientInboundElements.take());
    }
    assertThat(copy, containsInAnyOrder(elementsWithData("0"), elementsWithData("1"), elementsWithData("2")));
    waitForInboundElements.countDown();
}
Also used : ArrayList(java.util.ArrayList) Elements(org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) CountDownLatch(java.util.concurrent.CountDownLatch) LogicalEndpoint(org.apache.beam.sdk.fn.data.LogicalEndpoint) WindowedValue(org.apache.beam.sdk.util.WindowedValue) ExecutorService(java.util.concurrent.ExecutorService) ManagedChannel(org.apache.beam.vendor.grpc.v1p43p2.io.grpc.ManagedChannel) Test(org.junit.Test)

Aggregations

Elements (org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements)20 ArrayList (java.util.ArrayList)17 Test (org.junit.Test)17 ByteString (org.apache.beam.vendor.grpc.v1p43p2.com.google.protobuf.ByteString)13 CountDownLatch (java.util.concurrent.CountDownLatch)8 ExecutorService (java.util.concurrent.ExecutorService)7 Collection (java.util.Collection)6 BeamFnApi (org.apache.beam.model.fnexecution.v1.BeamFnApi)6 WindowedValue (org.apache.beam.sdk.util.WindowedValue)6 ManagedChannel (org.apache.beam.vendor.grpc.v1p43p2.io.grpc.ManagedChannel)6 IOException (java.io.IOException)5 LinkedBlockingQueue (java.util.concurrent.LinkedBlockingQueue)5 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 ApiServiceDescriptor (org.apache.beam.model.pipeline.v1.Endpoints.ApiServiceDescriptor)5 LogicalEndpoint (org.apache.beam.sdk.fn.data.LogicalEndpoint)5 ExperimentalOptions (org.apache.beam.sdk.options.ExperimentalOptions)5 PipelineOptions (org.apache.beam.sdk.options.PipelineOptions)5 StreamObserver (org.apache.beam.vendor.grpc.v1p43p2.io.grpc.stub.StreamObserver)5 Coder (org.apache.beam.sdk.coders.Coder)4 RunWith (org.junit.runner.RunWith)4