diff --git a/checkstyle-header.txt b/checkstyle-header.txt new file mode 100644 index 00000000..35348526 --- /dev/null +++ b/checkstyle-header.txt @@ -0,0 +1,6 @@ +/* + * 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 + */ \ No newline at end of file diff --git a/checkstyle.xml b/checkstyle.xml index b2babde5..2139a517 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -43,8 +43,7 @@ - + diff --git a/demos/RxChat/RxChat-Client/pom.xml b/demos/RxChat/RxChat-Client/pom.xml deleted file mode 100644 index 0ad9fb47..00000000 --- a/demos/RxChat/RxChat-Client/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - RxChat - com.salesforce.servicelibs - 0.6.2-SNAPSHOT - - 4.0.0 - - RxChat-Client - - - - jline - jline - 2.14.4 - - - - - - - maven-assembly-plugin - - - - com.salesforce.servicelibs.ChatClient - - - - jar-with-dependencies - - false - - - - make-assembly - package - - single - - - - - - - \ No newline at end of file diff --git a/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ChatClient.java b/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ChatClient.java deleted file mode 100644 index 8c97168f..00000000 --- a/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ChatClient.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.servicelibs; - -import com.google.protobuf.Empty; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import jline.console.ConsoleReader; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static com.salesforce.servicelibs.ConsoleUtil.*; - -/** - * Demonstrates building a gRPC streaming client using RxJava and RxGrpc. - */ -public final class ChatClient { - private static final int PORT = 9999; - - private ChatClient() { } - - public static void main(String[] args) throws Exception { - // Connect to the sever - ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", PORT).usePlaintext(true).build(); - RxChatGrpc.RxChatStub stub = RxChatGrpc.newRxStub(channel); - - CountDownLatch done = new CountDownLatch(1); - ConsoleReader console = new ConsoleReader(); - - // Prompt the user for their name - console.println("Press ctrl+D to quit"); - String author = console.readLine("Who are you? > "); - stub.postMessage(toMessage(author, author + " joined.")).subscribe(); - - // Subscribe to incoming messages - Disposable chatSubscription = stub.getMessages(Single.just(Empty.getDefaultInstance())).subscribe( - message -> { - // Don't re-print our own messages - if (!message.getAuthor().equals(author)) { - printLine(console, message.getAuthor(), message.getMessage()); - } - }, - throwable -> { - printLine(console, "ERROR", throwable.getMessage()); - done.countDown(); - }, - done::countDown - ); - - // Publish outgoing messages - Observable.fromIterable(new ConsoleIterator(console, author + " > ")) - .map(msg -> toMessage(author, msg)) - .flatMapSingle(stub::postMessage) - .subscribe( - empty -> { }, - throwable -> { - printLine(console, "ERROR", throwable.getMessage()); - done.countDown(); - }, - done::countDown - ); - - // Wait for a signal to exit, then clean up - done.await(); - stub.postMessage(toMessage(author, author + " left.")).subscribe(); - chatSubscription.dispose(); - channel.shutdown(); - channel.awaitTermination(1, TimeUnit.SECONDS); - console.getTerminal().restore(); - } - - private static Single toMessage(String author, String message) { - return Single.just( - ChatProto.ChatMessage.newBuilder() - .setAuthor(author) - .setMessage(message) - .build() - ); - } -} diff --git a/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ConsoleIterator.java b/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ConsoleIterator.java deleted file mode 100644 index a3db7ea8..00000000 --- a/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ConsoleIterator.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.servicelibs; - -import jline.console.ConsoleReader; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.util.Iterator; - -/** - * Adapts jLine to Iterator. - */ -public class ConsoleIterator implements Iterable, Iterator { - private ConsoleReader console; - private String prompt; - private String lastLine; - - ConsoleIterator(ConsoleReader console, String prompt) { - this.console = console; - this.prompt = prompt; - } - - @Override - @Nonnull - public Iterator iterator() { - return this; - } - - @Override - public boolean hasNext() { - try { - lastLine = console.readLine(prompt); - return lastLine != null; - } catch (IOException e) { - return false; - } - } - - @Override - public String next() { - return lastLine; - } -} diff --git a/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ConsoleUtil.java b/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ConsoleUtil.java deleted file mode 100644 index a5d8ce0b..00000000 --- a/demos/RxChat/RxChat-Client/src/main/java/com/salesforce/servicelibs/ConsoleUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.servicelibs; - -import jline.console.ConsoleReader; -import jline.console.CursorBuffer; - -import java.io.IOException; - -/** - * Utility methods for working with jLine. - */ -public final class ConsoleUtil { - private ConsoleUtil() { } - - public static void printLine(ConsoleReader console, String author, String message) throws IOException { - CursorBuffer stashed = stashLine(console); - console.println(author + " > " + message); - unstashLine(console, stashed); - console.flush(); - } - - public static CursorBuffer stashLine(ConsoleReader console) { - CursorBuffer stashed = console.getCursorBuffer().copy(); - try { - console.getOutput().write("\u001b[1G\u001b[K"); - console.flush(); - } catch (IOException e) { - e.printStackTrace(); - } - return stashed; - } - - - public static void unstashLine(ConsoleReader console, CursorBuffer stashed) { - try { - console.resetPromptLine(console.getPrompt(), stashed.toString(), stashed.cursor); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/demos/RxChat/RxChat-Client/src/main/proto/Chat.proto b/demos/RxChat/RxChat-Client/src/main/proto/Chat.proto deleted file mode 100644 index c1be978b..00000000 --- a/demos/RxChat/RxChat-Client/src/main/proto/Chat.proto +++ /dev/null @@ -1,20 +0,0 @@ -syntax = "proto3"; - -package com.salesforce.servicelibs; - -option java_package = "com.salesforce.servicelibs"; -option java_outer_classname = "ChatProto"; - -import "google/protobuf/empty.proto"; -import "google/protobuf/timestamp.proto"; - -service Chat { - rpc PostMessage (ChatMessage) returns (google.protobuf.Empty) {} - rpc GetMessages (google.protobuf.Empty) returns (stream ChatMessage) {} -} - -message ChatMessage { - google.protobuf.Timestamp when = 1; - string author = 2; - string message = 3; -} \ No newline at end of file diff --git a/demos/RxChat/RxChat-Client/src/main/resources/application.properties b/demos/RxChat/RxChat-Client/src/main/resources/application.properties deleted file mode 100644 index f5f7e593..00000000 --- a/demos/RxChat/RxChat-Client/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -host=localhost -port=9999 \ No newline at end of file diff --git a/demos/RxChat/RxChat-Server/pom.xml b/demos/RxChat/RxChat-Server/pom.xml deleted file mode 100644 index 69743f1a..00000000 --- a/demos/RxChat/RxChat-Server/pom.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - RxChat - com.salesforce.servicelibs - 0.6.2-SNAPSHOT - - 4.0.0 - - RxChat-Server - - - - - - org.springframework.boot - spring-boot-dependencies - 1.4.2.RELEASE - pom - import - - - - - - - com.salesforce.servicelibs - grpc-spring - - - org.springframework.boot - spring-boot - - - org.springframework.boot - spring-boot-autoconfigure - - - org.springframework.boot - spring-boot-starter-logging - - - org.springframework - spring-context - - - - - - - org.springframework.boot - spring-boot-maven-plugin - 1.5.4.RELEASE - - - - repackage - - - - - - - \ No newline at end of file diff --git a/demos/RxChat/RxChat-Server/src/main/java/com/salesforce/servicelibs/ChatImpl.java b/demos/RxChat/RxChat-Server/src/main/java/com/salesforce/servicelibs/ChatImpl.java deleted file mode 100644 index b7f508ea..00000000 --- a/demos/RxChat/RxChat-Server/src/main/java/com/salesforce/servicelibs/ChatImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.servicelibs; - -import com.google.protobuf.Empty; -import com.salesforce.grpc.contrib.spring.GrpcService; -import io.reactivex.BackpressureStrategy; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.subjects.PublishSubject; -import io.reactivex.subjects.Subject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Demonstrates building a gRPC streaming server using RxJava and RxGrpc. - */ -@GrpcService -public class ChatImpl extends RxChatGrpc.ChatImplBase { - private final Logger logger = LoggerFactory.getLogger(ChatImpl.class); - private final Subject broadcast = PublishSubject.create(); - - @Override - public Single postMessage(Single request) { - return request.map(this::broadcast); - } - - private Empty broadcast(ChatProto.ChatMessage message) { - logger.info(message.getAuthor() + ": " + message.getMessage()); - broadcast.onNext(message); - return Empty.getDefaultInstance(); - } - - @Override - public Flowable getMessages(Single request) { - return broadcast.toFlowable(BackpressureStrategy.BUFFER); - } -} diff --git a/demos/RxChat/RxChat-Server/src/main/java/com/salesforce/servicelibs/ChatServer.java b/demos/RxChat/RxChat-Server/src/main/java/com/salesforce/servicelibs/ChatServer.java deleted file mode 100644 index b52492ab..00000000 --- a/demos/RxChat/RxChat-Server/src/main/java/com/salesforce/servicelibs/ChatServer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.servicelibs; - -import com.salesforce.grpc.contrib.spring.GrpcServerHost; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -/** - * Demonstrates building a gRPC streaming server using RxJava, RxGrpc, grpc-spring, and Spring Boot. - */ -@SpringBootApplication -public class ChatServer { - private final Logger logger = LoggerFactory.getLogger(ChatServer.class); - - public static void main(String[] args) throws Exception { - SpringApplication.run(ChatServer.class, args); - Thread.currentThread().join(); - } - - @Bean(initMethod = "start") - public GrpcServerHost grpcServerHost(@Value("${port}") int port) { - logger.info("Listening for gRPC on port " + port); - GrpcServerHost host = new GrpcServerHost(port); - return host; - } - - @Bean - public ChatGrpc.ChatImplBase chatImpl() { - return new ChatImpl(); - } -} diff --git a/demos/RxChat/RxChat-Server/src/main/proto/Chat.proto b/demos/RxChat/RxChat-Server/src/main/proto/Chat.proto deleted file mode 100644 index c1be978b..00000000 --- a/demos/RxChat/RxChat-Server/src/main/proto/Chat.proto +++ /dev/null @@ -1,20 +0,0 @@ -syntax = "proto3"; - -package com.salesforce.servicelibs; - -option java_package = "com.salesforce.servicelibs"; -option java_outer_classname = "ChatProto"; - -import "google/protobuf/empty.proto"; -import "google/protobuf/timestamp.proto"; - -service Chat { - rpc PostMessage (ChatMessage) returns (google.protobuf.Empty) {} - rpc GetMessages (google.protobuf.Empty) returns (stream ChatMessage) {} -} - -message ChatMessage { - google.protobuf.Timestamp when = 1; - string author = 2; - string message = 3; -} \ No newline at end of file diff --git a/demos/RxChat/RxChat-Server/src/main/resources/application.properties b/demos/RxChat/RxChat-Server/src/main/resources/application.properties deleted file mode 100644 index 87f1d8f0..00000000 --- a/demos/RxChat/RxChat-Server/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -port=9999 \ No newline at end of file diff --git a/demos/RxChat/pom.xml b/demos/RxChat/pom.xml deleted file mode 100644 index 66adf6e9..00000000 --- a/demos/RxChat/pom.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - grpc-contrib-parent - com.salesforce.servicelibs - 0.6.2-SNAPSHOT - ../../pom.xml - - 4.0.0 - - RxChat - pom - - - true - true - - - - RxChat-Client - RxChat-Server - - - - - io.grpc - grpc-netty - - - com.salesforce.servicelibs - rxgrpc - provided - - - com.salesforce.servicelibs - rxgrpc-stub - - - com.salesforce.servicelibs - grpc-contrib - - - - - - - kr.motd.maven - os-maven-plugin - 1.4.1.Final - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.1 - - 1.8 - 1.8 - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.5.0 - - com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} - grpc-java - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} - - - - - compile - compile-custom - - - - - rxgrpc - com.salesforce.servicelibs - rxgrpc - ${project.version} - com.salesforce.rxgrpc.RxGrpcGenerator - - - - - - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 4e9bd24f..08815f6d 100644 --- a/pom.xml +++ b/pom.xml @@ -52,11 +52,6 @@ grpc-spring jprotoc-test demos/grpc-java-contrib-demo - demos/RxChat - rxgrpc/rxgrpc - rxgrpc/rxgrpc-test - rxgrpc/rxgrpc-stub - rxgrpc/rxgrpc-tck diff --git a/rxgrpc/README.md b/rxgrpc/README.md deleted file mode 100644 index f74a7939..00000000 --- a/rxgrpc/README.md +++ /dev/null @@ -1,88 +0,0 @@ -Overview -======== -RxGrpc is a new set of gRPC bindings for reactive programming with [RxJava](https://github.com/ReactiveX/RxJava). -RxGprc bindings support unary and streaming operations in both directions. RxGrpc also builds on top of gRPC's -back-pressure support, to deliver end-to-end back-pressure-based flow control in line with RxJava's `Flowable` -back-pressure model. - -Usage -===== -To use RxGrpc with the `protobuf-maven-plugin`, add a [custom protoc plugin configuration section](https://www.xolstice.org/protobuf-maven-plugin/examples/protoc-plugin.html). -```xml - - - rxgrpc - com.salesforce.servicelibs - rxgrpc - [VERSION] - com.salesforce.rxgrpc.RxGrpcGenerator - - -``` - -After installing the plugin, RxGrpc service stubs will be generated along with your gRPC service stubs. - -* To implement a service using an RxGrpc service, subclass `Rx[Name]Grpc.[Name]ImplBase` and override the RxJava-based - methods. - - ``` - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - @Override - public Single sayHello(Single rxRequest) { - return rxRequest.map(protoRequest -> greet("Hello", protoRequest)); - } - - ... - - @Override - public Flowable sayHelloBothStream(Flowable rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .buffer(2) - .map(names -> greet("Hello", String.join(" and ", names))); - } - }; - ``` -* To call a service using an RxGrpc client, call `Rx[Name]Grpc.newRxStub(Channel channel)`. - - ``` - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable req = Flowable.just( - HelloRequest.newBuilder().setName("a").build(), - HelloRequest.newBuilder().setName("b").build(), - HelloRequest.newBuilder().setName("c").build()); - Flowable resp = stub.sayHelloBothStream(req); - resp.subscribe(...); - ``` - -Back-pressure -============= -RxGrpc stubs support bi-directional streaming with back-pressure. Under the hood, RxGrpc is built atop the vanilla -gRPC service stubs generated by protoc. As such, they inherit gRPC's HTTP/2-based back-pressure model. - -Internally, gRPC and RxGrpc implement a pull-based back-pressure strategy. At the HTTP/2 layer, gRPC maintains a -buffer of serialized protocol buffer messages. As frames are consumed on the consumer side, the producer is signaled -to transmit more frames. If this producer-side transmit buffer fills, the HTTP/2 layer signals to the gRPC messaging -layer to stop producing new messages in the stream. RxGrpc handles this signal, applying back-pressure to RxJava -using the `Flowable` api. RxGrpc also implements `Flowable` back-pressure on the consumer side of a stream. As messages -are consumed by the consumer-side `Flowable`, signals are sent down through gRPC and HTTP/2 to request more data. - -An example of back-pressure in action can be found in `BackpressureIntegrationTest.java`. - -Exception Handling -============== -Exception handling with RxGrpc is a little strange due to the way gRPC deals with errors. Servers that produce an error -by calling `onError(Throwable)` will terminate the call with a `StatusRuntimeException`. The client will have its -`onError(Throwable)` subscription handler called as expected. - -Exceptions going from client to server are a little less predictable. Depending on the timing, gRPC may cancel -the request before sending any messages due to an exception in the outbound stream. - -Modules -======= - -RxGrpc is broken down into three sub-modules: - -* _rxgrpc_ - a protoc generator for generating gRPC bindings for RxJava. -* _rxgrpc-stub_ - stub classes supporting the generated RxGrpc bindings. -* _rxgrpc-test_ - integration tests for RxGrpc. diff --git a/rxgrpc/rxgrpc-stub/README.md b/rxgrpc/rxgrpc-stub/README.md deleted file mode 100644 index 3c4f3d16..00000000 --- a/rxgrpc/rxgrpc-stub/README.md +++ /dev/null @@ -1,18 +0,0 @@ -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.salesforce.servicelibs/rxgrpc-stub/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.salesforce.servicelibs/rxgrpc-stub) - -Usage -===== -```xml - - - ... - - - - com.salesforce.servicelibs - rxgrpc-stub - [VERSION] - - - -``` \ No newline at end of file diff --git a/rxgrpc/rxgrpc-stub/pom.xml b/rxgrpc/rxgrpc-stub/pom.xml deleted file mode 100644 index 57b273c5..00000000 --- a/rxgrpc/rxgrpc-stub/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - grpc-contrib-parent - com.salesforce.servicelibs - 0.6.2-SNAPSHOT - ../../pom.xml - - 4.0.0 - - rxgrpc-stub - - - - com.salesforce.servicelibs - grpc-contrib - - - io.reactivex.rxjava2 - rxjava - 2.1.0 - - - io.grpc - grpc-stub - - - junit - junit - test - - - org.assertj - assertj-core - test - - - org.mockito - mockito-core - test - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - ../../checkstyle.xml - ../../checkstyle_ignore.xml - - - - - \ No newline at end of file diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/CancellableStreamObserver.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/CancellableStreamObserver.java deleted file mode 100644 index 41a7b53f..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/CancellableStreamObserver.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.grpc.Status; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; -import io.grpc.stub.ClientCallStreamObserver; -import io.grpc.stub.ClientResponseObserver; - -/** - * CancellableStreamObserver wraps a {@link io.grpc.stub.StreamObserver} and invokes an onCanceledHandler if - * {@link io.grpc.stub.StreamObserver#onError(Throwable)} is invoked with a {@link StatusException} or - * {@link StatusRuntimeException} of type {@link Status.Code#CANCELLED}. This class is used to hook gRPC server - * cancellation events. - * - * @param - * @param - */ -public class CancellableStreamObserver implements ClientResponseObserver { - private final ClientResponseObserver delegate; - private final Runnable onCanceledHandler; - - public CancellableStreamObserver(ClientResponseObserver delegate, Runnable onCanceledHandler) { - this.delegate = delegate; - this.onCanceledHandler = onCanceledHandler; - } - - @Override - public void onNext(TResponse value) { - delegate.onNext(value); - } - - @Override - public void onError(Throwable t) { - if (t instanceof StatusException) { - if (((StatusException) t).getStatus().getCode() == Status.Code.CANCELLED) { - onCanceledHandler.run(); - } - } - if (t instanceof StatusRuntimeException) { - if (((StatusRuntimeException) t).getStatus().getCode() == Status.Code.CANCELLED) { - onCanceledHandler.run(); - } - } - delegate.onError(t); - } - - @Override - public void onCompleted() { - delegate.onCompleted(); - } - - @Override - public void beforeStart(ClientCallStreamObserver requestStream) { - delegate.beforeStart(requestStream); - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/ClientCalls.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/ClientCalls.java deleted file mode 100644 index 8fa097ab..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/ClientCalls.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import com.google.common.util.concurrent.Runnables; -import com.salesforce.grpc.contrib.LambdaStreamObserver; -import io.grpc.stub.StreamObserver; -import io.reactivex.Flowable; -import io.reactivex.Single; - -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 Single} -> {@link Single}. - */ - public static Single oneToOne( - Single rxRequest, - BiConsumer> delegate) { - try { - return Single - .create(emitter -> rxRequest.subscribe( - request -> delegate.accept(request, new LambdaStreamObserver( - emitter::onSuccess, - emitter::onError, - Runnables.doNothing() - )), - emitter::onError - )) - .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( - Single rxRequest, - BiConsumer> delegate) { - try { - RxConsumerStreamObserver consumerStreamObserver = new RxConsumerStreamObserver<>(); - rxRequest.subscribe(request -> delegate.accept(request, consumerStreamObserver)); - return consumerStreamObserver - .getRxConsumer() - .lift(new SubscribeOnlyOnceFlowableOperator<>()); - } 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. - */ - public static Single manyToOne( - Flowable rxRequest, - Function, StreamObserver> delegate) { - try { - return Single - .create(emitter -> { - RxProducerStreamObserver rxProducerStreamObserver = new RxProducerStreamObserver<>( - rxRequest, - emitter::onSuccess, - emitter::onError, - Runnables.doNothing()); - delegate.apply( - new CancellableStreamObserver<>(rxProducerStreamObserver, - rxProducerStreamObserver::cancel)); - rxProducerStreamObserver.rxSubscribe(); - }).lift(new SubscribeOnlyOnceSingleOperator<>()); - } 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. - */ - public static Flowable manyToMany( - Flowable rxRequest, - Function, StreamObserver> delegate) { - try { - RxProducerConsumerStreamObserver consumerStreamObserver = new RxProducerConsumerStreamObserver<>(rxRequest); - delegate.apply(new CancellableStreamObserver<>(consumerStreamObserver, consumerStreamObserver::cancel)); - consumerStreamObserver.rxSubscribe(); - return consumerStreamObserver - .getRxConsumer() - .lift(new SubscribeOnlyOnceFlowableOperator<>()); - } catch (Throwable throwable) { - return Flowable.error(throwable); - } - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxConsumerStreamObserver.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxConsumerStreamObserver.java deleted file mode 100644 index ef33a61f..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxConsumerStreamObserver.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import com.google.common.base.Preconditions; -import io.grpc.Status; -import io.grpc.stub.ClientCallStreamObserver; -import io.grpc.stub.ClientResponseObserver; -import io.reactivex.Flowable; -import io.reactivex.schedulers.Schedulers; - -import java.util.concurrent.CountDownLatch; - -/** - * RxConsumerStreamObserver configures client-side manual flow control for the consuming end of a message stream. - * - * @param - * @param - */ -public class RxConsumerStreamObserver implements ClientResponseObserver { - private RxStreamObserverPublisher publisher; - private Flowable rxConsumer; - private CountDownLatch beforeStartCalled = new CountDownLatch(1); - - public Flowable getRxConsumer() { - try { - beforeStartCalled.await(); - } catch (InterruptedException e) { - throw Status.INTERNAL.withCause(e).asRuntimeException(); - } - return rxConsumer; - } - - - @Override - public void beforeStart(ClientCallStreamObserver requestStream) { - publisher = new RxStreamObserverPublisher<>(Preconditions.checkNotNull(requestStream)); - - rxConsumer = Flowable.unsafeCreate(publisher) - .observeOn(Schedulers.from(RxExecutor.getSerializingExecutor())); - beforeStartCalled.countDown(); - } - - @Override - public void onNext(TResponse value) { - Preconditions.checkState(publisher != null, "beforeStart() not yet called"); - publisher.onNext(Preconditions.checkNotNull(value)); - } - - @Override - public void onError(Throwable throwable) { - Preconditions.checkState(publisher != null, "beforeStart() not yet called"); - publisher.onError(Preconditions.checkNotNull(throwable)); - } - - @Override - public void onCompleted() { - Preconditions.checkState(publisher != null, "beforeStart() not yet called"); - publisher.onCompleted(); - } -} \ No newline at end of file diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxExecutor.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxExecutor.java deleted file mode 100644 index ef733379..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxExecutor.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.grpc.internal.GrpcUtil; -import io.grpc.internal.SerializingExecutor; - -import java.util.concurrent.Executor; - -/** - * RxExecutor holds a shared executor used by RxGrpc to marshall messages between RxJava and gRPC streams. - */ -public final class RxExecutor { - private RxExecutor() { - - } - - private static Executor executor = GrpcUtil.SHARED_CHANNEL_EXECUTOR.create(); - - /** - * Get the shared executor. - */ - public static Executor getSerializingExecutor() { - return new SerializingExecutor(executor); - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxFlowableBackpressureOnReadyHandler.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxFlowableBackpressureOnReadyHandler.java deleted file mode 100644 index a511f07d..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxFlowableBackpressureOnReadyHandler.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import com.google.common.base.Preconditions; -import io.grpc.Status; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; -import io.grpc.stub.CallStreamObserver; -import io.grpc.stub.ClientCallStreamObserver; -import io.grpc.stub.ServerCallStreamObserver; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.concurrent.CountDownLatch; - -/** - * RxFlowableBackpressureOnReadyHandler bridges the manual flow control idioms of RxJava and gRPC. This class takes - * messages off of a {@link org.reactivestreams.Publisher} and feeds them into a {@link CallStreamObserver} - * while respecting backpressure. This class is the inverse of {@link RxStreamObserverPublisher}. - *

- * When a gRPC publisher's transport wants more data to transmit, the {@link CallStreamObserver}'s onReady handler is - * signaled. This handler must keep transmitting messages until {@link CallStreamObserver#isReady()} ceases to be true. - *

- * When a {@link org.reactivestreams.Publisher} is subscribed to by a {@link Subscriber}, the - * {@code Publisher} hands the {@code Subscriber} a {@link Subscription}. When the {@code Subscriber} - * wants more messages from the {@code Publisher}, the {@code Subscriber} calls {@link Subscription#request(long)}. - *

- * To bridge the two idioms: when gRPC wants more messages, the {@code onReadyHandler} is called and {@link #run()} - * calls the {@code Subscription}'s {@code request()} method, asking the {@code Publisher} to produce another message. - * Since this class is also registered as the {@code Publisher}'s {@code Subscriber}, the {@link #onNext(Object)} - * method is called. {@code onNext()} passes the message to gRPC's {@link CallStreamObserver#onNext(Object)} method, - * and then calls {@code request()} again if {@link CallStreamObserver#isReady()} is true. The loop of - * request->pass->check is repeated until {@code isReady()} returns false, indicating that the outbound transmit buffer - * is full and that backpressure must be applied. - * - * @param - */ -public class RxFlowableBackpressureOnReadyHandler implements Subscriber, Runnable { - private CallStreamObserver requestStream; - private Subscription subscription; - private boolean canceled = false; - private CountDownLatch subscribed = new CountDownLatch(1); - - public RxFlowableBackpressureOnReadyHandler(ClientCallStreamObserver requestStream) { - this.requestStream = Preconditions.checkNotNull(requestStream); - requestStream.setOnReadyHandler(this); - } - - public RxFlowableBackpressureOnReadyHandler(ServerCallStreamObserver requestStream) { - this.requestStream = Preconditions.checkNotNull(requestStream); - requestStream.setOnReadyHandler(this); - requestStream.setOnCancelHandler(() -> subscription.cancel()); - } - - @Override - public void run() { - try { - subscribed.await(); - } catch (InterruptedException e) { - - } - Preconditions.checkState(subscription != null, "onSubscribe() not yet called"); - if (!isCanceled()) { - // restart the pump - subscription.request(1); - } - } - - public void cancel() { - canceled = true; - if (subscription != null) { - subscription.cancel(); - subscription = null; - } - } - - public boolean isCanceled() { - return canceled; - } - - @Override - public void onSubscribe(Subscription subscription) { - if (this.subscription != null) { - subscription.cancel(); - } else { - this.subscription = Preconditions.checkNotNull(subscription); - subscribed.countDown(); - } - } - - @Override - public void onNext(T t) { - if (!isCanceled()) { - requestStream.onNext(Preconditions.checkNotNull(t)); - if (requestStream.isReady()) { - // keep the pump going - subscription.request(1); - } - } - } - - @Override - public void onError(Throwable throwable) { - requestStream.onError(prepareError(Preconditions.checkNotNull(throwable))); - } - - @Override - public void onComplete() { - requestStream.onCompleted(); - } - - private static Throwable prepareError(Throwable throwable) { - if (throwable instanceof StatusException || throwable instanceof StatusRuntimeException) { - return throwable; - } else { - return Status.fromThrowable(throwable).asException(); - } - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxProducerConsumerStreamObserver.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxProducerConsumerStreamObserver.java deleted file mode 100644 index b27ba4f2..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxProducerConsumerStreamObserver.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import com.google.common.base.Preconditions; -import io.grpc.stub.ClientCallStreamObserver; -import io.reactivex.Flowable; - -/** - * RxProducerConsumerStreamObserver configures client-side manual flow control for when the client is both producing - * and consuming streams of messages. - * - * @param - * @param - */ -public class RxProducerConsumerStreamObserver extends RxConsumerStreamObserver { - private Flowable rxProducer; - private RxFlowableBackpressureOnReadyHandler onReadyHandler; - - public RxProducerConsumerStreamObserver(Flowable rxProducer) { - this.rxProducer = rxProducer; - } - - @Override - public void beforeStart(ClientCallStreamObserver requestStream) { - super.beforeStart(Preconditions.checkNotNull(requestStream)); - onReadyHandler = new RxFlowableBackpressureOnReadyHandler<>(requestStream); - } - - public void rxSubscribe() { - rxProducer.subscribe(onReadyHandler); - } - - public void cancel() { - onReadyHandler.cancel(); - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxProducerStreamObserver.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxProducerStreamObserver.java deleted file mode 100644 index 24133395..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxProducerStreamObserver.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import com.google.common.base.Preconditions; -import com.salesforce.grpc.contrib.LambdaStreamObserver; -import io.grpc.stub.ClientCallStreamObserver; -import io.grpc.stub.ClientResponseObserver; -import io.reactivex.Flowable; - -import java.util.function.Consumer; - -/** - * LambdaStreamObserver configures client-side manual flow control for the producing end of a message stream. - * - * @param - * @param - */ -public class RxProducerStreamObserver extends LambdaStreamObserver implements ClientResponseObserver { - private Flowable rxProducer; - private RxFlowableBackpressureOnReadyHandler onReadyHandler; - - public RxProducerStreamObserver(Flowable rxProducer, Consumer onNext, Consumer onError, Runnable onCompleted) { - super( - Preconditions.checkNotNull(onNext), - Preconditions.checkNotNull(onError), - Preconditions.checkNotNull(onCompleted) - ); - this.rxProducer = Preconditions.checkNotNull(rxProducer); - } - - @Override - public void beforeStart(ClientCallStreamObserver producerStream) { - Preconditions.checkNotNull(producerStream); - // Subscribe to the rxProducer with an adapter to a gRPC StreamObserver that respects backpressure - // signals from the underlying gRPC client transport. - onReadyHandler = new RxFlowableBackpressureOnReadyHandler<>(producerStream); - } - - public void rxSubscribe() { - rxProducer.subscribe(onReadyHandler); - } - - public void cancel() { - onReadyHandler.cancel(); - } -} \ No newline at end of file diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxStreamObserverPublisher.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxStreamObserverPublisher.java deleted file mode 100644 index fa685330..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/RxStreamObserverPublisher.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import com.google.common.base.Preconditions; -import io.grpc.Status; -import io.grpc.stub.CallStreamObserver; -import io.grpc.stub.ClientCallStreamObserver; -import io.grpc.stub.ServerCallStreamObserver; -import io.grpc.stub.StreamObserver; -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.concurrent.CountDownLatch; - -/** - * RxStreamObserverPublisher bridges the manual flow control idioms of gRPC and RxJava. This class takes - * messages off of a {@link StreamObserver} and feeds them into a {@link Publisher} while respecting backpressure. This - * class is the inverse of {@link RxFlowableBackpressureOnReadyHandler}. - *

- * When a {@link Publisher} is subscribed to by a {@link Subscriber}, the {@code Publisher} hands the {@code Subscriber} - * a {@link Subscription}. When the {@code Subscriber} wants more messages from the {@code Publisher}, the - * {@code Subscriber} calls {@link Subscription#request(long)}. - *

- * gRPC also uses the {@link CallStreamObserver#request(int)} idiom to request more messages from the stream. - *

- * To bridge the two idioms: this class implements a {@code Publisher} which delegates calls to {@code request()} to - * a {@link CallStreamObserver} set in the constructor. When a message is generated as a response, the message is - * delegated in the reverse so the {@code Publisher} can announce it to RxJava. - * - * @param - */ -public class RxStreamObserverPublisher implements Publisher, StreamObserver { - private CallStreamObserver callStreamObserver; - private Subscriber subscriber; - private volatile boolean isCanceled; - - // A gRPC server can sometimes send messages before subscribe() has been called and the consumer may not have - // finished setting up the consumer pipeline. Use a countdown latch to prevent messages from processing before - // subscribe() has been called. - private CountDownLatch subscribed = new CountDownLatch(1); - - public RxStreamObserverPublisher(CallStreamObserver callStreamObserver) { - Preconditions.checkNotNull(callStreamObserver); - this.callStreamObserver = callStreamObserver; - callStreamObserver.disableAutoInboundFlowControl(); - } - - @Override - public void subscribe(Subscriber subscriber) { - Preconditions.checkNotNull(subscriber); - subscriber.onSubscribe(new Subscription() { - @Override - public void request(long l) { - // RxJava uses Long.MAX_VALUE to indicate "all messages"; gRPC uses Integer.MAX_VALUE. - int i = (int) Long.min(l, Integer.MAX_VALUE); - - // Very rarely, request() gets called before the client has finished setting up its stream. If this - // happens, wait momentarily and try again. - try { - callStreamObserver.request(i); - } catch (IllegalStateException ex) { - try { - Thread.sleep(2); - } catch (InterruptedException e) { - // no-op - } - callStreamObserver.request(i); - } - } - - @Override - public void cancel() { - // Don't cancel twice if the server is already canceled - if (callStreamObserver instanceof ServerCallStreamObserver && ((ServerCallStreamObserver) callStreamObserver).isCancelled()) { - return; - } - - isCanceled = true; - if (callStreamObserver instanceof ClientCallStreamObserver) { - ((ClientCallStreamObserver) callStreamObserver).cancel("Client canceled request", null); - } else { - callStreamObserver.onError(Status.CANCELLED.withDescription("Server canceled request").asRuntimeException()); - } - } - }); - this.subscriber = subscriber; - - subscribed.countDown(); - } - - @Override - public void onNext(T value) { - try { - subscribed.await(); - } catch (InterruptedException e) { - - } - subscriber.onNext(Preconditions.checkNotNull(value)); - } - - @Override - public void onError(Throwable t) { - try { - subscribed.await(); - } catch (InterruptedException e) { - - } - - subscriber.onError(Preconditions.checkNotNull(t)); - // Release the subscriber, we don't need a reference to it anymore - subscriber = null; - } - - @Override - public void onCompleted() { - try { - subscribed.await(); - } catch (InterruptedException e) { - - } - subscriber.onComplete(); - // Release the subscriber, we don't need a reference to it anymore - subscriber = null; - } - - public boolean isCanceled() { - return isCanceled; - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/ServerCalls.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/ServerCalls.java deleted file mode 100644 index fddbeeca..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/ServerCalls.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import com.google.common.base.Preconditions; -import com.salesforce.grpc.contrib.LambdaStreamObserver; -import io.grpc.Status; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; -import io.grpc.stub.CallStreamObserver; -import io.grpc.stub.ServerCallStreamObserver; -import io.grpc.stub.StreamObserver; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.schedulers.Schedulers; -import org.reactivestreams.Subscriber; - -import java.util.function.Function; - -/** - * 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( - TRequest request, StreamObserver responseObserver, - Function, Single> delegate) { - try { - Single rxRequest = Single.just(request); - - Single rxResponse = Preconditions.checkNotNull(delegate.apply(rxRequest)); - rxResponse.subscribe( - 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(); - }, - 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( - TRequest request, StreamObserver responseObserver, - Function, Flowable> delegate) { - try { - Single rxRequest = Single.just(request); - - Flowable rxResponse = Preconditions.checkNotNull(delegate.apply(rxRequest)); - rxResponse.subscribe(new RxFlowableBackpressureOnReadyHandler<>( - (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( - StreamObserver responseObserver, - Function, Single> delegate) { - RxStreamObserverPublisher streamObserverPublisher = - new RxStreamObserverPublisher<>((CallStreamObserver) responseObserver); - - try { - Single rxResponse = Preconditions.checkNotNull(delegate.apply( - Flowable.unsafeCreate(streamObserverPublisher) - .observeOn(Schedulers.from(RxExecutor.getSerializingExecutor())))); - rxResponse.subscribe( - value -> { - // Don't try to respond if the server has already canceled the request - if (!streamObserverPublisher.isCanceled()) { - responseObserver.onNext(value); - responseObserver.onCompleted(); - } - }, - throwable -> { - // Don't try to respond if the server has already canceled the request - if (!streamObserverPublisher.isCanceled()) { - responseObserver.onError(prepareError(throwable)); - } - } - ); - } catch (Throwable throwable) { - responseObserver.onError(prepareError(throwable)); - } - - return new LambdaStreamObserver<>( - streamObserverPublisher::onNext, - streamObserverPublisher::onError, - streamObserverPublisher::onCompleted); - } - - /** - * 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( - StreamObserver responseObserver, - Function, Flowable> delegate) { - RxStreamObserverPublisher streamObserverPublisher = - new RxStreamObserverPublisher<>((CallStreamObserver) responseObserver); - - try { - Flowable rxResponse = Preconditions.checkNotNull(delegate.apply( - Flowable.unsafeCreate(streamObserverPublisher) - .observeOn(Schedulers.from(RxExecutor.getSerializingExecutor())))); - Subscriber subscriber = new RxFlowableBackpressureOnReadyHandler<>( - (ServerCallStreamObserver) responseObserver); - // Don't try to respond if the server has already canceled the request - rxResponse.subscribe( - tResponse -> { - if (!streamObserverPublisher.isCanceled()) { - subscriber.onNext(tResponse); - } - }, - throwable -> { - if (!streamObserverPublisher.isCanceled()) { - subscriber.onError(throwable); - } - }, - () -> { - if (!streamObserverPublisher.isCanceled()) { - subscriber.onComplete(); - } - }, - subscriber::onSubscribe - ); - } catch (Throwable throwable) { - responseObserver.onError(prepareError(throwable)); - } - - return new LambdaStreamObserver<>( - streamObserverPublisher::onNext, - streamObserverPublisher::onError, - streamObserverPublisher::onCompleted); - } - - private static Throwable prepareError(Throwable throwable) { - if (throwable instanceof StatusException || throwable instanceof StatusRuntimeException) { - return throwable; - } else { - return Status.fromThrowable(throwable).asException(); - } - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceFlowableOperator.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceFlowableOperator.java deleted file mode 100644 index 990cce2d..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceFlowableOperator.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.rxgrpc.stub; - - -import io.reactivex.FlowableOperator; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * SubscribeOnlyOnceFlowableOperator throws an exception if a user attempts to subscribe more than once to a - * {@link io.reactivex.Flowable}. - * - * @param - */ -public class SubscribeOnlyOnceFlowableOperator implements FlowableOperator { - private AtomicBoolean subscribedOnce = new AtomicBoolean(false); - - @Override - public Subscriber apply(Subscriber observer) throws Exception { - return new Subscriber() { - @Override - public void onSubscribe(Subscription subscription) { - if (subscribedOnce.getAndSet(true)) { - throw new NullPointerException("You cannot directly subscribe to a gRPC service multiple times " + - "concurrently. Use Flowable.share() instead."); - } else { - observer.onSubscribe(subscription); - } - } - - @Override - public void onNext(T t) { - observer.onNext(t); - } - - @Override - public void onError(Throwable throwable) { - observer.onError(throwable); - } - - @Override - public void onComplete() { - observer.onComplete(); - } - }; - } -} diff --git a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceSingleOperator.java b/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceSingleOperator.java deleted file mode 100644 index 4c3349b2..00000000 --- a/rxgrpc/rxgrpc-stub/src/main/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceSingleOperator.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.reactivex.SingleObserver; -import io.reactivex.SingleOperator; -import io.reactivex.disposables.Disposable; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * SubscribeOnlyOnceSingleOperator throws an exception if a user attempts to subscribe more than once to a - * {@link io.reactivex.Single}. - * - * @param - */ -public class SubscribeOnlyOnceSingleOperator implements SingleOperator { - private AtomicBoolean subscribedOnce = new AtomicBoolean(false); - - @Override - public SingleObserver apply(SingleObserver observer) throws Exception { - return new SingleObserver() { - @Override - public void onSubscribe(Disposable d) { - if (subscribedOnce.getAndSet(true)) { - throw new NullPointerException("You cannot directly subscribe to a gRPC service multiple times " + - "concurrently. Use Flowable.share() instead."); - } else { - observer.onSubscribe(d); - } - } - - @Override - public void onSuccess(T t) { - observer.onSuccess(t); - } - - @Override - public void onError(Throwable e) { - observer.onError(e); - } - }; - } -} diff --git a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/CancellableStreamObserverTest.java b/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/CancellableStreamObserverTest.java deleted file mode 100644 index 1e42ca77..00000000 --- a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/CancellableStreamObserverTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.grpc.Status; -import io.grpc.stub.ClientResponseObserver; -import org.junit.Test; - -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.mockito.Mockito.*; -import static org.assertj.core.api.Assertions.*; - -@SuppressWarnings("ALL") -public class CancellableStreamObserverTest { - @Test - public void statusExceptionTriggersHandler() { - ClientResponseObserver delegate = mock(ClientResponseObserver.class); - AtomicBoolean called = new AtomicBoolean(false); - - CancellableStreamObserver observer = new CancellableStreamObserver<>(delegate, () -> called.set(true)); - - observer.onError(Status.CANCELLED.asException()); - - assertThat(called.get()).isTrue(); - } - - @Test - public void statusRuntimeExceptionTriggersHandler() { - ClientResponseObserver delegate = mock(ClientResponseObserver.class); - AtomicBoolean called = new AtomicBoolean(false); - - CancellableStreamObserver observer = new CancellableStreamObserver<>(delegate, () -> called.set(true)); - - observer.onError(Status.CANCELLED.asRuntimeException()); - - assertThat(called.get()).isTrue(); - } - - @Test - public void otherExceptionDoesNotTriggersHandler() { - ClientResponseObserver delegate = mock(ClientResponseObserver.class); - AtomicBoolean called = new AtomicBoolean(false); - - CancellableStreamObserver observer = new CancellableStreamObserver<>(delegate, () -> called.set(true)); - - observer.onError(Status.INTERNAL.asRuntimeException()); - - assertThat(called.get()).isFalse(); - } -} diff --git a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxConsumerStreamObserverTest.java b/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxConsumerStreamObserverTest.java deleted file mode 100644 index 800efe76..00000000 --- a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxConsumerStreamObserverTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.grpc.stub.CallStreamObserver; -import io.grpc.stub.ClientCallStreamObserver; -import io.reactivex.subscribers.TestSubscriber; -import org.junit.Test; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.concurrent.TimeUnit; - -import static org.mockito.Mockito.*; -import static org.assertj.core.api.Assertions.*; - -@SuppressWarnings("unchecked") -public class RxConsumerStreamObserverTest { - @Test - public void rxConsumerIsSet() { - ClientCallStreamObserver obs = mock(ClientCallStreamObserver.class); - RxConsumerStreamObserver rxObs = new RxConsumerStreamObserver(); - - rxObs.beforeStart(obs); - - assertThat(rxObs.getRxConsumer()).isNotNull(); - } - - @Test - public void onNextDelegates() { - ClientCallStreamObserver obs = mock(ClientCallStreamObserver.class); - RxConsumerStreamObserver rxObs = new RxConsumerStreamObserver(); - Subscriber sub = mock(Subscriber.class); - - rxObs.beforeStart(obs); - rxObs.getRxConsumer().subscribe(sub); - - TestSubscriber testSubscriber = rxObs.getRxConsumer().test(); - - Object obj = new Object(); - rxObs.onNext(obj); - rxObs.onCompleted(); - - testSubscriber.awaitTerminalEvent(3, TimeUnit.SECONDS); - testSubscriber.assertValues(obj); - } - - @Test - public void onErrorDelegates() { - ClientCallStreamObserver obs = mock(ClientCallStreamObserver.class); - RxConsumerStreamObserver rxObs = new RxConsumerStreamObserver(); - Subscriber sub = mock(Subscriber.class); - - rxObs.beforeStart(obs); - rxObs.getRxConsumer().subscribe(sub); - - TestSubscriber testSubscriber = rxObs.getRxConsumer().test(); - - Throwable obj = new Exception(); - rxObs.onError(obj); - - testSubscriber.awaitTerminalEvent(3, TimeUnit.SECONDS); - testSubscriber.assertError(obj); - } -} diff --git a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxFlowableBackpressureOnReadyHandlerTest.java b/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxFlowableBackpressureOnReadyHandlerTest.java deleted file mode 100644 index a4f83041..00000000 --- a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxFlowableBackpressureOnReadyHandlerTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.grpc.stub.CallStreamObserver; -import io.grpc.stub.ClientCallStreamObserver; -import org.junit.Test; -import org.reactivestreams.Subscription; - -import static org.mockito.Mockito.*; - -@SuppressWarnings("unchecked") -public class RxFlowableBackpressureOnReadyHandlerTest { - @Test - public void runPrimesThePump() { - ClientCallStreamObserver obs = mock(ClientCallStreamObserver.class); - RxFlowableBackpressureOnReadyHandler handler = new RxFlowableBackpressureOnReadyHandler<>(obs); - Subscription sub = mock(Subscription.class); - - handler.onSubscribe(sub); - - handler.run(); - verify(sub).request(1); - } - - @Test - public void onNextKeepsPumpRunning() { - ClientCallStreamObserver obs = mock(ClientCallStreamObserver.class); - when(obs.isReady()).thenReturn(true); - - RxFlowableBackpressureOnReadyHandler handler = new RxFlowableBackpressureOnReadyHandler<>(obs); - Subscription sub = mock(Subscription.class); - - handler.onSubscribe(sub); - - Object obj = new Object(); - handler.onNext(obj); - - verify(obs).onNext(obj); - verify(sub).request(1); - } - - @Test - public void onNextStopsPump() { - ClientCallStreamObserver obs = mock(ClientCallStreamObserver.class); - when(obs.isReady()).thenReturn(false); - - RxFlowableBackpressureOnReadyHandler handler = new RxFlowableBackpressureOnReadyHandler<>(obs); - Subscription sub = mock(Subscription.class); - - handler.onSubscribe(sub); - - Object obj = new Object(); - handler.onNext(obj); - - verify(obs).onNext(obj); - verify(sub, never()).request(1); - } -} diff --git a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxStreamObserverPublisherTest.java b/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxStreamObserverPublisherTest.java deleted file mode 100644 index 6e44d980..00000000 --- a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/RxStreamObserverPublisherTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.grpc.stub.CallStreamObserver; -import org.junit.Test; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.concurrent.atomic.AtomicReference; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -@SuppressWarnings("unchecked") -public class RxStreamObserverPublisherTest { - @Test - public void onNextDelegates() { - CallStreamObserver obs = mock(CallStreamObserver.class); - Subscriber sub = mock(Subscriber.class); - - RxStreamObserverPublisher pub = new RxStreamObserverPublisher<>(obs); - pub.subscribe(sub); - - Object obj = new Object(); - - pub.onNext(obj); - verify(sub).onNext(obj); - } - - @Test - public void onErrorDelegates() { - CallStreamObserver obs = mock(CallStreamObserver.class); - Subscriber sub = mock(Subscriber.class); - - RxStreamObserverPublisher pub = new RxStreamObserverPublisher<>(obs); - pub.subscribe(sub); - - Throwable obj = new Exception(); - - pub.onError(obj); - verify(sub).onError(obj); - } - - @Test - public void onCompletedDelegates() { - CallStreamObserver obs = mock(CallStreamObserver.class); - Subscriber sub = mock(Subscriber.class); - - RxStreamObserverPublisher pub = new RxStreamObserverPublisher<>(obs); - pub.subscribe(sub); - - pub.onCompleted(); - verify(sub).onComplete(); - } - - @Test - public void requestDelegates() { - CallStreamObserver obs = mock(CallStreamObserver.class); - Subscriber sub = mock(Subscriber.class); - - AtomicReference subscription = new AtomicReference<>(); - doAnswer(invocationOnMock -> { - subscription.set((Subscription)invocationOnMock.getArguments()[0]); - return null; - }).when(sub).onSubscribe(any(Subscription.class)); - - RxStreamObserverPublisher pub = new RxStreamObserverPublisher<>(obs); - pub.subscribe(sub); - - assertThat(subscription.get()).isNotNull(); - subscription.get().request(10); - verify(obs).request(10); - } -} diff --git a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceTest.java b/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceTest.java deleted file mode 100644 index c392c3c1..00000000 --- a/rxgrpc/rxgrpc-stub/src/test/java/com/salesforce/rxgrpc/stub/SubscribeOnlyOnceTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.rxgrpc.stub; - -import io.reactivex.SingleObserver; -import io.reactivex.disposables.Disposable; -import org.junit.Test; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import static org.mockito.Mockito.*; -import static org.assertj.core.api.Assertions.*; - -public class SubscribeOnlyOnceTest { - @Test - public void subscribeOnlyOnceFlowableOperatorErrorsWhenMultipleSubscribe() throws Exception { - SubscribeOnlyOnceFlowableOperator op = new SubscribeOnlyOnceFlowableOperator<>(); - Subscriber innerSub = mock(Subscriber.class); - Subscription subscription = mock(Subscription.class); - - Subscriber outerSub = op.apply(innerSub); - - outerSub.onSubscribe(subscription); - assertThatThrownBy(() -> outerSub.onSubscribe(subscription)) - .isInstanceOf(NullPointerException.class) - .hasMessageContaining("cannot directly subscribe to a gRPC service multiple times"); - - verify(innerSub, times(1)).onSubscribe(subscription); - } - - @Test - public void subscribeOnlyOnceSingleOperatorErrorsWhenMultipleSubscribe() throws Exception { - SubscribeOnlyOnceSingleOperator op = new SubscribeOnlyOnceSingleOperator<>(); - SingleObserver innerSub = mock(SingleObserver.class); - Disposable disposable = mock(Disposable.class); - - SingleObserver outerSub = op.apply(innerSub); - - outerSub.onSubscribe(disposable); - assertThatThrownBy(() -> outerSub.onSubscribe(disposable)) - .isInstanceOf(NullPointerException.class) - .hasMessageContaining("cannot directly subscribe to a gRPC service multiple times"); - - verify(innerSub, times(1)).onSubscribe(disposable); - } -} diff --git a/rxgrpc/rxgrpc-tck/README.md b/rxgrpc/rxgrpc-tck/README.md deleted file mode 100644 index 38db3a75..00000000 --- a/rxgrpc/rxgrpc-tck/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This module contains tests from the Reactive Streams Technology Compatibility Kit for RxGrpc. - -https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck \ No newline at end of file diff --git a/rxgrpc/rxgrpc-tck/pom.xml b/rxgrpc/rxgrpc-tck/pom.xml deleted file mode 100644 index 535e5ecf..00000000 --- a/rxgrpc/rxgrpc-tck/pom.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - grpc-contrib-parent - com.salesforce.servicelibs - 0.6.2-SNAPSHOT - ../../pom.xml - - 4.0.0 - - rxgrpc-tck - - - true - - - - - com.salesforce.servicelibs - rxgrpc-stub - ${project.version} - test - - - io.grpc - grpc-netty - test - - - io.grpc - grpc-core - test - - - io.grpc - grpc-stub - test - - - io.grpc - grpc-protobuf - test - - - org.reactivestreams - reactive-streams-tck - 1.0.1 - test - - - - - - - kr.motd.maven - os-maven-plugin - 1.4.1.Final - - - - - org.apache.maven.plugins - maven-install-plugin - 2.5.2 - - - true - - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.5.0 - - com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} - grpc-java - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} - - - - - test-compile - test-compile-custom - - - - - rxgrpc - com.salesforce.servicelibs - rxgrpc - ${project.version} - com.salesforce.rxgrpc.RxGrpcGenerator - - - - - - - - - - \ No newline at end of file diff --git a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherManyToManyVerificationTest.java b/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherManyToManyVerificationTest.java deleted file mode 100644 index 873507a4..00000000 --- a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherManyToManyVerificationTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.rxgrpc.tck; - -import io.grpc.ManagedChannel; -import io.grpc.Server; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.inprocess.InProcessServerBuilder; -import io.reactivex.Flowable; -import org.reactivestreams.Publisher; -import org.reactivestreams.tck.PublisherVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; - -/** - * Publisher tests from the Reactive Streams Technology Compatibility Kit. - * https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck - */ -@SuppressWarnings("Duplicates") -public class RxGrpcPublisherManyToManyVerificationTest extends PublisherVerification { - public static final long DEFAULT_TIMEOUT_MILLIS = 500L; - public static final long PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS = 500L; - - public RxGrpcPublisherManyToManyVerificationTest() { - super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS, DEFAULT_TIMEOUT_MILLIS), PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS); - } - - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setup() throws Exception { - System.out.println("RxGrpcPublisherManyToManyVerificationTest"); - server = InProcessServerBuilder.forName("RxGrpcPublisherManyToManyVerificationTest").addService(new TckService()).build().start(); - channel = InProcessChannelBuilder.forName("RxGrpcPublisherManyToManyVerificationTest").usePlaintext(true).build(); - } - - @AfterClass - public static void tearDown() throws Exception { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Override - public Publisher createPublisher(long elements) { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Flowable request = Flowable.range(0, (int)elements).map(this::toMessage); - Publisher publisher = stub.manyToMany(request); - - return publisher; - } - - @Override - public Publisher createFailedPublisher() { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Flowable request = Flowable.just(toMessage(TckService.KABOOM)); - Publisher publisher = stub.manyToMany(request); - - return publisher; - } - - private Message toMessage(int i) { - return Message.newBuilder().setNumber(i).build(); - } -} diff --git a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherManyToOneVerificationTest.java b/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherManyToOneVerificationTest.java deleted file mode 100644 index 12951b17..00000000 --- a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherManyToOneVerificationTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.rxgrpc.tck; - -import io.grpc.ManagedChannel; -import io.grpc.Server; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.inprocess.InProcessServerBuilder; -import io.reactivex.Flowable; -import io.reactivex.Single; -import org.reactivestreams.Publisher; -import org.reactivestreams.tck.PublisherVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; - -/** - * Publisher tests from the Reactive Streams Technology Compatibility Kit. - * https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck - */ -@SuppressWarnings("Duplicates") -public class RxGrpcPublisherManyToOneVerificationTest extends PublisherVerification { - public static final long DEFAULT_TIMEOUT_MILLIS = 500L; - public static final long PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS = 500L; - - public RxGrpcPublisherManyToOneVerificationTest() { - super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS, DEFAULT_TIMEOUT_MILLIS), PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS); - } - - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setup() throws Exception { - System.out.println("RxGrpcPublisherManyToOneVerificationTest"); - server = InProcessServerBuilder.forName("RxGrpcPublisherManyToOneVerificationTest").addService(new TckService()).build().start(); - channel = InProcessChannelBuilder.forName("RxGrpcPublisherManyToOneVerificationTest").usePlaintext(true).build(); - } - - @AfterClass - public static void tearDown() throws Exception { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Override - public long maxElementsFromPublisher() { - return 1; - } - - @Override - public Publisher createPublisher(long elements) { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Flowable request = Flowable.range(0, (int)elements).map(this::toMessage); - Single publisher = stub.manyToOne(request); - - return publisher.toFlowable(); - } - - @Override - public Publisher createFailedPublisher() { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Flowable request = Flowable.just(toMessage(TckService.KABOOM)); - Single publisher = stub.manyToOne(request); - - return publisher.toFlowable(); - } - - private Message toMessage(int i) { - return Message.newBuilder().setNumber(i).build(); - } -} diff --git a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherOneToManyVerificationTest.java b/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherOneToManyVerificationTest.java deleted file mode 100644 index cd9c8e6b..00000000 --- a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherOneToManyVerificationTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.rxgrpc.tck; - -import io.grpc.ManagedChannel; -import io.grpc.Server; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.inprocess.InProcessServerBuilder; -import io.reactivex.Single; -import org.reactivestreams.Publisher; -import org.reactivestreams.tck.PublisherVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; - -/** - * Publisher tests from the Reactive Streams Technology Compatibility Kit. - * https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck - */ -@SuppressWarnings("Duplicates") -public class RxGrpcPublisherOneToManyVerificationTest extends PublisherVerification { - public static final long DEFAULT_TIMEOUT_MILLIS = 500L; - public static final long PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS = 500L; - - public RxGrpcPublisherOneToManyVerificationTest() { - super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS, DEFAULT_TIMEOUT_MILLIS), PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS); - } - - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setup() throws Exception { - System.out.println("RxGrpcPublisherOneToManyVerificationTest"); - server = InProcessServerBuilder.forName("RxGrpcPublisherOneToManyVerificationTest").addService(new TckService()).build().start(); - channel = InProcessChannelBuilder.forName("RxGrpcPublisherOneToManyVerificationTest").usePlaintext(true).build(); - } - - @AfterClass - public static void tearDown() throws Exception { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Override - public Publisher createPublisher(long elements) { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Single request = Single.just(toMessage((int) elements)); - Publisher publisher = stub.oneToMany(request); - - return publisher; - } - - @Override - public Publisher createFailedPublisher() { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Single request = Single.just(toMessage(TckService.KABOOM)); - Publisher publisher = stub.oneToMany(request); - - return publisher; - } - - private Message toMessage(int i) { - return Message.newBuilder().setNumber(i).build(); - } -} diff --git a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherOneToOneVerificationTest.java b/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherOneToOneVerificationTest.java deleted file mode 100644 index 220559bb..00000000 --- a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcPublisherOneToOneVerificationTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.rxgrpc.tck; - -import io.grpc.ManagedChannel; -import io.grpc.Server; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.inprocess.InProcessServerBuilder; -import io.reactivex.Single; -import org.reactivestreams.Publisher; -import org.reactivestreams.tck.PublisherVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; - -/** - * Publisher tests from the Reactive Streams Technology Compatibility Kit. - * https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck - */ -@SuppressWarnings("Duplicates") -public class RxGrpcPublisherOneToOneVerificationTest extends PublisherVerification { - public static final long DEFAULT_TIMEOUT_MILLIS = 500L; - public static final long PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS = 500L; - - public RxGrpcPublisherOneToOneVerificationTest() { - super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS, DEFAULT_TIMEOUT_MILLIS), PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS); - } - - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setup() throws Exception { - System.out.println("RxGrpcPublisherOneToOneVerificationTest"); - server = InProcessServerBuilder.forName("RxGrpcPublisherOneToOneVerificationTest").addService(new TckService()).build().start(); - channel = InProcessChannelBuilder.forName("RxGrpcPublisherOneToOneVerificationTest").usePlaintext(true).build(); - } - - @AfterClass - public static void tearDown() throws Exception { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Override - public long maxElementsFromPublisher() { - return 1; - } - - @Override - public Publisher createPublisher(long elements) { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Single request = Single.just(toMessage((int) elements)); - Single publisher = stub.oneToOne(request); - - return publisher.toFlowable(); - } - - @Override - public Publisher createFailedPublisher() { - RxTckGrpc.RxTckStub stub = RxTckGrpc.newRxStub(channel); - Single request = Single.just(toMessage(TckService.KABOOM)); - Single publisher = stub.oneToOne(request); - - return publisher.toFlowable(); - } - - private Message toMessage(int i) { - return Message.newBuilder().setNumber(i).build(); - } -} diff --git a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcSubscriberWhiteboxVerificationTest.java b/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcSubscriberWhiteboxVerificationTest.java deleted file mode 100644 index bd1a26b1..00000000 --- a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/RxGrpcSubscriberWhiteboxVerificationTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.rxgrpc.tck; - -import com.salesforce.rxgrpc.stub.RxFlowableBackpressureOnReadyHandler; -import io.grpc.stub.ClientCallStreamObserver; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.SubscriberWhiteboxVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.testng.annotations.BeforeClass; - -import javax.annotation.Nullable; - -/** - * Subscriber tests from the Reactive Streams Technology Compatibility Kit. - * https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck - */ -public class RxGrpcSubscriberWhiteboxVerificationTest extends SubscriberWhiteboxVerification { - public RxGrpcSubscriberWhiteboxVerificationTest() { - super(new TestEnvironment()); - } - - @BeforeClass - public static void setup() throws Exception { - System.out.println("RxGrpcSubscriberWhiteboxVerificationTest"); - } - - @Override - public Subscriber createSubscriber(WhiteboxSubscriberProbe probe) { - return new RxFlowableBackpressureOnReadyHandler(new StubServerCallStreamObserver()) { - @Override - public void onSubscribe(final Subscription s) { - super.onSubscribe(s); - - // register a successful Subscription, and create a Puppet, - // for the WhiteboxVerification to be able to drive its tests: - probe.registerOnSubscribe(new SubscriberPuppet() { - - @Override - public void triggerRequest(long elements) { - s.request(elements); - } - - @Override - public void signalCancel() { - s.cancel(); - } - }); - - super.run(); - } - - @Override - public void onNext(Message element) { - // in addition to normal Subscriber work that you're testing, register onNext with the probe - super.onNext(element); - probe.registerOnNext(element); - } - - @Override - public void onError(Throwable cause) { - // in addition to normal Subscriber work that you're testing, register onError with the probe - super.onError(cause); - probe.registerOnError(cause); - } - - @Override - public void onComplete() { - // in addition to normal Subscriber work that you're testing, register onComplete with the probe - super.onComplete(); - probe.registerOnComplete(); - } - }; - } - - @Override - public Message createElement(int i) { - return Message.newBuilder().setNumber(i).build(); - } - - private final class StubServerCallStreamObserver extends ClientCallStreamObserver { - @Override - public boolean isReady() { - return true; - } - - @Override - public void setOnReadyHandler(Runnable onReadyHandler) { - - } - - @Override - public void disableAutoInboundFlowControl() { - - } - - @Override - public void request(int count) { - System.out.println("Request " + count); - } - - @Override - public void setMessageCompression(boolean enable) { - - } - - @Override - public void onNext(Message value) { - System.out.println(value.getNumber()); - } - - @Override - public void onError(Throwable t) { - System.out.println(t.getMessage()); - } - - @Override - public void onCompleted() { - System.out.println("Completed"); - } - - @Override - public void cancel(@Nullable String s, @Nullable Throwable throwable) { - - } - } -} diff --git a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/TckService.java b/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/TckService.java deleted file mode 100644 index c595b26f..00000000 --- a/rxgrpc/rxgrpc-tck/src/test/java/com/salesforce/rxgrpc/tck/TckService.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.rxgrpc.tck; - -import io.reactivex.Flowable; -import io.reactivex.Single; - -public class TckService extends RxTckGrpc.TckImplBase { - public static final int KABOOM = -1; - - @Override - public Single oneToOne(Single request) { - return request.map(this::maybeExplode); - } - - @Override - public Flowable oneToMany(Single request) { - return request - .map(this::maybeExplode) - // send back no more than 10 responses - .flatMapPublisher(message -> Flowable.range(0, Math.min(message.getNumber(), 10))) - .map(this::toMessage); - } - - @Override - public Single manyToOne(Flowable request) { - return request.map(this::maybeExplode).last(Message.newBuilder().setNumber(0).build()); - } - - @Override - public Flowable manyToMany(Flowable request) { - return request.map(this::maybeExplode); - } - - private Message maybeExplode(Message req) throws Exception { - if (req.getNumber() < 0) { - throw new Exception("Kaboom!"); - } else { - return req; - } - } - - private Message toMessage(int i) { - return Message.newBuilder().setNumber(i).build(); - } -} \ No newline at end of file diff --git a/rxgrpc/rxgrpc-tck/src/test/proto/tck.proto b/rxgrpc/rxgrpc-tck/src/test/proto/tck.proto deleted file mode 100644 index f55e0ffd..00000000 --- a/rxgrpc/rxgrpc-tck/src/test/proto/tck.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; - -package tck; - -option java_multiple_files = true; -option java_package = "com.salesforce.rxgrpc.tck"; -option java_outer_classname = "TckProto"; - -service Tck { - rpc OneToOne (Message) returns (Message) {} - rpc OneToMany (Message) returns (stream Message) {} - rpc ManyToOne (stream Message) returns (Message) {} - rpc ManyToMany (stream Message) returns (stream Message) {} -} - -message Message { - int32 number = 1; -} \ No newline at end of file diff --git a/rxgrpc/rxgrpc-test/README.md b/rxgrpc/rxgrpc-test/README.md deleted file mode 100644 index a559387b..00000000 --- a/rxgrpc/rxgrpc-test/README.md +++ /dev/null @@ -1 +0,0 @@ -This module contains integration tests for RxGrpc. \ No newline at end of file diff --git a/rxgrpc/rxgrpc-test/pom.xml b/rxgrpc/rxgrpc-test/pom.xml deleted file mode 100644 index 78a5494f..00000000 --- a/rxgrpc/rxgrpc-test/pom.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - grpc-contrib-parent - com.salesforce.servicelibs - 0.6.2-SNAPSHOT - ../../pom.xml - - 4.0.0 - - rxgrpc-test - - - true - true - - - - - com.salesforce.servicelibs - rxgrpc-stub - ${project.version} - test - - - io.grpc - grpc-netty - test - - - io.grpc - grpc-core - test - - - io.grpc - grpc-stub - test - - - io.grpc - grpc-protobuf - test - - - io.grpc - grpc-context - test - - - junit - junit - test - - - org.assertj - assertj-core - test - - - org.mockito - mockito-core - test - - - org.awaitility - awaitility - test - - - - - - - kr.motd.maven - os-maven-plugin - 1.4.1.Final - - - - - org.apache.maven.plugins - maven-install-plugin - 2.5.2 - - - true - - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.5.0 - - com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} - grpc-java - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} - - - - - test-compile - test-compile-custom - - - - - rxgrpc - com.salesforce.servicelibs - rxgrpc - ${project.version} - com.salesforce.rxgrpc.RxGrpcGenerator - - - - - - - - - \ No newline at end of file diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/BackpressureDetector.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/BackpressureDetector.java deleted file mode 100644 index 67d46872..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/BackpressureDetector.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.rxgrpc; - -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Neither gRPC nor rxJava provide a direct way to detect that backpressure occurred. However, we can detect - * it statistically. Backpressure is signalled by delaying calls to request(). If messages were flowing without - * backpressure, the rate at which request() is called would be relatively constant. In the presence of backpressure, - * calls to request() are delayed while the consumer deals with its backlog. We can measure these delays by looking - * for statistical outliers in the durations between calls to request(). Large outliers indicate the presence of a - * backpressure event. - * - * https://eurekastatistics.com/using-the-median-absolute-deviation-to-find-outliers/ - */ -public class BackpressureDetector { - private final List timestamps = new LinkedList<>(); - private final int madMultiple; - - public BackpressureDetector(int madMultipleCutoff) { - this.madMultiple = madMultipleCutoff; - } - - public void tick() { - timestamps.add(System.currentTimeMillis() * 1.0); - } - - public void reset() { - timestamps.clear(); - } - - public List getTimesBetweenNextCalls() { - List ret = new LinkedList<>(); - for (int i = 1; i < timestamps.size(); i++) { - ret.add(timestamps.get(i) - timestamps.get(i - 1)); - } - return ret; - } - - public boolean backpressureDelayOcurred() { - try { - return getOutliers().size() > 0; - } catch (IndexOutOfBoundsException ex) { - ex.printStackTrace(); - return false; - } - } - - public List getOutliers() { - List samples = getTimesBetweenNextCalls(); - double median = median(samples); - double mad = mad(samples); - return samples.stream() - .map(s -> Math.abs(s - median) / mad) - .filter(s -> s > madMultiple) - .collect(Collectors.toList()); - } - - private double mad(List samples) { - // Compute median absolute deviation - double median = median(samples); - List deviations = samples.stream().map(s -> Math.abs(s - median)).collect(Collectors.toList()); - return median(deviations); - } - - private double median(List samples) { - // Compute the statistical median of a SORTED list of data - samples.sort(Comparator.naturalOrder()); - int c = samples.size() / 2; - if (samples.size() % 2 == 1) { // ODD number of samples - return samples.get(c); - } else { - return (samples.get(c - 1) + samples.get(c)) / 2.0; - } - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/BackpressureIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/BackpressureIntegrationTest.java deleted file mode 100644 index 4748a3ef..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/BackpressureIntegrationTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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.rxgrpc; - -import com.google.protobuf.Empty; -import com.salesforce.servicelibs.NumberProto; -import com.salesforce.servicelibs.RxNumbersGrpc; -import io.grpc.ManagedChannel; -import io.grpc.Server; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.inprocess.InProcessServerBuilder; -import io.reactivex.Flowable; -import io.reactivex.Single; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -import static org.assertj.core.api.Assertions.assertThat; - -@SuppressWarnings("Duplicates") -public class BackpressureIntegrationTest { - private static Server server; - private static ManagedChannel channel; - - private static final int madMultipleCutoff = 100; - private static BackpressureDetector serverRecBPDetector = new BackpressureDetector(madMultipleCutoff); - private static BackpressureDetector serverRespBPDetector = new BackpressureDetector(madMultipleCutoff); - - @BeforeClass - public static void setupServer() throws Exception { - RxNumbersGrpc.NumbersImplBase svc = new RxNumbersGrpc.NumbersImplBase() { - @Override - public Single requestPressure(Flowable request) { - return request - .map(proto -> proto.getNumber(0)) - .doOnNext(i -> { - serverRecBPDetector.tick(); - System.out.println(" --> " + i); - try { Thread.sleep(50); } catch (InterruptedException e) {} - }) - .last(-1) - .map(BackpressureIntegrationTest::protoNum); - } - - @Override - public Flowable responsePressure(Single request) { - return Flowable - .fromIterable(new Sequence(200, serverRespBPDetector)) - .doOnNext(i -> System.out.println(" <-- " + i)) - .map(BackpressureIntegrationTest::protoNum); - } - - @Override - public Flowable twoWayPressure(Flowable request) { - request - .map(proto -> proto.getNumber(0)) - .subscribe( - n -> { - serverRecBPDetector.tick(); - System.out.println(" --> " + n); - try { Thread.sleep(50); } catch (InterruptedException e) {} - }, - Throwable::printStackTrace, - () -> System.out.println("Server done.") - ); - - return Flowable - .fromIterable(new Sequence(200, serverRespBPDetector)) - .doOnNext(i -> System.out.println(" <-- " + i)) - .map(BackpressureIntegrationTest::protoNum); - } - }; - - server = InProcessServerBuilder.forName("e2e").addService(svc).build().start(); - channel = InProcessChannelBuilder.forName("e2e").usePlaintext(true).build(); - } - - @Before - public void resetServerStats() { - serverRecBPDetector.reset(); - serverRespBPDetector.reset(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void clientToServerBackpressure() throws InterruptedException { - Object lock = new Object(); - - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - BackpressureDetector clientBackpressureDetector = new BackpressureDetector(madMultipleCutoff); - Sequence seq = new Sequence(200, clientBackpressureDetector); - - Flowable rxRequest = Flowable - .fromIterable(seq) - .doOnNext(i -> System.out.println(i + " -->")) - .map(BackpressureIntegrationTest::protoNum); - - - Single rxResponse = stub.requestPressure(rxRequest); - - rxResponse.subscribe( - n -> { - System.out.println("Client done. " + n.getNumber(0)); - synchronized (lock) { - lock.notify(); - } - }, - t -> { - t.printStackTrace(); - synchronized (lock) { - lock.notify(); - } - }); - - synchronized (lock) { - lock.wait(TimeUnit.SECONDS.toMillis(20)); - } - - assertThat(clientBackpressureDetector.backpressureDelayOcurred()).isTrue(); - } - - @Test - public void serverToClientBackpressure() throws InterruptedException { - Object lock = new Object(); - BackpressureDetector clientBackpressureDetector = new BackpressureDetector(madMultipleCutoff); - - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - - Single rxRequest = Single.just(Empty.getDefaultInstance()); - - Flowable rxResponse = stub.responsePressure(rxRequest); - rxResponse.subscribe( - n -> { - clientBackpressureDetector.tick(); - System.out.println(n.getNumber(0) + " <--"); - try { Thread.sleep(50); } catch (InterruptedException e) {} - }, - t -> { - t.printStackTrace(); - synchronized (lock) { - lock.notify(); - } - }, - () -> { - System.out.println("Client done."); - synchronized (lock) { - lock.notify(); - } - }); - - synchronized (lock) { - lock.wait(TimeUnit.SECONDS.toMillis(20)); - } - - assertThat(serverRespBPDetector.backpressureDelayOcurred()).isTrue(); - } - - @Test - public void bidiBackpressure() throws InterruptedException { - Object lock = new Object(); - BackpressureDetector clientReqBPDetector = new BackpressureDetector(madMultipleCutoff); - BackpressureDetector clientRespBPDetector = new BackpressureDetector(madMultipleCutoff); - - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - - Flowable rxRequest = Flowable - .fromIterable(new Sequence(180, clientReqBPDetector)) - .doOnNext(i -> System.out.println(i + " -->")) - .map(BackpressureIntegrationTest::protoNum); - - Flowable rxResponse = stub.twoWayPressure(rxRequest); - - rxResponse.subscribe( - n -> { - clientRespBPDetector.tick(); - System.out.println(" " + n.getNumber(0) + " <--"); - try { Thread.sleep(50); } catch (InterruptedException e) {} - }, - t -> { - t.printStackTrace(); - synchronized (lock) { - lock.notify(); - } - }, - () -> { - System.out.println("Client done."); - synchronized (lock) { - lock.notify(); - } - }); - - synchronized (lock) { - lock.wait(TimeUnit.SECONDS.toMillis(20)); - } - - assertThat(clientReqBPDetector.backpressureDelayOcurred()).isTrue(); - assertThat(serverRespBPDetector.backpressureDelayOcurred()).isTrue(); - } - - private static NumberProto.Number protoNum(int i) { - Integer[] ints = new Integer[32 * 1024]; - Arrays.setAll(ints, operand -> i); - - return NumberProto.Number.newBuilder().addAllNumber(Arrays.asList(ints)).build(); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/CancellationPropagationIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/CancellationPropagationIntegrationTest.java deleted file mode 100644 index b75b4ac4..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/CancellationPropagationIntegrationTest.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * 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.rxgrpc; - -import com.google.protobuf.Empty; -import com.salesforce.servicelibs.NumberProto; -import com.salesforce.servicelibs.RxNumbersGrpc; -import io.grpc.*; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.reactivex.observers.TestObserver; -import io.reactivex.subscribers.TestSubscriber; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.Arrays; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.assertj.core.api.Assertions.assertThat; - -@SuppressWarnings("ALL") -public class CancellationPropagationIntegrationTest { - private static Server server; - private static ManagedChannel channel; - private static TestService svc = new TestService(); - - private static class TestService extends RxNumbersGrpc.NumbersImplBase { - private AtomicInteger lastNumberProduced = new AtomicInteger(Integer.MIN_VALUE); - private AtomicBoolean wasCanceled = new AtomicBoolean(false); - private AtomicBoolean explicitCancel = new AtomicBoolean(false); - - public void reset() { - lastNumberProduced.set(Integer.MIN_VALUE); - wasCanceled.set(false); - explicitCancel.set(false); - } - - public int getLastNumberProduced() { - return lastNumberProduced.get(); - } - - public boolean wasCanceled() { - return wasCanceled.get(); - } - - public void setExplicitCancel(boolean explicitCancel) { - this.explicitCancel.set(explicitCancel); - } - - @Override - public Flowable responsePressure(Single request) { - // Produce a very long sequence - return Flowable.fromIterable(new Sequence(10000)) - .doOnNext(i -> lastNumberProduced.set(i)) - .map(CancellationPropagationIntegrationTest::protoNum) - .doOnCancel(() -> { - wasCanceled.set(true); - System.out.println("Server canceled"); - }); - } - - @Override - public Single requestPressure(Flowable request) { - if (explicitCancel.get()) { - // Process a very long sequence - Disposable subscription = request.subscribe(n -> System.out.println("S: " + n.getNumber(0))); - return Single - .just(protoNum(-1)) - .delay(250, TimeUnit.MILLISECONDS) - // Explicitly cancel by disposing the subscription - .doOnSuccess(x -> subscription.dispose()); - } else { - // Process some of a very long sequence and cancel implicitly with a take(10) - return request.map(req -> req.getNumber(0)) - .doOnNext(System.out::println) - .take(10) - .last(-1) - .map(CancellationPropagationIntegrationTest::protoNum); - } - } - - @Override - public Flowable twoWayPressure(Flowable request) { - return requestPressure(request).toFlowable(); - } - } - - @BeforeClass - public static void setupServer() throws Exception { - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @Before - public void resetServerStats() { - svc.reset(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void clientCanCancelServerStreamExplicitly() throws InterruptedException { - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - TestSubscriber subscription = stub - .responsePressure(Single.just(Empty.getDefaultInstance())) - .doOnNext(number -> System.out.println(number.getNumber(0))) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .doOnComplete(() -> System.out.println("Completed")) - .doOnCancel(() -> System.out.println("Client canceled")) - .test(); - - Thread.sleep(250); - subscription.dispose(); - Thread.sleep(250); - - subscription.awaitTerminalEvent(3, TimeUnit.SECONDS); - // Cancellation may or may not deliver the last generated message due to delays in the gRPC processing thread - assertThat(Math.abs(subscription.valueCount() - svc.getLastNumberProduced())).isLessThanOrEqualTo(3); - assertThat(svc.wasCanceled()).isTrue(); - } - - @Test - public void clientCanCancelServerStreamImplicitly() throws InterruptedException { - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - TestSubscriber subscription = stub - .responsePressure(Single.just(Empty.getDefaultInstance())) - .doOnNext(number -> System.out.println(number.getNumber(0))) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .doOnComplete(() -> System.out.println("Completed")) - .doOnCancel(() -> System.out.println("Client canceled")) - .take(10) - .test(); - - // Consume some work - Thread.sleep(TimeUnit.SECONDS.toMillis(1)); - subscription.dispose(); - - subscription.awaitTerminalEvent(3, TimeUnit.SECONDS); - subscription.assertValueCount(10); - subscription.assertTerminated(); - assertThat(svc.wasCanceled()).isTrue(); - } - - @Test - public void serverCanCancelClientStreamImplicitly() { - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - - svc.setExplicitCancel(false); - - AtomicBoolean requestWasCanceled = new AtomicBoolean(false); - AtomicBoolean requestDidProduce = new AtomicBoolean(false); - - Flowable request = Flowable.fromIterable(new Sequence(10000)) - .map(CancellationPropagationIntegrationTest::protoNum) - .doOnNext(x -> { - requestDidProduce.set(true); - System.out.println("Produced: " + x.getNumber(0)); - }) - .doOnCancel(() -> { - requestWasCanceled.set(true); - System.out.println("Client canceled"); - }); - - TestObserver observer = stub - .requestPressure(request) - .doOnSuccess(number -> System.out.println(number.getNumber(0))) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .test(); - - observer.awaitTerminalEvent(3, TimeUnit.SECONDS); - - observer.assertError(StatusRuntimeException.class); - observer.assertTerminated(); - assertThat(requestWasCanceled.get()).isTrue(); - assertThat(requestDidProduce.get()).isTrue(); - } - - @Test - public void serverCanCancelClientStreamExplicitly() { - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - - svc.setExplicitCancel(true); - - AtomicBoolean requestWasCanceled = new AtomicBoolean(false); - AtomicBoolean requestDidProduce = new AtomicBoolean(false); - - Flowable request = Flowable.fromIterable(new Sequence(10000)) - .map(CancellationPropagationIntegrationTest::protoNum) - .doOnNext(n -> { - requestDidProduce.set(true); - System.out.println("P: " + n.getNumber(0)); - }) - .doOnCancel(() -> { - requestWasCanceled.set(true); - System.out.println("Client canceled"); - }); - - TestObserver observer = stub - .requestPressure(request) - .doOnSuccess(number -> System.out.println(number.getNumber(0))) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .test(); - - observer.awaitTerminalEvent(); - observer.assertError(StatusRuntimeException.class); - observer.assertTerminated(); - assertThat(requestWasCanceled.get()).isTrue(); - assertThat(requestDidProduce.get()).isTrue(); - } - - @Test - public void serverCanCancelClientStreamImplicitlyBidi() { - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - - svc.setExplicitCancel(false); - - AtomicBoolean requestWasCanceled = new AtomicBoolean(false); - AtomicBoolean requestDidProduce = new AtomicBoolean(false); - - Flowable request = Flowable.fromIterable(new Sequence(10000)) - .map(CancellationPropagationIntegrationTest::protoNum) - .doOnNext(x -> { - requestDidProduce.set(true); - System.out.println("Produced: " + x.getNumber(0)); - }) - .doOnCancel(() -> { - requestWasCanceled.set(true); - System.out.println("Client canceled"); - }); - - TestSubscriber observer = stub - .twoWayPressure(request) - .doOnNext(number -> System.out.println(number.getNumber(0))) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .test(); - - observer.awaitTerminalEvent(3, TimeUnit.SECONDS); - observer.assertTerminated(); - assertThat(requestWasCanceled.get()).isTrue(); - assertThat(requestDidProduce.get()).isTrue(); - } - - @Test - public void serverCanCancelClientStreamExplicitlyBidi() { - RxNumbersGrpc.RxNumbersStub stub = RxNumbersGrpc.newRxStub(channel); - - svc.setExplicitCancel(true); - - AtomicBoolean requestWasCanceled = new AtomicBoolean(false); - AtomicBoolean requestDidProduce = new AtomicBoolean(false); - - Flowable request = Flowable.fromIterable(new Sequence(10000)) - .map(CancellationPropagationIntegrationTest::protoNum) - .doOnNext(n -> { - requestDidProduce.set(true); - System.out.println("P: " + n.getNumber(0)); - }) - .doOnCancel(() -> { - requestWasCanceled.set(true); - System.out.println("Client canceled"); - }); - - TestSubscriber observer = stub - .twoWayPressure(request) - .doOnNext(number -> System.out.println(number.getNumber(0))) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .test(); - - observer.awaitTerminalEvent(); - observer.assertTerminated(); - assertThat(requestWasCanceled.get()).isTrue(); - assertThat(requestDidProduce.get()).isTrue(); - } - - private static NumberProto.Number protoNum(int i) { - Integer[] ints = {i}; - return NumberProto.Number.newBuilder().addAllNumber(Arrays.asList(ints)).build(); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ChainedCallIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ChainedCallIntegrationTest.java deleted file mode 100644 index 8fe89f6d..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ChainedCallIntegrationTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.rxgrpc; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.observers.TestObserver; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -@SuppressWarnings("Duplicates") -public class ChainedCallIntegrationTest { - private Server server; - private ManagedChannel channel; - - @Before - public void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - - @Override - public Single sayHello(Single rxRequest) { - return rxRequest.map(protoRequest -> response("[" + protoRequest.getName() + "]")); - } - - @Override - public Flowable sayHelloRespStream(Single rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .flatMapPublisher(name -> Flowable.just( - response("{" + name + "}"), - response("/" + name + "/"), - response("\\" + name + "\\"), - response("(" + name + ")")) - ); - } - - @Override - public Single sayHelloReqStream(Flowable rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .reduce((l, r) -> l + " :: " + r) - .toSingle("EMPTY") - .map(ChainedCallIntegrationTest::response); - } - - @Override - public Flowable sayHelloBothStream(Flowable rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .map(name -> "<" + name + ">") - .map(ChainedCallIntegrationTest::response); - } - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @After - public void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void servicesCanCallOtherServices() throws InterruptedException { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - - Single input = Single.just(request("X")); - Single one = stub.sayHello(input) - .map(ChainedCallIntegrationTest::bridge) - .doOnSuccess(System.out::println); - Flowable two = stub.sayHelloRespStream(one) - .map(ChainedCallIntegrationTest::bridge) - .doOnNext(System.out::println); - Flowable three = stub.sayHelloBothStream(two) - .map(ChainedCallIntegrationTest::bridge) - .doOnNext(System.out::println); - Single four = stub.sayHelloReqStream(three) - .map(ChainedCallIntegrationTest::bridge) - .doOnSuccess(System.out::println); - Single five = stub.sayHello(four) - .map(HelloResponse::getMessage) - .doOnSuccess(System.out::println); - - TestObserver test = five.test(); - - test.awaitTerminalEvent(2, TimeUnit.SECONDS); - test.assertComplete(); - test.assertValue("[<{[X]}> :: :: <\\[X]\\> :: <([X])>]"); - } - - private static HelloRequest bridge(HelloResponse response) { - return request(response.getMessage()); - } - - private static HelloRequest request(String text) { - return HelloRequest.newBuilder().setName(text).build(); - } - - private static HelloResponse response(String text) { - return HelloResponse.newBuilder().setMessage(text).build(); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ConcurrentRequestIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ConcurrentRequestIntegrationTest.java deleted file mode 100644 index 16e06fb9..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ConcurrentRequestIntegrationTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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.rxgrpc; - -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.observers.TestObserver; -import io.reactivex.subscribers.TestSubscriber; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import static org.assertj.core.api.Assertions.assertThat; - -@SuppressWarnings("Duplicates") -public class ConcurrentRequestIntegrationTest { - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - - @Override - public Single sayHello(Single rxRequest) { - return rxRequest - .doOnSuccess(System.out::println) - .map(protoRequest -> greet("Hello", protoRequest)); - } - - @Override - public Flowable sayHelloRespStream(Single rxRequest) { - return rxRequest - .doOnSuccess(System.out::println) - .flatMapPublisher(protoRequest -> Flowable.just( - greet("Hello", protoRequest), - greet("Hi", protoRequest), - greet("Greetings", protoRequest))); - } - - @Override - public Single sayHelloReqStream(Flowable rxRequest) { - return rxRequest - .doOnNext(System.out::println) - .map(HelloRequest::getName) - .toList() - .map(names -> greet("Hello", String.join(" and ", names))); - } - - @Override - public Flowable sayHelloBothStream(Flowable rxRequest) { - return rxRequest - .doOnNext(System.out::println) - .map(HelloRequest::getName) - .buffer(2) - .map(names -> greet("Hello", String.join(" and ", names))); - } - - private HelloResponse greet(String greeting, HelloRequest request) { - return greet(greeting, request.getName()); - } - - private HelloResponse greet(String greeting, String name) { - return HelloResponse.newBuilder().setMessage(greeting + " " + name).build(); - } - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void fourKindsOfRequestAtOnce() throws Exception { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - - // == MAKE REQUESTS == - // One to One - Single req1 = Single.just(HelloRequest.newBuilder().setName("rxjava").build()); - Single resp1 = stub.sayHello(req1); - - // One to Many - Single req2 = Single.just(HelloRequest.newBuilder().setName("rxjava").build()); - Flowable resp2 = stub.sayHelloRespStream(req2); - - // Many to One - Flowable req3 = Flowable.just( - HelloRequest.newBuilder().setName("a").build(), - HelloRequest.newBuilder().setName("b").build(), - HelloRequest.newBuilder().setName("c").build()); - - Single resp3 = stub.sayHelloReqStream(req3); - - // Many to Many - Flowable req4 = Flowable.just( - HelloRequest.newBuilder().setName("a").build(), - HelloRequest.newBuilder().setName("b").build(), - HelloRequest.newBuilder().setName("c").build(), - HelloRequest.newBuilder().setName("d").build(), - HelloRequest.newBuilder().setName("e").build()); - - Flowable resp4 = stub.sayHelloBothStream(req4); - - // == VERIFY RESPONSES == - ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); - - // Run all four verifications in parallel - try { - // One to One - ListenableFuture oneToOne = executorService.submit(() -> { - TestObserver testObserver1 = resp1.map(HelloResponse::getMessage).test(); - testObserver1.awaitTerminalEvent(1, TimeUnit.SECONDS); - testObserver1.assertValue("Hello rxjava"); - return true; - }); - - // One to Many - ListenableFuture oneToMany = executorService.submit(() -> { - TestSubscriber testSubscriber1 = resp2.map(HelloResponse::getMessage).test(); - testSubscriber1.awaitTerminalEvent(1, TimeUnit.SECONDS); - testSubscriber1.assertValues("Hello rxjava", "Hi rxjava", "Greetings rxjava"); - return true; - }); - - // Many to One - ListenableFuture manyToOne = executorService.submit(() -> { - TestObserver testObserver2 = resp3.map(HelloResponse::getMessage).test(); - testObserver2.awaitTerminalEvent(1, TimeUnit.SECONDS); - testObserver2.assertValue("Hello a and b and c"); - return true; - }); - - // Many to Many - ListenableFuture manyToMany = executorService.submit(() -> { - TestSubscriber testSubscriber2 = resp4.map(HelloResponse::getMessage).test(); - testSubscriber2.awaitTerminalEvent(1, TimeUnit.SECONDS); - testSubscriber2.assertValues("Hello a and b", "Hello c and d", "Hello e"); - testSubscriber2.assertComplete(); - return true; - }); - - ListenableFuture> allFutures = Futures.allAsList(Lists.newArrayList(oneToOne, oneToMany, manyToOne, manyToMany)); - // Block for response - List results = allFutures.get(3, TimeUnit.SECONDS); - assertThat(results).containsExactly(true, true, true, true); - - } finally { - executorService.shutdown(); - } - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ContextPropagationIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ContextPropagationIntegrationTest.java deleted file mode 100644 index a959eca9..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ContextPropagationIntegrationTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.rxgrpc; - -import io.grpc.*; -import io.reactivex.Single; -import io.reactivex.observers.TestObserver; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -import static org.assertj.core.api.Assertions.assertThat; - -@SuppressWarnings("Duplicates") -public class ContextPropagationIntegrationTest { - private static Server server; - private static ManagedChannel channel; - - private static Context.Key ctxKey = Context.key("ctxKey"); - private static Single worldReq = Single.just(HelloRequest.newBuilder().setName("World").build()); - - private static TestService svc = new TestService(); - private static TestClientInterceptor clientInterceptor = new TestClientInterceptor(); - private static TestServerInterceptor serverInterceptor = new TestServerInterceptor(); - - private static class TestClientInterceptor implements ClientInterceptor { - private String sendMessageCtxValue; - - public void reset() { - sendMessageCtxValue = null; - } - - public String getSendMessageCtxValue() { - return sendMessageCtxValue; - } - - @Override - public ClientCall interceptCall(MethodDescriptor method, CallOptions callOptions, Channel next) { - return new ForwardingClientCall.SimpleForwardingClientCall(next.newCall(method, callOptions)) { - @Override - public void start(Listener responseListener, Metadata headers) { - super.start(new ForwardingClientCallListener.SimpleForwardingClientCallListener(responseListener){ - @Override - public void onMessage(RespT message) { - Context.current().withValue(ctxKey, "ClientGetsContext").run(() -> super.onMessage(message)); - } - }, headers); - } - - @Override - public void sendMessage(ReqT message) { - sendMessageCtxValue = ctxKey.get(); - super.sendMessage(message); - } - }; - } - } - - private static class TestServerInterceptor implements ServerInterceptor { - @Override - public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler next) { - Context ctx = Context.current().withValue(ctxKey, "ServerAcceptsContext"); - return Contexts.interceptCall(ctx, call, headers, next); - } - } - - private static class TestService extends RxGreeterGrpc.GreeterImplBase { - private String receivedCtxValue; - - public String getReceivedCtxValue() { - return receivedCtxValue; - } - - private void reset() { - receivedCtxValue = null; - } - - @Override - public Single sayHello(Single request) { - return request - .doOnSuccess(x -> receivedCtxValue = ctxKey.get()) - .map(HelloRequest::getName) - .map(name -> HelloResponse.newBuilder().setMessage("Hello " + name).build()); - } - } - - @BeforeClass - public static void setupServer() throws Exception { - server = ServerBuilder.forPort(0).addService(ServerInterceptors.intercept(svc, serverInterceptor)).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).intercept(clientInterceptor).build(); - } - - @Before - public void resetServerStats() { - svc.reset(); - clientInterceptor.reset(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void ClientSendsContext() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Context.current() - .withValue(ctxKey, "ClientSendsContext") - .run(() -> stub.sayHello(worldReq).test().awaitTerminalEvent(1, TimeUnit.SECONDS)); - - assertThat(clientInterceptor.getSendMessageCtxValue()).isEqualTo("ClientSendsContext"); - } - - @Test - public void ClientGetsContext() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - - TestObserver testObserver = stub.sayHello(worldReq) - .doOnSuccess(resp -> { - Context ctx = Context.current(); - assertThat(ctxKey.get(ctx)).isEqualTo("ClientGetsContext"); - }) - .test(); - - testObserver.awaitTerminalEvent(1, TimeUnit.SECONDS); - testObserver.assertComplete(); - } - - @Test - public void ServerAcceptsContext() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - - stub.sayHello(worldReq).test().awaitTerminalEvent(1, TimeUnit.SECONDS); - - assertThat(svc.getReceivedCtxValue()).isEqualTo("ServerAcceptsContext"); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/EndToEndIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/EndToEndIntegrationTest.java deleted file mode 100644 index 5f862351..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/EndToEndIntegrationTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.rxgrpc; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.observers.TestObserver; -import io.reactivex.subscribers.TestSubscriber; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -@SuppressWarnings("Duplicates") -public class EndToEndIntegrationTest { - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - - @Override - public Single sayHello(Single rxRequest) { - return rxRequest.map(protoRequest -> greet("Hello", protoRequest)); - } - - @Override - public Flowable sayHelloRespStream(Single rxRequest) { - return rxRequest.flatMapPublisher(protoRequest -> Flowable.just( - greet("Hello", protoRequest), - greet("Hi", protoRequest), - greet("Greetings", protoRequest))); - } - - @Override - public Single sayHelloReqStream(Flowable rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .toList() - .map(names -> greet("Hello", String.join(" and ", names))); - } - - @Override - public Flowable sayHelloBothStream(Flowable rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .buffer(2) - .map(names -> greet("Hello", String.join(" and ", names))); - } - - private HelloResponse greet(String greeting, HelloRequest request) { - return greet(greeting, request.getName()); - } - - private HelloResponse greet(String greeting, String name) { - return HelloResponse.newBuilder().setMessage(greeting + " " + name).build(); - } - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void oneToOne() throws IOException { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Single req = Single.just(HelloRequest.newBuilder().setName("rxjava").build()); - Single resp = stub.sayHello(req); - - TestObserver testObserver = resp.map(HelloResponse::getMessage).test(); - testObserver.awaitTerminalEvent(3, TimeUnit.SECONDS); - testObserver.assertValue("Hello rxjava"); - } - - @Test - public void oneToMany() throws IOException { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Single req = Single.just(HelloRequest.newBuilder().setName("rxjava").build()); - Flowable resp = stub.sayHelloRespStream(req); - - TestSubscriber testSubscriber = resp.map(HelloResponse::getMessage).test(); - testSubscriber.awaitTerminalEvent(3, TimeUnit.SECONDS); - testSubscriber.assertValues("Hello rxjava", "Hi rxjava", "Greetings rxjava"); - } - - @Test - public void manyToOne() throws Exception { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable req = Flowable.just( - HelloRequest.newBuilder().setName("a").build(), - HelloRequest.newBuilder().setName("b").build(), - HelloRequest.newBuilder().setName("c").build()); - - Single resp = stub.sayHelloReqStream(req); - - TestObserver testObserver = resp.map(HelloResponse::getMessage).test(); - testObserver.awaitTerminalEvent(3, TimeUnit.SECONDS); - testObserver.assertValue("Hello a and b and c"); - } - - @Test - public void manyToMany() throws Exception { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable req = Flowable.just( - HelloRequest.newBuilder().setName("a").build(), - HelloRequest.newBuilder().setName("b").build(), - HelloRequest.newBuilder().setName("c").build(), - HelloRequest.newBuilder().setName("d").build(), - HelloRequest.newBuilder().setName("e").build()); - - Flowable resp = stub.sayHelloBothStream(req); - - TestSubscriber testSubscriber = resp.map(HelloResponse::getMessage).test(); - testSubscriber.awaitTerminalEvent(3, TimeUnit.SECONDS); - testSubscriber.assertValues("Hello a and b", "Hello c and d", "Hello e"); - testSubscriber.assertComplete(); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ReactiveClientStandardServerInteropTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ReactiveClientStandardServerInteropTest.java deleted file mode 100644 index 51296953..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ReactiveClientStandardServerInteropTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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.rxgrpc; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.grpc.stub.StreamObserver; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.observers.TestObserver; -import io.reactivex.subscribers.TestSubscriber; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -@SuppressWarnings("Duplicates") -public class ReactiveClientStandardServerInteropTest { - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new GreeterGrpc.GreeterImplBase() { - - @Override - public void sayHello(HelloRequest request, StreamObserver responseObserver) { - responseObserver.onNext(HelloResponse.newBuilder().setMessage("Hello " + request.getName()).build()); - responseObserver.onCompleted(); - } - - @Override - public void sayHelloRespStream(HelloRequest request, StreamObserver responseObserver) { - responseObserver.onNext(HelloResponse.newBuilder().setMessage("Hello " + request.getName()).build()); - responseObserver.onNext(HelloResponse.newBuilder().setMessage("Hi " + request.getName()).build()); - responseObserver.onNext(HelloResponse.newBuilder().setMessage("Greetings " + request.getName()).build()); - responseObserver.onCompleted(); - } - - @Override - public StreamObserver sayHelloReqStream(StreamObserver responseObserver) { - return new StreamObserver() { - List names = new ArrayList<>(); - - @Override - public void onNext(HelloRequest request) { - names.add(request.getName()); - } - - @Override - public void onError(Throwable t) { - responseObserver.onError(t); - } - - @Override - public void onCompleted() { - String message = "Hello " + String.join(" and ", names); - responseObserver.onNext(HelloResponse.newBuilder().setMessage(message).build()); - responseObserver.onCompleted(); - } - }; - } - - @Override - public StreamObserver sayHelloBothStream(StreamObserver responseObserver) { - return new StreamObserver() { - List names = new ArrayList<>(); - - @Override - public void onNext(HelloRequest request) { - names.add(request.getName()); - } - - @Override - public void onError(Throwable t) { - responseObserver.onError(t); - } - - @Override - public void onCompleted() { - // Will fail for odd number of names, but that's not what is being tested, so ¯\_(ツ)_/¯ - for (int i = 0; i < names.size(); i += 2) { - String message = "Hello " + names.get(i) + " and " + names.get(i+1); - responseObserver.onNext(HelloResponse.newBuilder().setMessage(message).build()); - } - responseObserver.onCompleted(); - } - }; - } - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void oneToOne() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Single rxRequest = Single.just("World"); - Single rxResponse = stub.sayHello(rxRequest.map(this::toRequest)).map(this::fromResponse); - - TestObserver test = rxResponse.test(); - test.awaitTerminalEvent(1, TimeUnit.SECONDS); - - test.assertNoErrors(); - test.assertValue("Hello World"); - } - - @Test - public void oneToMany() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Single rxRequest = Single.just("World"); - Flowable rxResponse = stub.sayHelloRespStream(rxRequest.map(this::toRequest)).map(this::fromResponse); - - TestSubscriber test = rxResponse.test(); - test.awaitTerminalEvent(1, TimeUnit.SECONDS); - - test.assertNoErrors(); - test.assertValues("Hello World", "Hi World", "Greetings World"); - } - - @Test - public void manyToOne() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable rxRequest = Flowable.just("A", "B", "C"); - Single rxResponse = stub.sayHelloReqStream(rxRequest.map(this::toRequest)).map(this::fromResponse); - - TestObserver test = rxResponse.test(); - test.awaitTerminalEvent(1, TimeUnit.SECONDS); - - test.assertNoErrors(); - test.assertValue("Hello A and B and C"); - } - - @Test - public void manyToMany() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable rxRequest = Flowable.just("A", "B", "C", "D"); - Flowable rxResponse = stub.sayHelloBothStream(rxRequest.map(this::toRequest)).map(this::fromResponse); - - TestSubscriber test = rxResponse.test(); - test.awaitTerminalEvent(1, TimeUnit.SECONDS); - - test.assertNoErrors(); - test.assertValues("Hello A and B", "Hello C and D"); - } - - private HelloRequest toRequest(String name) { - return HelloRequest.newBuilder().setName(name).build(); - } - - private String fromResponse(HelloResponse response) { - return response.getMessage(); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/Sequence.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/Sequence.java deleted file mode 100644 index 6de3d859..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/Sequence.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.rxgrpc; - -import javax.annotation.Nonnull; -import java.util.Iterator; - -public class Sequence implements Iterable { - private final int max; - private final BackpressureDetector backpressureDetector; - - public Sequence(int max) { - this(max, null); - } - - public Sequence(int max, BackpressureDetector backpressureDetector) { - this.max = max; - this.backpressureDetector = backpressureDetector; - } - - @Override - @Nonnull - public Iterator iterator() { - return new Iterator() { - int i = 1; - - public void remove() { - throw new UnsupportedOperationException(); - } - - public boolean hasNext() { - return i < max; - } - - public Integer next() { - if (backpressureDetector != null) { - backpressureDetector.tick(); - } - try { Thread.sleep(10); } catch (InterruptedException e) {} - return i++; - } - }; - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ServerErrorIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ServerErrorIntegrationTest.java deleted file mode 100644 index 3a7438b0..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/ServerErrorIntegrationTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.rxgrpc; - -import io.grpc.*; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.observers.TestObserver; -import io.reactivex.subscribers.TestSubscriber; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -@SuppressWarnings("ALL") -public class ServerErrorIntegrationTest { - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - @Override - public Single sayHello(Single rxRequest) { - return Single.error(new StatusRuntimeException(Status.INTERNAL)); - } - - @Override - public Flowable sayHelloRespStream(Single rxRequest) { - return Flowable.error(new StatusRuntimeException(Status.INTERNAL)); - } - - @Override - public Single sayHelloReqStream(Flowable rxRequest) { - return Single.error(new StatusRuntimeException(Status.INTERNAL)); - } - - @Override - public Flowable sayHelloBothStream(Flowable rxRequest) { - return Flowable.error(new StatusRuntimeException(Status.INTERNAL)); - } - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @AfterClass - public static void stopServer() { - server.shutdown(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void oneToOne() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Single resp = stub.sayHello(Single.just(HelloRequest.getDefaultInstance())); - TestObserver test = resp.test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - test.assertError(t -> ((StatusRuntimeException)t).getStatus() == Status.INTERNAL); - } - - @Test - public void oneToMany() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable resp = stub.sayHelloRespStream(Single.just(HelloRequest.getDefaultInstance())); - TestSubscriber test = resp - .doOnNext(msg -> System.out.println(msg)) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .doOnComplete(() -> System.out.println("Completed")) - .doOnCancel(() -> System.out.println("Client canceled")) - .test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - test.assertError(t -> ((StatusRuntimeException)t).getStatus() == Status.INTERNAL); - } - - @Test - public void manyToOne() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Single resp = stub.sayHelloReqStream(Flowable.just(HelloRequest.getDefaultInstance())); - TestObserver test = resp.test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - test.assertError(t -> ((StatusRuntimeException)t).getStatus() == Status.INTERNAL); - } - - @Test - public void manyToMany() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable resp = stub.sayHelloBothStream(Flowable.just(HelloRequest.getDefaultInstance())); - TestSubscriber test = resp.test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - test.assertError(t -> ((StatusRuntimeException)t).getStatus() == Status.INTERNAL); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/StandardClientReactiveServerInteropTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/StandardClientReactiveServerInteropTest.java deleted file mode 100644 index 85c9a7f6..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/StandardClientReactiveServerInteropTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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.rxgrpc; - -import com.salesforce.grpc.contrib.LambdaStreamObserver; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.grpc.stub.StreamObserver; -import io.reactivex.Flowable; -import io.reactivex.Single; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.hamcrest.core.IsEqual.equalTo; - -@SuppressWarnings("Duplicates") -public class StandardClientReactiveServerInteropTest { - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - - @Override - public Single sayHello(Single rxRequest) { - return rxRequest.map(protoRequest -> greet("Hello", protoRequest)); - } - - @Override - public Flowable sayHelloRespStream(Single rxRequest) { - return rxRequest.flatMapPublisher(protoRequest -> Flowable.just( - greet("Hello", protoRequest), - greet("Hi", protoRequest), - greet("Greetings", protoRequest))); - } - - @Override - public Single sayHelloReqStream(Flowable rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .toList() - .map(names -> greet("Hello", String.join(" and ", names))); - } - - @Override - public Flowable sayHelloBothStream(Flowable rxRequest) { - return rxRequest - .map(HelloRequest::getName) - .buffer(2) - .map(names -> greet("Hello", String.join(" and ", names))); - } - - private HelloResponse greet(String greeting, HelloRequest request) { - return greet(greeting, request.getName()); - } - - private HelloResponse greet(String greeting, String name) { - return HelloResponse.newBuilder().setMessage(greeting + " " + name).build(); - } - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void oneToOne() { - AtomicBoolean called = new AtomicBoolean(false); - GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel); - - HelloRequest request = HelloRequest.newBuilder().setName("World").build(); - stub.sayHello(request, new LambdaStreamObserver<>( - response -> { - assertThat(response.getMessage()).isEqualTo("Hello World"); - called.set(true); - } - )); - - await().atMost(1, TimeUnit.SECONDS).untilTrue(called); - } - - @Test - public void oneToMany() { - AtomicInteger called = new AtomicInteger(0); - GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel); - - HelloRequest request = HelloRequest.newBuilder().setName("World").build(); - stub.sayHelloRespStream(request, new LambdaStreamObserver<>( - response -> { - assertThat(response.getMessage()).isIn("Hello World", "Hi World", "Greetings World"); - called.incrementAndGet(); - } - )); - - await().atMost(1, TimeUnit.SECONDS).untilAtomic(called, equalTo(3)); - } - - @Test - public void manyToOne() { - AtomicBoolean called = new AtomicBoolean(false); - GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel); - - StreamObserver requestStream = stub.sayHelloReqStream(new LambdaStreamObserver<>( - response -> { - assertThat(response.getMessage()).isEqualTo("Hello A and B and C"); - called.set(true); - } - )); - - requestStream.onNext(HelloRequest.newBuilder().setName("A").build()); - requestStream.onNext(HelloRequest.newBuilder().setName("B").build()); - requestStream.onNext(HelloRequest.newBuilder().setName("C").build()); - requestStream.onCompleted(); - - await().atMost(1, TimeUnit.SECONDS).untilTrue(called); - } - - @Test - public void manyToMany() { - AtomicInteger called = new AtomicInteger(0); - GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel); - - StreamObserver requestStream = stub.sayHelloBothStream(new LambdaStreamObserver<>( - response -> { - assertThat(response.getMessage()).isIn("Hello A and B", "Hello C and D"); - called.incrementAndGet(); - } - )); - - requestStream.onNext(HelloRequest.newBuilder().setName("A").build()); - requestStream.onNext(HelloRequest.newBuilder().setName("B").build()); - requestStream.onNext(HelloRequest.newBuilder().setName("C").build()); - requestStream.onNext(HelloRequest.newBuilder().setName("D").build()); - requestStream.onCompleted(); - - await().atMost(1, TimeUnit.SECONDS).untilAtomic(called, equalTo(2)); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/UnexpectedServerErrorIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/UnexpectedServerErrorIntegrationTest.java deleted file mode 100644 index 59e8770b..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/UnexpectedServerErrorIntegrationTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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.rxgrpc; - -import io.grpc.*; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.observers.TestObserver; -import io.reactivex.subscribers.TestSubscriber; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -@SuppressWarnings("ALL") -public class UnexpectedServerErrorIntegrationTest { - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - @Override - public Single sayHello(Single rxRequest) { - return rxRequest.map(this::map); - } - - @Override - public Flowable sayHelloRespStream(Single rxRequest) { - return rxRequest.map(this::map).toFlowable(); - } - - @Override - public Single sayHelloReqStream(Flowable rxRequest) { - return rxRequest.map(this::map).firstOrError(); - } - - @Override - public Flowable sayHelloBothStream(Flowable rxRequest) { - return rxRequest.map(this::map); - } - - private HelloResponse map(HelloRequest request) throws Exception{ - throw Status.INTERNAL.withDescription("Kaboom!").asException(); - } - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @AfterClass - public static void stopServer() { - server.shutdown(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void oneToOne() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Single resp = stub.sayHello(Single.just(HelloRequest.getDefaultInstance())); - TestObserver test = resp.test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - test.assertError(t -> ((StatusRuntimeException)t).getStatus().getCode() == Status.Code.INTERNAL); - } - - @Test - public void oneToMany() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable resp = stub.sayHelloRespStream(Single.just(HelloRequest.getDefaultInstance())); - TestSubscriber test = resp - .doOnNext(msg -> System.out.println(msg)) - .doOnError(throwable -> System.out.println(throwable.getMessage())) - .doOnComplete(() -> System.out.println("Completed")) - .doOnCancel(() -> System.out.println("Client canceled")) - .test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - test.assertError(t -> ((StatusRuntimeException)t).getStatus().getCode() == Status.Code.INTERNAL); - } - - @Test - public void manyToOne() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable req = Flowable.just(HelloRequest.getDefaultInstance()); - Single resp = stub.sayHelloReqStream(req); - TestObserver test = resp.test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - // Flowable requests get canceled when unexpected errors happen - test.assertError(t -> ((StatusRuntimeException)t).getStatus().getCode() == Status.Code.CANCELLED); - } - - @Test - public void manyToMany() { - RxGreeterGrpc.RxGreeterStub stub = RxGreeterGrpc.newRxStub(channel); - Flowable req = Flowable.just(HelloRequest.getDefaultInstance()); - Flowable resp = stub.sayHelloBothStream(req); - TestSubscriber test = resp.test(); - - test.awaitTerminalEvent(3, TimeUnit.SECONDS); - test.assertError(t -> t instanceof StatusRuntimeException); - test.assertError(t -> ((StatusRuntimeException)t).getStatus().getCode() == Status.Code.CANCELLED); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/UnimplementedMethodIntegrationTest.java b/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/UnimplementedMethodIntegrationTest.java deleted file mode 100644 index 71fc1a03..00000000 --- a/rxgrpc/rxgrpc-test/src/test/java/com/salesforce/rxgrpc/UnimplementedMethodIntegrationTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.rxgrpc; - -import io.grpc.*; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@SuppressWarnings("Duplicates") -public class UnimplementedMethodIntegrationTest { - private static Server server; - private static ManagedChannel channel; - - @BeforeClass - public static void setupServer() throws Exception { - GreeterGrpc.GreeterImplBase svc = new RxGreeterGrpc.GreeterImplBase() { - // Don't implement anything - }; - - server = ServerBuilder.forPort(0).addService(svc).build().start(); - channel = ManagedChannelBuilder.forAddress("localhost", server.getPort()).usePlaintext(true).build(); - } - - @AfterClass - public static void stopServer() throws InterruptedException { - server.shutdown(); - server.awaitTermination(); - channel.shutdown(); - - server = null; - channel = null; - } - - @Test - public void unimplementedMethodShouldFail() { - GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel); - - assertThatThrownBy(() -> stub.sayHello(HelloRequest.newBuilder().setName("World").build())) - .isInstanceOf(StatusRuntimeException.class) - .hasMessageContaining("UNIMPLEMENTED"); - } -} diff --git a/rxgrpc/rxgrpc-test/src/test/proto/backpressure.proto b/rxgrpc/rxgrpc-test/src/test/proto/backpressure.proto deleted file mode 100644 index 4857734c..00000000 --- a/rxgrpc/rxgrpc-test/src/test/proto/backpressure.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; - -package com.salesforce.servicelibs; - -option java_package = "com.salesforce.servicelibs"; -option java_outer_classname = "NumberProto"; - -import "google/protobuf/empty.proto"; - -service Numbers { - rpc RequestPressure (stream Number) returns (Number) {} - rpc ResponsePressure (google.protobuf.Empty) returns (stream Number) {} - rpc TwoWayPressure (stream Number) returns (stream Number) {} -} - -message Number { - repeated int32 number = 1; -} diff --git a/rxgrpc/rxgrpc-test/src/test/proto/helloworld.proto b/rxgrpc/rxgrpc-test/src/test/proto/helloworld.proto deleted file mode 100644 index 665564ca..00000000 --- a/rxgrpc/rxgrpc-test/src/test/proto/helloworld.proto +++ /dev/null @@ -1,30 +0,0 @@ -syntax = "proto3"; - -package helloworld; - -option java_multiple_files = true; -option java_package = "com.salesforce.rxgrpc"; -option java_outer_classname = "HelloWorldProto"; - -// The greeting service definition. -service Greeter { - // Sends a greeting - rpc SayHello (HelloRequest) returns (HelloResponse) {} - rpc SayHelloRespStream (HelloRequest) returns (stream HelloResponse) {} - rpc SayHelloReqStream (stream HelloRequest) returns (HelloResponse) {} - rpc SayHelloBothStream (stream HelloRequest) returns (stream HelloResponse) {} -} - -service Dismisser { - rpc SayGoodbye (HelloRequest) returns (HelloResponse) {} -} - -// The request message containing the user's name. -message HelloRequest { - string name = 1; -} - -// The response message containing the greetings -message HelloResponse { - string message = 1; -} \ No newline at end of file diff --git a/rxgrpc/rxgrpc/README.md b/rxgrpc/rxgrpc/README.md deleted file mode 100644 index c6706d44..00000000 --- a/rxgrpc/rxgrpc/README.md +++ /dev/null @@ -1,53 +0,0 @@ -[![Javadocs](https://javadoc.io/badge/com.salesforce.servicelibs/rxgrpc-stub.svg)](https://javadoc.io/doc/com.salesforce.servicelibs/rxgrpc-stub) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.salesforce.servicelibs/rxgrpc/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.salesforce.servicelibs/rxgrpc) - - -Usage -===== -```xml - - - ... - - - - - kr.motd.maven - os-maven-plugin - 1.4.1.Final - - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.5.0 - - com.google.protobuf:protoc:3.0.2:exe:${os.detected.classifier} - grpc-java - io.grpc:protoc-gen-grpc-java:1.2.0:exe:${os.detected.classifier} - - - - - test-compile - test-compile-custom - - - - - rxgrpc - com.salesforce.servicelibs - rxgrpc - [VERSION] - com.salesforce.rxgrpc.RxGrpcGenerator - - - - - - - - - -``` \ No newline at end of file diff --git a/rxgrpc/rxgrpc/pom.xml b/rxgrpc/rxgrpc/pom.xml deleted file mode 100644 index 7053f1ef..00000000 --- a/rxgrpc/rxgrpc/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - grpc-contrib-parent - com.salesforce.servicelibs - 0.6.2-SNAPSHOT - ../../pom.xml - - 4.0.0 - - rxgrpc - - - - io.grpc - grpc-protobuf - - - - com.salesforce.servicelibs - jprotoc - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - ../../checkstyle.xml - ../../checkstyle_ignore.xml - - - - - \ No newline at end of file diff --git a/rxgrpc/rxgrpc/src/main/java/com/salesforce/rxgrpc/RxGrpcGenerator.java b/rxgrpc/rxgrpc/src/main/java/com/salesforce/rxgrpc/RxGrpcGenerator.java deleted file mode 100644 index 267f1b04..00000000 --- a/rxgrpc/rxgrpc/src/main/java/com/salesforce/rxgrpc/RxGrpcGenerator.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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.rxgrpc; - -import com.google.common.base.Strings; -import com.google.protobuf.DescriptorProtos; -import com.google.protobuf.DescriptorProtos.*; -import com.google.protobuf.compiler.PluginProtos; -import com.salesforce.jprotoc.Generator; -import com.salesforce.jprotoc.GeneratorException; -import com.salesforce.jprotoc.ProtoTypeMap; -import com.salesforce.jprotoc.ProtocPlugin; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * A protoc generator for generating ReactiveX 2.0 bindings for gRPC. - */ -public class RxGrpcGenerator extends Generator { - private static final String CLASS_PREFIX = "Rx"; - - public static void main(String[] args) { - ProtocPlugin.generate(new RxGrpcGenerator()); - } - - @Override - public Stream generate(PluginProtos.CodeGeneratorRequest request) throws GeneratorException { - final ProtoTypeMap typeMap = ProtoTypeMap.of(request.getProtoFileList()); - - List protosToGenerate = request.getProtoFileList().stream() - .filter(protoFile -> request.getFileToGenerateList().contains(protoFile.getName())) - .collect(Collectors.toList()); - - List services = findServices(protosToGenerate, typeMap); - List files = generateFiles(services); - return files.stream(); - } - - private List findServices(List protos, ProtoTypeMap typeMap) { - List contexts = new ArrayList<>(); - - for (FileDescriptorProto fileProto : protos) { - for (ServiceDescriptorProto serviceProto : fileProto.getServiceList()) { - ServiceContext serviceContext = buildServiceContext(serviceProto, typeMap); - serviceContext.protoName = fileProto.getName(); - serviceContext.packageName = extractPackageName(fileProto); - contexts.add(serviceContext); - } - } - - return contexts; - } - - private String extractPackageName(DescriptorProtos.FileDescriptorProto proto) { - DescriptorProtos.FileOptions options = proto.getOptions(); - if (options != null) { - String javaPackage = options.getJavaPackage(); - if (!Strings.isNullOrEmpty(javaPackage)) { - return javaPackage; - } - } - - return Strings.nullToEmpty(proto.getPackage()); - } - - private ServiceContext buildServiceContext(ServiceDescriptorProto serviceProto, ProtoTypeMap typeMap) { - ServiceContext serviceContext = new ServiceContext(); - serviceContext.fileName = CLASS_PREFIX + serviceProto.getName() + "Grpc.java"; - serviceContext.className = CLASS_PREFIX + serviceProto.getName() + "Grpc"; - serviceContext.serviceName = serviceProto.getName(); - serviceContext.deprecated = serviceProto.getOptions() != null && serviceProto.getOptions().getDeprecated(); - - serviceContext.oneToOne = serviceProto.getMethodList().stream() - .filter(method -> !method.getClientStreaming() && !method.getServerStreaming()) - .map(methodProto -> buildMethodContext(methodProto, typeMap)) - .collect(Collectors.toList()); - - serviceContext.oneToMany = serviceProto.getMethodList().stream() - .filter(method -> !method.getClientStreaming() && method.getServerStreaming()) - .map(methodProto -> buildMethodContext(methodProto, typeMap)) - .collect(Collectors.toList()); - - serviceContext.manyToOne = serviceProto.getMethodList().stream() - .filter(method -> method.getClientStreaming() && !method.getServerStreaming()) - .map(methodProto -> buildMethodContext(methodProto, typeMap)) - .collect(Collectors.toList()); - - serviceContext.manyToMany = serviceProto.getMethodList().stream() - .filter(method -> method.getClientStreaming() && method.getServerStreaming()) - .map(methodProto -> buildMethodContext(methodProto, typeMap)) - .collect(Collectors.toList()); - - return serviceContext; - } - - private MethodContext buildMethodContext(MethodDescriptorProto methodProto, ProtoTypeMap typeMap) { - MethodContext methodContext = new MethodContext(); - methodContext.methodName = lowerCaseFirst(methodProto.getName()); - methodContext.inputType = typeMap.toJavaTypeName(methodProto.getInputType()); - methodContext.outputType = typeMap.toJavaTypeName(methodProto.getOutputType()); - methodContext.deprecated = methodProto.getOptions() != null && methodProto.getOptions().getDeprecated(); - return methodContext; - } - - private String lowerCaseFirst(String s) { - return Character.toLowerCase(s.charAt(0)) + s.substring(1); - } - - private List generateFiles(List services) { - return services.stream() - .map(this::buildFile) - .collect(Collectors.toList()); - } - - private PluginProtos.CodeGeneratorResponse.File buildFile(ServiceContext context) { - String content = applyTemplate("RxStub.mustache", context); - return PluginProtos.CodeGeneratorResponse.File - .newBuilder() - .setName(absoluteFileName(context)) - .setContent(content) - .build(); - } - - private String absoluteFileName(ServiceContext ctx) { - String dir = ctx.packageName.replace('.', '/'); - if (Strings.isNullOrEmpty(dir)) { - return ctx.fileName; - } else { - return dir + "/" + ctx.fileName; - } - } - - /** - * Template class for proto Service objects. - */ - private class ServiceContext { - // CHECKSTYLE DISABLE VisibilityModifier FOR 11 LINES - public String fileName; - public String protoName; - public String packageName; - public String className; - public String serviceName; - public boolean deprecated; - - public List oneToOne; - public List oneToMany; - public List manyToOne; - public List manyToMany; - - public boolean getHasOneToOne() { - return oneToOne != null && oneToOne.size() > 0; - } - - public boolean getHasOneToMany() { - return oneToMany != null && oneToMany.size() > 0; - } - - public boolean getHasManyToOne() { - return manyToOne != null && manyToOne.size() > 0; - } - - public boolean getHasManyToMany() { - return manyToMany != null && manyToMany.size() > 0; - } - } - - /** - * Template class for proto RPC objects. - */ - private class MethodContext { - // CHECKSTYLE DISABLE VisibilityModifier FOR 4 LINES - public String methodName; - public String inputType; - public String outputType; - public boolean deprecated; - } -} diff --git a/rxgrpc/rxgrpc/src/main/resources/RxStub.mustache b/rxgrpc/rxgrpc/src/main/resources/RxStub.mustache deleted file mode 100644 index 60f7d4ad..00000000 --- a/rxgrpc/rxgrpc/src/main/resources/RxStub.mustache +++ /dev/null @@ -1,101 +0,0 @@ -{{#packageName}} -package {{packageName}}; -{{/packageName}} - -import com.salesforce.rxgrpc.stub.*; -import com.google.common.util.concurrent.Runnables; -import io.grpc.Channel; -import io.grpc.Status; -import io.grpc.StatusRuntimeException; -import io.grpc.stub.StreamObserver; -import io.reactivex.*; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -import com.salesforce.rxgrpc.stub.ClientCalls; -import com.salesforce.rxgrpc.stub.ServerCalls; - -{{#deprecated}}@Deprecated{{/deprecated}} -@javax.annotation.Generated( -value = "by RxGrpc generator", -comments = "Source: {{protoName}}") -public final class {{className}} { - private {{className}}() {} - - public static Rx{{serviceName}}Stub newRxStub(Channel channel) { - return new Rx{{serviceName}}Stub(channel); - } - - public static final class Rx{{serviceName}}Stub { - private {{serviceName}}Grpc.{{serviceName}}Stub delegateStub; - - private Rx{{serviceName}}Stub(Channel channel) { - delegateStub = {{serviceName}}Grpc.newStub(channel); - } - {{#oneToOne}}{{#deprecated}}@Deprecated{{/deprecated}} - public Single<{{outputType}}> {{methodName}}(Single<{{inputType}}> rxRequest) { - return ClientCalls.oneToOne(rxRequest, delegateStub::{{methodName}}); - } - {{/oneToOne}} - {{#oneToMany}}{{#deprecated}}@Deprecated{{/deprecated}} - public Flowable<{{outputType}}> {{methodName}}(Single<{{inputType}}> rxRequest) { - return ClientCalls.oneToMany(rxRequest, delegateStub::{{methodName}}); - } - {{/oneToMany}} - {{#manyToOne}}{{#deprecated}}@Deprecated{{/deprecated}} - public Single<{{outputType}}> {{methodName}}(Flowable<{{inputType}}> rxRequest) { - return ClientCalls.manyToOne(rxRequest, delegateStub::{{methodName}}); - } - {{/manyToOne}} - {{#manyToMany}}{{#deprecated}}@Deprecated{{/deprecated}} - public Flowable<{{outputType}}> {{methodName}}(Flowable<{{inputType}}> rxRequest) { - return ClientCalls.manyToMany(rxRequest, delegateStub::{{methodName}}); - } - {{/manyToMany}} - } - - public static abstract class {{serviceName}}ImplBase extends {{serviceName}}Grpc.{{serviceName}}ImplBase { - {{#oneToOne}}{{#deprecated}}@Deprecated{{/deprecated}} - public Single<{{outputType}}> {{methodName}}(Single<{{inputType}}> request) { - throw new StatusRuntimeException(Status.UNIMPLEMENTED); - } - - @Override - public void {{methodName}}({{inputType}} request, StreamObserver<{{outputType}}> responseObserver) { - ServerCalls.oneToOne(request, responseObserver, this::{{methodName}}); - } - {{/oneToOne}} - {{#oneToMany}}{{#deprecated}}@Deprecated{{/deprecated}} - public Flowable<{{outputType}}> {{methodName}}(Single<{{inputType}}> request) { - throw new StatusRuntimeException(Status.UNIMPLEMENTED); - } - - @Override - public void {{methodName}}({{inputType}} request, StreamObserver<{{outputType}}> responseObserver) { - ServerCalls.oneToMany(request, responseObserver, this::{{methodName}}); - } - {{/oneToMany}} - {{#manyToOne}}{{#deprecated}}@Deprecated{{/deprecated}} - public Single<{{outputType}}> {{methodName}}(Flowable<{{inputType}}> request) { - throw new StatusRuntimeException(Status.UNIMPLEMENTED); - } - - @Override - public StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver) { - return ServerCalls.manyToOne(responseObserver, this::{{methodName}}); - } - {{/manyToOne}} - {{#manyToMany}}{{#deprecated}}@Deprecated{{/deprecated}} - public Flowable<{{outputType}}> {{methodName}}(Flowable<{{inputType}}> request) { - throw new StatusRuntimeException(Status.UNIMPLEMENTED); - } - - @Override - public StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver) { - return ServerCalls.manyToMany(responseObserver, this::{{methodName}}); - } - {{/manyToMany}} - } -}