Search in sources :

Example 11 with InstructionRequest

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

the class RegisterAndProcessBundleOperationTest method testRegisterOnlyOnFirstBundle.

@Test
public void testRegisterOnlyOnFirstBundle() throws Exception {
    List<BeamFnApi.InstructionRequest> requests = new ArrayList<>();
    IdGenerator idGenerator = makeIdGeneratorStartingFrom(777L);
    RegisterAndProcessBundleOperation operation = new RegisterAndProcessBundleOperation(idGenerator, new TestInstructionRequestHandler() {

        @Override
        public CompletionStage<InstructionResponse> handle(InstructionRequest request) {
            requests.add(request);
            switch(request.getRequestCase()) {
                case REGISTER:
                case PROCESS_BUNDLE:
                    return CompletableFuture.completedFuture(responseFor(request).build());
                default:
                    // block forever on other requests
                    return new CompletableFuture<>();
            }
        }
    }, mockBeamFnStateDelegator, REGISTER_REQUEST, ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of(), ImmutableTable.of(), ImmutableMap.of(), mockContext);
    // Ensure that the first time we start we send the register and process bundle requests
    assertThat(requests, empty());
    operation.start();
    assertEquals(requests.get(0), BeamFnApi.InstructionRequest.newBuilder().setInstructionId("777").setRegister(REGISTER_REQUEST).build());
    assertEquals(requests.get(1), BeamFnApi.InstructionRequest.newBuilder().setInstructionId("778").setProcessBundle(BeamFnApi.ProcessBundleRequest.newBuilder().setProcessBundleDescriptorId("555")).build());
    operation.finish();
    assertEquals(false, operation.hasFailed());
    // Ensure on restart that we only send the process bundle request
    operation.start();
    assertEquals(requests.get(2), BeamFnApi.InstructionRequest.newBuilder().setInstructionId("779").setProcessBundle(BeamFnApi.ProcessBundleRequest.newBuilder().setProcessBundleDescriptorId("555")).build());
    operation.finish();
    assertEquals(false, operation.hasFailed());
}
Also used : InstructionRequest(org.apache.beam.model.fnexecution.v1.BeamFnApi.InstructionRequest) ArrayList(java.util.ArrayList) IdGenerator(org.apache.beam.sdk.fn.IdGenerator) CompletionStage(java.util.concurrent.CompletionStage) Test(org.junit.Test)

Example 12 with InstructionRequest

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

the class RegisterAndProcessBundleOperationTest method testProcessingBundleBlocksOnFinish.

@Test
public void testProcessingBundleBlocksOnFinish() throws Exception {
    List<BeamFnApi.InstructionRequest> requests = new ArrayList<>();
    IdGenerator idGenerator = makeIdGeneratorStartingFrom(777L);
    ExecutorService executorService = Executors.newCachedThreadPool();
    RegisterAndProcessBundleOperation operation = new RegisterAndProcessBundleOperation(idGenerator, new TestInstructionRequestHandler() {

        @Override
        public CompletionStage<InstructionResponse> handle(InstructionRequest request) {
            requests.add(request);
            switch(request.getRequestCase()) {
                case REGISTER:
                    return CompletableFuture.completedFuture(responseFor(request).build());
                case PROCESS_BUNDLE:
                    CompletableFuture<InstructionResponse> responseFuture = new CompletableFuture<>();
                    executorService.submit(() -> {
                        // Purposefully sleep simulating SDK harness doing work
                        Thread.sleep(100);
                        responseFuture.complete(responseFor(request).build());
                        return null;
                    });
                    return responseFuture;
                default:
                    // Anything else hangs; nothing else should be blocking
                    return new CompletableFuture<>();
            }
        }
    }, mockBeamFnStateDelegator, REGISTER_REQUEST, ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of(), ImmutableTable.of(), ImmutableMap.of(), mockContext);
    operation.start();
    // This method blocks till the requests are completed
    operation.finish();
    assertEquals(false, operation.hasFailed());
    // Ensure that the messages were received
    assertEquals(requests.get(0), BeamFnApi.InstructionRequest.newBuilder().setInstructionId("777").setRegister(REGISTER_REQUEST).build());
    assertEquals(requests.get(1), BeamFnApi.InstructionRequest.newBuilder().setInstructionId("778").setProcessBundle(BeamFnApi.ProcessBundleRequest.newBuilder().setProcessBundleDescriptorId("555")).build());
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) InstructionRequest(org.apache.beam.model.fnexecution.v1.BeamFnApi.InstructionRequest) ArrayList(java.util.ArrayList) ExecutorService(java.util.concurrent.ExecutorService) IdGenerator(org.apache.beam.sdk.fn.IdGenerator) CompletionStage(java.util.concurrent.CompletionStage) Test(org.junit.Test)

Example 13 with InstructionRequest

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

the class FnApiControlClientPoolServiceTest method testCloseCompletesClients.

@Test
public void testCloseCompletesClients() throws Exception {
    CountDownLatch latch = new CountDownLatch(1);
    AtomicBoolean sawComplete = new AtomicBoolean();
    stub.control(new StreamObserver<InstructionRequest>() {

        @Override
        public void onNext(InstructionRequest value) {
            Assert.fail("Should never see a request");
        }

        @Override
        public void onError(Throwable t) {
            latch.countDown();
        }

        @Override
        public void onCompleted() {
            sawComplete.set(true);
            latch.countDown();
        }
    });
    pool.getSource().take(WORKER_ID, Duration.ofSeconds(2));
    server.close();
    latch.await();
    assertThat(sawComplete.get(), is(true));
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) InstructionRequest(org.apache.beam.model.fnexecution.v1.BeamFnApi.InstructionRequest) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 14 with InstructionRequest

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

the class FnHarness method main.

/**
 * Run a FnHarness with the given id and options that attaches to the specified logging and
 * control API service descriptors using the given channel factory and outbound observer factory.
 *
 * @param id Harness ID
 * @param options The options for this pipeline
 * @param runnerCapabilites
 * @param loggingApiServiceDescriptor
 * @param controlApiServiceDescriptor
 * @param statusApiServiceDescriptor
 * @param channelFactory
 * @param outboundObserverFactory
 * @param processWideCache
 * @throws Exception
 */
public static void main(String id, PipelineOptions options, Set<String> runnerCapabilites, Endpoints.ApiServiceDescriptor loggingApiServiceDescriptor, Endpoints.ApiServiceDescriptor controlApiServiceDescriptor, Endpoints.ApiServiceDescriptor statusApiServiceDescriptor, ManagedChannelFactory channelFactory, OutboundObserverFactory outboundObserverFactory, Cache<Object, Object> processWideCache) throws Exception {
    channelFactory = channelFactory.withInterceptors(ImmutableList.of(AddHarnessIdInterceptor.create(id)));
    IdGenerator idGenerator = IdGenerators.decrementingLongs();
    ShortIdMap metricsShortIds = new ShortIdMap();
    ExecutorService executorService = options.as(GcsOptions.class).getExecutorService();
    // intercepts logging and sends it to the logging service.
    try (BeamFnLoggingClient logging = new BeamFnLoggingClient(options, loggingApiServiceDescriptor, channelFactory::forDescriptor)) {
        LOG.info("Fn Harness started");
        // Register standard file systems.
        FileSystems.setDefaultPipelineOptions(options);
        EnumMap<BeamFnApi.InstructionRequest.RequestCase, ThrowingFunction<InstructionRequest, BeamFnApi.InstructionResponse.Builder>> handlers = new EnumMap<>(BeamFnApi.InstructionRequest.RequestCase.class);
        ManagedChannel channel = channelFactory.forDescriptor(controlApiServiceDescriptor);
        BeamFnControlGrpc.BeamFnControlStub controlStub = BeamFnControlGrpc.newStub(channel);
        BeamFnControlGrpc.BeamFnControlBlockingStub blockingControlStub = BeamFnControlGrpc.newBlockingStub(channel);
        BeamFnDataGrpcClient beamFnDataMultiplexer = new BeamFnDataGrpcClient(options, channelFactory::forDescriptor, outboundObserverFactory);
        BeamFnStateGrpcClientCache beamFnStateGrpcClientCache = new BeamFnStateGrpcClientCache(idGenerator, channelFactory, outboundObserverFactory);
        FinalizeBundleHandler finalizeBundleHandler = new FinalizeBundleHandler(options.as(GcsOptions.class).getExecutorService());
        Function<String, BeamFnApi.ProcessBundleDescriptor> getProcessBundleDescriptor = new Function<String, ProcessBundleDescriptor>() {

            private static final String PROCESS_BUNDLE_DESCRIPTORS = "ProcessBundleDescriptors";

            private final Cache<String, BeamFnApi.ProcessBundleDescriptor> cache = Caches.subCache(processWideCache, PROCESS_BUNDLE_DESCRIPTORS);

            @Override
            public BeamFnApi.ProcessBundleDescriptor apply(String id) {
                return cache.computeIfAbsent(id, this::loadDescriptor);
            }

            private BeamFnApi.ProcessBundleDescriptor loadDescriptor(String id) {
                return blockingControlStub.getProcessBundleDescriptor(BeamFnApi.GetProcessBundleDescriptorRequest.newBuilder().setProcessBundleDescriptorId(id).build());
            }
        };
        MetricsEnvironment.setProcessWideContainer(MetricsContainerImpl.createProcessWideContainer());
        ProcessBundleHandler processBundleHandler = new ProcessBundleHandler(options, runnerCapabilites, getProcessBundleDescriptor, beamFnDataMultiplexer, beamFnStateGrpcClientCache, finalizeBundleHandler, metricsShortIds, processWideCache);
        BeamFnStatusClient beamFnStatusClient = null;
        if (statusApiServiceDescriptor != null) {
            beamFnStatusClient = new BeamFnStatusClient(statusApiServiceDescriptor, channelFactory::forDescriptor, processBundleHandler.getBundleProcessorCache(), options, processWideCache);
        }
        // TODO(BEAM-9729): Remove once runners no longer send this instruction.
        handlers.put(BeamFnApi.InstructionRequest.RequestCase.REGISTER, request -> BeamFnApi.InstructionResponse.newBuilder().setRegister(BeamFnApi.RegisterResponse.getDefaultInstance()));
        handlers.put(BeamFnApi.InstructionRequest.RequestCase.FINALIZE_BUNDLE, finalizeBundleHandler::finalizeBundle);
        handlers.put(BeamFnApi.InstructionRequest.RequestCase.PROCESS_BUNDLE, processBundleHandler::processBundle);
        handlers.put(BeamFnApi.InstructionRequest.RequestCase.PROCESS_BUNDLE_PROGRESS, processBundleHandler::progress);
        handlers.put(BeamFnApi.InstructionRequest.RequestCase.PROCESS_BUNDLE_SPLIT, processBundleHandler::trySplit);
        handlers.put(InstructionRequest.RequestCase.MONITORING_INFOS, request -> BeamFnApi.InstructionResponse.newBuilder().setMonitoringInfos(BeamFnApi.MonitoringInfosMetadataResponse.newBuilder().putAllMonitoringInfo(StreamSupport.stream(request.getMonitoringInfos().getMonitoringInfoIdList().spliterator(), false).collect(Collectors.toMap(Function.identity(), metricsShortIds::get)))));
        HarnessMonitoringInfosInstructionHandler processWideHandler = new HarnessMonitoringInfosInstructionHandler(metricsShortIds);
        handlers.put(InstructionRequest.RequestCase.HARNESS_MONITORING_INFOS, processWideHandler::harnessMonitoringInfos);
        JvmInitializers.runBeforeProcessing(options);
        String samplingPeriodMills = ExperimentalOptions.getExperimentValue(options, ExperimentalOptions.STATE_SAMPLING_PERIOD_MILLIS);
        if (samplingPeriodMills != null) {
            ExecutionStateSampler.setSamplingPeriod(Integer.parseInt(samplingPeriodMills));
        }
        ExecutionStateSampler.instance().start();
        LOG.info("Entering instruction processing loop");
        // The control client immediately dispatches requests to an executor so we execute on the
        // direct executor. If we created separate channels for different stubs we could use
        // directExecutor() when building the channel.
        BeamFnControlClient control = new BeamFnControlClient(controlStub.withExecutor(MoreExecutors.directExecutor()), outboundObserverFactory, executorService, handlers);
        control.waitForTermination();
        if (beamFnStatusClient != null) {
            beamFnStatusClient.close();
        }
        processBundleHandler.shutdown();
    } finally {
        System.out.println("Shutting SDK harness down.");
        ExecutionStateSampler.instance().stop();
        executorService.shutdown();
    }
}
Also used : BeamFnControlClient(org.apache.beam.fn.harness.control.BeamFnControlClient) ProcessBundleDescriptor(org.apache.beam.model.fnexecution.v1.BeamFnApi.ProcessBundleDescriptor) ProcessBundleHandler(org.apache.beam.fn.harness.control.ProcessBundleHandler) BeamFnStateGrpcClientCache(org.apache.beam.fn.harness.state.BeamFnStateGrpcClientCache) ThrowingFunction(org.apache.beam.sdk.function.ThrowingFunction) Function(java.util.function.Function) BeamFnStatusClient(org.apache.beam.fn.harness.status.BeamFnStatusClient) InstructionRequest(org.apache.beam.model.fnexecution.v1.BeamFnApi.InstructionRequest) ManagedChannel(org.apache.beam.vendor.grpc.v1p43p2.io.grpc.ManagedChannel) GcsOptions(org.apache.beam.sdk.extensions.gcp.options.GcsOptions) EnumMap(java.util.EnumMap) BeamFnControlGrpc(org.apache.beam.model.fnexecution.v1.BeamFnControlGrpc) HarnessMonitoringInfosInstructionHandler(org.apache.beam.fn.harness.control.HarnessMonitoringInfosInstructionHandler) ThrowingFunction(org.apache.beam.sdk.function.ThrowingFunction) BeamFnDataGrpcClient(org.apache.beam.fn.harness.data.BeamFnDataGrpcClient) BeamFnApi(org.apache.beam.model.fnexecution.v1.BeamFnApi) IdGenerator(org.apache.beam.sdk.fn.IdGenerator) FinalizeBundleHandler(org.apache.beam.fn.harness.control.FinalizeBundleHandler) ShortIdMap(org.apache.beam.runners.core.metrics.ShortIdMap) ExecutorService(java.util.concurrent.ExecutorService) BeamFnLoggingClient(org.apache.beam.fn.harness.logging.BeamFnLoggingClient) BeamFnStateGrpcClientCache(org.apache.beam.fn.harness.state.BeamFnStateGrpcClientCache)

Aggregations

InstructionRequest (org.apache.beam.model.fnexecution.v1.BeamFnApi.InstructionRequest)13 Test (org.junit.Test)10 IdGenerator (org.apache.beam.sdk.fn.IdGenerator)9 CompletableFuture (java.util.concurrent.CompletableFuture)7 InstructionResponse (org.apache.beam.model.fnexecution.v1.BeamFnApi.InstructionResponse)7 CompletionStage (java.util.concurrent.CompletionStage)6 CountDownLatch (java.util.concurrent.CountDownLatch)6 ArrayList (java.util.ArrayList)5 ExecutorService (java.util.concurrent.ExecutorService)5 DataflowStepContext (org.apache.beam.runners.dataflow.worker.DataflowExecutionContext.DataflowStepContext)4 InstructionRequestHandler (org.apache.beam.runners.fnexecution.control.InstructionRequestHandler)4 BeamFnApi (org.apache.beam.model.fnexecution.v1.BeamFnApi)3 ProcessBundleDescriptor (org.apache.beam.model.fnexecution.v1.BeamFnApi.ProcessBundleDescriptor)3 StateRequest (org.apache.beam.model.fnexecution.v1.BeamFnApi.StateRequest)3 StateResponse (org.apache.beam.model.fnexecution.v1.BeamFnApi.StateResponse)3 BoundedWindow (org.apache.beam.sdk.transforms.windowing.BoundedWindow)3 ByteString (org.apache.beam.vendor.grpc.v1p43p2.com.google.protobuf.ByteString)3 List (java.util.List)2 Callable (java.util.concurrent.Callable)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2