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

com.salesforce.rxgrpc.stub.ServerCalls 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.rxgrpc.stub;

import com.google.common.base.Preconditions;
import com.salesforce.reactivegrpc.common.Function;
import io.grpc.Status;
import io.grpc.StatusException;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.ServerCallStreamObserver;
import io.grpc.stub.StreamObserver;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.functions.Consumer;

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

    }

    /**
     * Implements a unary → unary call using {@link Single} → {@link Single}.
     */
    public static  void oneToOne(
            final TRequest request,
            final StreamObserver responseObserver,
            final Function, Single> delegate) {
        try {
            final Single rxRequest = Single.just(request);

            final Single rxResponse = Preconditions.checkNotNull(delegate.apply(rxRequest));
            rxResponse.subscribe(
                    new Consumer() {
                        @Override
                        public void accept(TResponse value) {
                            // Don't try to respond if the server has already canceled the request
                            if (responseObserver instanceof ServerCallStreamObserver && ((ServerCallStreamObserver) responseObserver).isCancelled()) {
                                return;
                            }
                            responseObserver.onNext(value);
                            responseObserver.onCompleted();
                        }
                    },
                    new Consumer() {
                        @Override
                        public void accept(Throwable throwable) {
                            responseObserver.onError(prepareError(throwable));
                        }
                    });
        } catch (Throwable throwable) {
            responseObserver.onError(prepareError(throwable));
        }
    }

    /**
     * Implements a unary → stream call as {@link Single} → {@link Flowable}, where the server responds with a
     * stream of messages.
     */
    public static  void oneToMany(
            final TRequest request,
            final StreamObserver responseObserver,
            final Function, Flowable> delegate) {
        try {
            final Single rxRequest = Single.just(request);

            final Flowable rxResponse = Preconditions.checkNotNull(delegate.apply(rxRequest));
            final RxSubscriberAndServerProducer serverProducer =
                    rxResponse.subscribeWith(new RxSubscriberAndServerProducer());
            serverProducer.subscribe((ServerCallStreamObserver) responseObserver);
        } catch (Throwable throwable) {
            responseObserver.onError(prepareError(throwable));
        }
    }

    /**
     * Implements a stream → unary call as {@link Flowable} → {@link Single}, where the client transits a stream of
     * messages.
     */
    public static  StreamObserver manyToOne(
            final StreamObserver responseObserver,
            final Function, Single> delegate) {
        final RxServerStreamObserverAndPublisher streamObserverPublisher =
                new RxServerStreamObserverAndPublisher((ServerCallStreamObserver) responseObserver, null);

        try {
            final Single rxResponse = Preconditions.checkNotNull(delegate.apply(Flowable.fromPublisher(streamObserverPublisher)));
            rxResponse.subscribe(
                    new Consumer() {
                        @Override
                        public void accept(TResponse value) {
                            // Don't try to respond if the server has already canceled the request
                            if (!streamObserverPublisher.isCancelled()) {
                                responseObserver.onNext(value);
                                responseObserver.onCompleted();
                            }
                        }
                    },
                    new Consumer() {
                        @Override
                        public void accept(Throwable throwable) {
                            // Don't try to respond if the server has already canceled the request
                            if (!streamObserverPublisher.isCancelled()) {
                                streamObserverPublisher.abortPendingCancel();
                                responseObserver.onError(prepareError(throwable));
                            }
                        }
                    }
            );
        } catch (Throwable throwable) {
            responseObserver.onError(prepareError(throwable));
        }

        return streamObserverPublisher;
    }

    /**
     * Implements a bidirectional stream → stream call as {@link Flowable} → {@link Flowable}, where both the client
     * and the server independently stream to each other.
     */
    public static  StreamObserver manyToMany(
            final StreamObserver responseObserver,
            final Function, Flowable> delegate) {
        final RxServerStreamObserverAndPublisher streamObserverPublisher =
                new RxServerStreamObserverAndPublisher((ServerCallStreamObserver) responseObserver, null);

        try {
            final Flowable rxResponse = Preconditions.checkNotNull(delegate.apply(Flowable.fromPublisher(streamObserverPublisher)));
            final RxSubscriberAndServerProducer subscriber = new RxSubscriberAndServerProducer();
            subscriber.subscribe((ServerCallStreamObserver) responseObserver);
            // Don't try to respond if the server has already canceled the request
            rxResponse.subscribe(subscriber);
        } catch (Throwable throwable) {
            responseObserver.onError(prepareError(throwable));
        }

        return streamObserverPublisher;
    }

    private static Throwable prepareError(Throwable throwable) {
        if (throwable instanceof StatusException || throwable instanceof StatusRuntimeException) {
            return throwable;
        } else {
            return Status.fromThrowable(throwable).asException();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy