forked from ReactiveX/RxJava
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ReactiveX#35 Add Reactor support for circuit breaker, bulkhead and ra…
…te limiter. (ReactiveX#205) * ReactiveX#35 Add Reactor support for circuit breaker, bulkhead and rate limiter. * Fix Codacity warnings * Commit build.gradle file for resilence4j-reactor * Static import assertThat
- Loading branch information
Showing
33 changed files
with
1,335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
dependencies { | ||
compileOnly project(':resilience4j-circuitbreaker') | ||
compileOnly project(':resilience4j-ratelimiter') | ||
compileOnly project(':resilience4j-bulkhead') | ||
compileOnly project(':resilience4j-retry') | ||
compile (libraries.reactor) | ||
testCompile project(':resilience4j-test') | ||
testCompile project(':resilience4j-circuitbreaker') | ||
testCompile project(':resilience4j-ratelimiter') | ||
testCompile project(':resilience4j-bulkhead') | ||
testCompile project(':resilience4j-retry') | ||
testCompile (libraries.reactor_test) | ||
testCompile (libraries.assertj) | ||
testCompile (libraries.reactive_streams_tck) | ||
} |
11 changes: 11 additions & 0 deletions
11
resilience4j-reactor/src/main/java/io/github/resilience4j/reactor/FluxResilience.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package io.github.resilience4j.reactor; | ||
|
||
import reactor.core.publisher.Flux; | ||
|
||
public abstract class FluxResilience<T> extends Flux<T> { | ||
|
||
public static <T> Flux<T> onAssembly(Flux<T> source) { | ||
return Flux.onAssembly(source); | ||
} | ||
|
||
} |
10 changes: 10 additions & 0 deletions
10
resilience4j-reactor/src/main/java/io/github/resilience4j/reactor/MonoResilience.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package io.github.resilience4j.reactor; | ||
|
||
import reactor.core.publisher.Mono; | ||
|
||
public abstract class MonoResilience<T> extends Mono<T> { | ||
|
||
public static <T> Mono<T> onAssembly(Mono<T> source) { | ||
return Mono.onAssembly(source); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
resilience4j-reactor/src/main/java/io/github/resilience4j/reactor/Permit.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package io.github.resilience4j.reactor; | ||
|
||
/** | ||
* Represents the possible states of a permit. | ||
*/ | ||
public enum Permit { | ||
PENDING, ACQUIRED, REJECTED | ||
} |
64 changes: 64 additions & 0 deletions
64
...ctor/src/main/java/io/github/resilience4j/reactor/bulkhead/operator/BulkheadOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package io.github.resilience4j.reactor.bulkhead.operator; | ||
|
||
import io.github.resilience4j.bulkhead.Bulkhead; | ||
import io.github.resilience4j.reactor.FluxResilience; | ||
import io.github.resilience4j.reactor.MonoResilience; | ||
import org.reactivestreams.Publisher; | ||
import reactor.core.publisher.Flux; | ||
import reactor.core.publisher.Mono; | ||
import reactor.core.scheduler.Scheduler; | ||
import reactor.core.scheduler.Schedulers; | ||
|
||
import java.util.function.Function; | ||
|
||
/** | ||
* A Reactor operator which wraps a reactive type in a bulkhead. | ||
* | ||
* @param <T> the value type of the upstream and downstream | ||
*/ | ||
public class BulkheadOperator<T> implements Function<Publisher<T>, Publisher<T>> { | ||
private final Bulkhead bulkhead; | ||
private final Scheduler scheduler; | ||
|
||
private BulkheadOperator(Bulkhead bulkhead, Scheduler scheduler) { | ||
this.bulkhead = bulkhead; | ||
this.scheduler = scheduler; | ||
} | ||
|
||
/** | ||
* Creates a BulkheadOperator. | ||
* | ||
* @param <T> the value type of the upstream and downstream | ||
* @param bulkhead the Bulkhead | ||
* @return a BulkheadOperator | ||
*/ | ||
public static <T> BulkheadOperator<T> of(Bulkhead bulkhead) { | ||
return of(bulkhead, Schedulers.parallel()); | ||
} | ||
|
||
/** | ||
* Creates a BulkheadOperator. | ||
* | ||
* @param <T> the value type of the upstream and downstream | ||
* @param bulkhead the Bulkhead | ||
* @param scheduler the {@link Scheduler} where to publish | ||
* @return a BulkheadOperator | ||
*/ | ||
public static <T> BulkheadOperator<T> of(Bulkhead bulkhead, Scheduler scheduler) { | ||
return new BulkheadOperator<>(bulkhead, scheduler); | ||
} | ||
|
||
@Override | ||
public Publisher<T> apply(Publisher<T> publisher) { | ||
if (publisher instanceof Mono) { | ||
return MonoResilience | ||
.onAssembly(new MonoBulkhead<T>((Mono<? extends T>) publisher, bulkhead, scheduler)); | ||
} else if (publisher instanceof Flux) { | ||
return FluxResilience | ||
.onAssembly(new FluxBulkhead<T>((Flux<? extends T>) publisher, bulkhead, scheduler)); | ||
} | ||
|
||
throw new IllegalStateException("Publisher of type <" + publisher.getClass().getSimpleName() | ||
+ "> are not supported by this operator"); | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
...or/src/main/java/io/github/resilience4j/reactor/bulkhead/operator/BulkheadSubscriber.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package io.github.resilience4j.reactor.bulkhead.operator; | ||
|
||
import io.github.resilience4j.bulkhead.Bulkhead; | ||
import io.github.resilience4j.bulkhead.BulkheadFullException; | ||
import io.github.resilience4j.reactor.Permit; | ||
import org.reactivestreams.Subscriber; | ||
import org.reactivestreams.Subscription; | ||
import reactor.core.CoreSubscriber; | ||
import reactor.core.publisher.Operators; | ||
|
||
import java.util.concurrent.atomic.AtomicReference; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
/** | ||
* A Reactor {@link Subscriber} to wrap another subscriber in a bulkhead. | ||
* | ||
* @param <T> the value type of the upstream and downstream | ||
*/ | ||
class BulkheadSubscriber<T> extends Operators.MonoSubscriber<T, T> { | ||
|
||
private final Bulkhead bulkhead; | ||
private final AtomicReference<Permit> permitted = new AtomicReference<>(Permit.PENDING); | ||
|
||
private Subscription subscription; | ||
|
||
public BulkheadSubscriber(Bulkhead bulkhead, | ||
CoreSubscriber<? super T> actual) { | ||
super(actual); | ||
this.bulkhead = requireNonNull(bulkhead); | ||
} | ||
|
||
@Override | ||
public void onSubscribe(Subscription subscription) { | ||
if (Operators.validate(this.subscription, subscription)) { | ||
this.subscription = subscription; | ||
if (acquireCallPermit()) { | ||
actual.onSubscribe(this); | ||
} else { | ||
cancel(); | ||
actual.onSubscribe(this); | ||
actual.onError(new BulkheadFullException( | ||
String.format("Bulkhead '%s' is full", bulkhead.getName()))); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void onNext(T t) { | ||
requireNonNull(t); | ||
|
||
if (isInvocationPermitted()) { | ||
actual.onNext(t); | ||
} | ||
} | ||
|
||
@Override | ||
public void onError(Throwable t) { | ||
requireNonNull(t); | ||
|
||
if (isInvocationPermitted()) { | ||
bulkhead.onComplete(); | ||
actual.onError(t); | ||
} | ||
} | ||
|
||
@Override | ||
public void onComplete() { | ||
if (isInvocationPermitted()) { | ||
releaseBulkhead(); | ||
actual.onComplete(); | ||
} | ||
} | ||
|
||
@Override | ||
public void request(long n) { | ||
subscription.request(n); | ||
} | ||
|
||
@Override | ||
public void cancel() { | ||
super.cancel(); | ||
} | ||
|
||
private boolean acquireCallPermit() { | ||
boolean callPermitted = false; | ||
if (permitted.compareAndSet(Permit.PENDING, Permit.ACQUIRED)) { | ||
callPermitted = bulkhead.isCallPermitted(); | ||
if (!callPermitted) { | ||
permitted.set(Permit.REJECTED); | ||
} | ||
} | ||
return callPermitted; | ||
} | ||
|
||
private boolean isInvocationPermitted() { | ||
return notCancelled() && wasCallPermitted(); | ||
} | ||
|
||
private boolean notCancelled() { | ||
return !this.isCancelled(); | ||
} | ||
|
||
private boolean wasCallPermitted() { | ||
return permitted.get() == Permit.ACQUIRED; | ||
} | ||
|
||
private void releaseBulkhead() { | ||
if (wasCallPermitted()) { | ||
bulkhead.onComplete(); | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...-reactor/src/main/java/io/github/resilience4j/reactor/bulkhead/operator/FluxBulkhead.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package io.github.resilience4j.reactor.bulkhead.operator; | ||
|
||
import io.github.resilience4j.bulkhead.Bulkhead; | ||
import reactor.core.CoreSubscriber; | ||
import reactor.core.publisher.Flux; | ||
import reactor.core.publisher.FluxOperator; | ||
import reactor.core.scheduler.Scheduler; | ||
|
||
public class FluxBulkhead<T> extends FluxOperator<T, T> { | ||
|
||
private final Bulkhead bulkhead; | ||
private final Scheduler scheduler; | ||
|
||
public FluxBulkhead(Flux<? extends T> source, Bulkhead bulkhead, | ||
Scheduler scheduler) { | ||
super(source); | ||
this.bulkhead = bulkhead; | ||
this.scheduler = scheduler; | ||
} | ||
|
||
@Override | ||
public void subscribe(CoreSubscriber<? super T> actual) { | ||
source.publishOn(scheduler) | ||
.subscribe(new BulkheadSubscriber<>(bulkhead, actual)); | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
...-reactor/src/main/java/io/github/resilience4j/reactor/bulkhead/operator/MonoBulkhead.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package io.github.resilience4j.reactor.bulkhead.operator; | ||
|
||
import io.github.resilience4j.bulkhead.Bulkhead; | ||
import reactor.core.CoreSubscriber; | ||
import reactor.core.publisher.Mono; | ||
import reactor.core.publisher.MonoOperator; | ||
import reactor.core.scheduler.Scheduler; | ||
|
||
public class MonoBulkhead<T> extends MonoOperator<T, T> { | ||
private final Bulkhead bulkhead; | ||
private final Scheduler scheduler; | ||
|
||
public MonoBulkhead(Mono<? extends T> source, Bulkhead bulkhead, | ||
Scheduler scheduler) { | ||
super(source); | ||
this.bulkhead = bulkhead; | ||
this.scheduler = scheduler; | ||
} | ||
|
||
@Override | ||
public void subscribe(CoreSubscriber<? super T> actual) { | ||
source.publishOn(scheduler) | ||
.subscribe(new BulkheadSubscriber<>(bulkhead, actual)); | ||
} | ||
} |
Oops, something went wrong.