com.salesforce.rxgrpc.GrpcRetry Maven / Gradle / Ivy
/*
* Copyright (c) 2019, Salesforce.com, Inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
package com.salesforce.rxgrpc;
import io.reactivex.*;
import io.reactivex.functions.Function;
import org.reactivestreams.Publisher;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
/**
* {@code GrpcRetry} is used to transparently re-establish a streaming gRPC request in the event of a server error.
*
* During a retry, the upstream rx pipeline is re-subscribed to acquire a request message and the RPC call re-issued.
* The downstream rx pipeline never sees the error.
*/
public final class GrpcRetry {
private GrpcRetry() { }
/**
* {@link GrpcRetry} functions for streaming response gRPC operations.
*/
public static final class OneToMany {
private OneToMany() { }
/**
* Retries a streaming gRPC call, using the same semantics as {@link Flowable#retryWhen(Function)}.
*
* For easier use, use the RetryWhen builder from
* RxJava2 Extras.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param handler receives a Publisher of notifications with which a user can complete or error, aborting the retry
* @param I
* @param O
*
* @see Flowable#retryWhen(Function)
*/
public static SingleConverter> retryWhen(final Function, Flowable> operation, final Function super Flowable, ? extends Publisher>> handler) {
return new SingleConverter>() {
@Override
public Flowable apply(final Single request) {
return Flowable.defer(new Callable>() {
@Override
public Publisher call() throws Exception {
return operation.apply(request);
}
}).retryWhen(handler);
}
};
}
/**
* Retries a streaming gRPC call with a fixed delay between retries.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param delay the delay between retries
* @param unit the units to use for {@code delay}
* @param I
* @param O
*/
public static SingleConverter> retryAfter(final Function, Flowable> operation, final int delay, final TimeUnit unit) {
return retryWhen(operation, new Function, Publisher>>() {
@Override
public Publisher> apply(Flowable errors) {
return errors.flatMap(new Function>() {
@Override
public Publisher> apply(Throwable error) {
return Flowable.timer(delay, unit);
}
});
}
});
}
/**
* Retries a streaming gRPC call immediately.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param I
* @param O
*/
public static SingleConverter> retryImmediately(final Function, Flowable> operation) {
return retryWhen(operation, new Function, Publisher>>() {
@Override
public Publisher> apply(Flowable errors) {
return errors;
}
});
}
}
/**
* {@link GrpcRetry} functions for bi-directional streaming gRPC operations.
*/
public static final class ManyToMany {
private ManyToMany() { }
/**
* Retries a streaming gRPC call, using the same semantics as {@link Flowable#retryWhen(Function)}.
*
* For easier use, use the RetryWhen builder from
* RxJava2 Extras.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param handler receives a Publisher of notifications with which a user can complete or error, aborting the retry
* @param I
* @param O
*
* @see Flowable#retryWhen(Function)
*/
public static FlowableTransformer retryWhen(final Function, Flowable> operation, final Function super Flowable, ? extends Publisher>> handler) {
return new FlowableTransformer() {
@Override
public Flowable apply(final Flowable request) {
return Flowable.defer(new Callable>() {
@Override
public Publisher call() throws Exception {
return operation.apply(request);
}
}).retryWhen(handler);
}
};
}
/**
* Retries a streaming gRPC call with a fixed delay between retries.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param delay the delay between retries
* @param unit the units to use for {@code delay}
* @param I
* @param O
*/
public static FlowableTransformer retryAfter(final Function, Flowable> operation, final int delay, final TimeUnit unit) {
return retryWhen(operation, new Function, Publisher>>() {
@Override
public Publisher> apply(Flowable errors) {
return errors.flatMap(new Function>() {
@Override
public Publisher> apply(Throwable error) {
return Flowable.timer(delay, unit);
}
});
}
});
}
/**
* Retries a streaming gRPC call immediately.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param I
* @param O
*/
public static FlowableTransformer retryImmediately(final Function, Flowable> operation) {
return retryWhen(operation, new Function, Publisher>>() {
@Override
public Publisher> apply(Flowable errors) {
return errors;
}
});
}
}
/**
* {@link GrpcRetry} functions for streaming request gRPC operations.
*/
public static final class ManyToOne {
private ManyToOne() { }
/**
* Retries a streaming gRPC call, using the same semantics as {@link Flowable#retryWhen(Function)}.
*
* For easier use, use the RetryWhen builder from
* RxJava2 Extras.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param handler receives a Publisher of notifications with which a user can complete or error, aborting the retry
* @param I
* @param O
*
* @see Flowable#retryWhen(Function)
*/
public static FlowableConverter> retryWhen(final Function, Single> operation, final Function super Flowable, ? extends Publisher>> handler) {
return new FlowableConverter>() {
@Override
public Single apply(final Flowable request) {
return Single.defer(new Callable>() {
@Override
public SingleSource call() throws Exception {
return operation.apply(request);
}
}).retryWhen(handler);
}
};
}
/**
* Retries a streaming gRPC call with a fixed delay between retries.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param delay the delay between retries
* @param unit the units to use for {@code delay}
* @param I
* @param O
*/
public static FlowableConverter> retryAfter(final Function, Single> operation, final int delay, final TimeUnit unit) {
return retryWhen(operation, new Function, Publisher>>() {
@Override
public Publisher> apply(Flowable errors) {
return errors.flatMap(new Function>() {
@Override
public Publisher> apply(Throwable error) {
return Flowable.timer(delay, unit);
}
});
}
});
}
/**
* Retries a streaming gRPC call immediately.
*
* @param operation the gRPC operation to retry, typically from a generated reactive-grpc stub class
* @param I
* @param O
*/
public static FlowableConverter> retryImmediately(final Function, Single> operation) {
return retryWhen(operation, new Function, Publisher>>() {
@Override
public Publisher> apply(Flowable errors) {
return errors;
}
});
}
}
}