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

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

/*
 *  Copyright (c) 2017, 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 com.google.common.util.concurrent.Runnables;
import com.salesforce.grpc.contrib.LambdaStreamObserver;
import com.salesforce.reactivegrpccommon.CancellableStreamObserver;
import com.salesforce.reactivegrpccommon.ReactiveProducerStreamObserver;
import io.grpc.stub.StreamObserver;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Operators;

import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * 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 rxRequest,
            BiConsumer> delegate) {
        try {
            return Mono
                    .create(emitter -> rxRequest.subscribe(
                        request -> delegate.accept(request, new LambdaStreamObserver(
                            emitter::success,
                            emitter::error,
                            Runnables.doNothing()
                        )),
                        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 rxRequest,
            BiConsumer> delegate) {
        try {
            ReactorConsumerStreamObserver consumerStreamObserver = new ReactorConsumerStreamObserver<>();
            rxRequest.subscribe(request -> delegate.accept(request, consumerStreamObserver));
            return ((Flux) consumerStreamObserver.getRxConsumer())
                    .transform(Operators.lift(new SubscribeOnlyOnceLifter()));
        } 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.
     */
    public static  Mono manyToOne(
            Flux rxRequest,
            Function, StreamObserver> delegate) {
        try {
            return Mono
                    .create(emitter -> {
                        ReactiveProducerStreamObserver reactiveProducerStreamObserver = new ReactiveProducerStreamObserver<>(
                                rxRequest,
                                emitter::success,
                                emitter::error,
                                Runnables.doNothing());
                        delegate.apply(
                                new CancellableStreamObserver<>(reactiveProducerStreamObserver,
                                reactiveProducerStreamObserver::cancel));
                        reactiveProducerStreamObserver.rxSubscribe();
                    })
                    .transform(Operators.lift(new SubscribeOnlyOnceLifter()));
        } 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.
     */
    public static  Flux manyToMany(
            Flux rxRequest,
            Function, StreamObserver> delegate) {
        try {
            ReactorProducerConsumerStreamObserver consumerStreamObserver = new ReactorProducerConsumerStreamObserver<>(rxRequest);
            delegate.apply(new CancellableStreamObserver<>(consumerStreamObserver, consumerStreamObserver::cancel));
            consumerStreamObserver.rxSubscribe();
            return ((Flux) consumerStreamObserver.getRxConsumer())
                    .transform(Operators.lift(new SubscribeOnlyOnceLifter()));
        } catch (Throwable throwable) {
            return Flux.error(throwable);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy