All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.salesforce.reactorgrpc.stub.ClientCalls Maven / Gradle / Ivy

There is a newer version: 1.2.4
Show newest version
/*
 *  Copyright (c) 2019, Salesforce.com, Inc.
 *  All rights reserved.
 *  Licensed under the BSD 3-Clause license.
 *  For full license text, see LICENSE.txt file in the repo root  or https://opensource.org/licenses/BSD-3-Clause
 */

package com.salesforce.reactorgrpc.stub;

import io.grpc.CallOptions;
import io.grpc.stub.CallStreamObserver;
import io.grpc.stub.StreamObserver;
import java.util.function.BiConsumer;
import java.util.function.Function;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Operators;

/**
 * Utility functions for processing different client call idioms. We have one-to-one correspondence
 * between utilities in this class and the potential signatures in a generated stub client class so
 * that the runtime can vary behavior without requiring regeneration of the stub.
 */
public final class ClientCalls {
    private ClientCalls() {

    }

    /**
     * Implements a unary → unary call using {@link Mono} → {@link Mono}.
     */
    public static  Mono oneToOne(
            Mono monoSource,
            BiConsumer> delegate,
            CallOptions options) {
        try {
            return Mono
                    .create(emitter -> monoSource.subscribe(
                        request -> delegate.accept(request, new StreamObserver() {
                            @Override
                            public void onNext(TResponse tResponse) {
                                emitter.success(tResponse);
                            }

                            @Override
                            public void onError(Throwable throwable) {
                                emitter.error(throwable);
                            }

                            @Override
                            public void onCompleted() {
                                // Do nothing
                            }
                        }),
                        emitter::error
                    ))
                    .transform(Operators.lift(new SubscribeOnlyOnceLifter()));
        } catch (Throwable throwable) {
            return Mono.error(throwable);
        }
    }

    /**
     * Implements a unary → stream call as {@link Mono} → {@link Flux}, where the server responds with a
     * stream of messages.
     */
    public static  Flux oneToMany(
            Mono monoSource,
            BiConsumer> delegate,
            CallOptions options) {
        try {

            final int prefetch = ReactorCallOptions.getPrefetch(options);
            final int lowTide = ReactorCallOptions.getLowTide(options);

            return monoSource
                    .flatMapMany(request -> {
                        ReactorClientStreamObserverAndPublisher consumerStreamObserver =
                            new ReactorClientStreamObserverAndPublisher<>(null, null, prefetch, lowTide);

                        delegate.accept(request, consumerStreamObserver);

                        return consumerStreamObserver;
                    });
        } catch (Throwable throwable) {
            return Flux.error(throwable);
        }
    }

    /**
     * Implements a stream → unary call as {@link Flux} → {@link Mono}, where the client transits a stream of
     * messages.
     */
    @SuppressWarnings("unchecked")
    public static  Mono manyToOne(
            Flux fluxSource,
            Function, StreamObserver> delegate,
            CallOptions options) {
        try {
            ReactorSubscriberAndClientProducer subscriberAndGRPCProducer =
                    fluxSource.subscribeWith(new ReactorSubscriberAndClientProducer<>());
            ReactorClientStreamObserverAndPublisher observerAndPublisher =
                    new ReactorClientStreamObserverAndPublisher<>(
                        s -> subscriberAndGRPCProducer.subscribe((CallStreamObserver) s),
                        subscriberAndGRPCProducer::cancel
                    );
            delegate.apply(observerAndPublisher);

            return Flux.from(observerAndPublisher)
                       .singleOrEmpty();
        } catch (Throwable throwable) {
            return Mono.error(throwable);
        }
    }

    /**
     * Implements a bidirectional stream → stream call as {@link Flux} → {@link Flux}, where both the client
     * and the server independently stream to each other.
     */
    @SuppressWarnings("unchecked")
    public static  Flux manyToMany(
            Flux fluxSource,
            Function, StreamObserver> delegate,
            CallOptions options) {
        try {

            final int prefetch = ReactorCallOptions.getPrefetch(options);
            final int lowTide = ReactorCallOptions.getLowTide(options);

            ReactorSubscriberAndClientProducer subscriberAndGRPCProducer =
                fluxSource.subscribeWith(new ReactorSubscriberAndClientProducer<>());
            ReactorClientStreamObserverAndPublisher observerAndPublisher =
                new ReactorClientStreamObserverAndPublisher<>(
                    s -> subscriberAndGRPCProducer.subscribe((CallStreamObserver) s),
                    subscriberAndGRPCProducer::cancel, prefetch, lowTide
                );
            delegate.apply(observerAndPublisher);

            return Flux.from(observerAndPublisher);
        } catch (Throwable throwable) {
            return Flux.error(throwable);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy