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

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

The 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.rxgrpc.stub;

import com.salesforce.reactivegrpc.common.BiConsumer;
import com.salesforce.reactivegrpc.common.Function;
import io.grpc.CallOptions;
import io.grpc.stub.CallStreamObserver;
import io.grpc.stub.StreamObserver;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.SingleEmitter;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.functions.Consumer;
import org.reactivestreams.Publisher;

/**
 * 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 Single} → {@link Single}.
     */
    public static  Single oneToOne(
            final Single rxRequest,
            final BiConsumer> delegate,
            final CallOptions options) {
        try {
            return Single
                .create(new SingleOnSubscribe() {
                    @Override
                    public void subscribe(final SingleEmitter emitter) {
                        rxRequest.subscribe(
                            new Consumer() {
                                @Override
                                public void accept(TRequest request) {
                                    delegate.accept(request, new StreamObserver() {
                                        @Override
                                        public void onNext(TResponse tResponse) {
                                            emitter.onSuccess(tResponse);
                                        }

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

                                        @Override
                                        public void onCompleted() {
                                            // Do nothing
                                        }
                                    });
                                }
                            },
                            new Consumer() {
                                @Override
                                public void accept(Throwable t) {
                                    emitter.onError(t);
                                }
                            }
                        );
                    }
                })
                .lift(new SubscribeOnlyOnceSingleOperator());
        } catch (Throwable throwable) {
            return Single.error(throwable);
        }
    }

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

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

            return rxRequest
                    .flatMapPublisher(new io.reactivex.functions.Function>() {
                        @Override
                        public Publisher apply(TRequest request) {
                            final RxClientStreamObserverAndPublisher consumerStreamObserver =
                                new RxClientStreamObserverAndPublisher(null, null, prefetch, lowTide);

                            delegate.accept(request, consumerStreamObserver);

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

    /**
     * Implements a stream → unary call as {@link Flowable} → {@link Single}, where the client transits a stream of
     * messages.
     */
    @SuppressWarnings("unchecked")
    public static  Single manyToOne(
            final Flowable flowableSource,
            final Function, StreamObserver> delegate,
            final CallOptions options) {
        try {
            final RxSubscriberAndClientProducer subscriberAndGRPCProducer =
                    flowableSource.subscribeWith(new RxSubscriberAndClientProducer());
            final RxClientStreamObserverAndPublisher observerAndPublisher =
                new RxClientStreamObserverAndPublisher(
                    new com.salesforce.reactivegrpc.common.Consumer>() {
                        @Override
                        public void accept(CallStreamObserver observer) {
                            subscriberAndGRPCProducer.subscribe((CallStreamObserver) observer);
                        }
                    },
                    new Runnable() {
                        @Override
                        public void run() {
                            subscriberAndGRPCProducer.cancel();
                        }
                    }
                );

            return Flowable.fromPublisher(observerAndPublisher)
                        .doOnSubscribe(s -> delegate.apply(observerAndPublisher))
                        .singleOrError();
        } catch (Throwable throwable) {
            return Single.error(throwable);
        }
    }

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

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

        try {
            final RxSubscriberAndClientProducer subscriberAndGRPCProducer =
                    flowableSource.subscribeWith(new RxSubscriberAndClientProducer());
            final RxClientStreamObserverAndPublisher observerAndPublisher =
                new RxClientStreamObserverAndPublisher(
                    new com.salesforce.reactivegrpc.common.Consumer>() {
                        @Override
                        public void accept(CallStreamObserver observer) {
                            subscriberAndGRPCProducer.subscribe((CallStreamObserver) observer);
                        }
                    },
                    new Runnable() {
                        @Override
                        public void run() {
                            subscriberAndGRPCProducer.cancel();
                        }
                    },
                    prefetch, lowTide);

            return Flowable.fromPublisher(observerAndPublisher).doOnSubscribe(s -> delegate.apply(observerAndPublisher));
        } catch (Throwable throwable) {
            return Flowable.error(throwable);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy