Migrate HystrixCommands to Resilience4j
Asked Answered
G

1

6

Given Hystrix going into mainentance mode, I've been working on migrating a (rather large) codebase to Resilience4j.

I make heavy use of the following pattern with Hystrix:

new HystrixCommand<SomeReturnValue>(DependencyKeys.DEPENDENCY) {
    @Override
    protected SomeReturnValue run() {
        return someExpensiveCall();
    }
}
    .observe()

And I want to replicate some of Hystrix' functionality with Resilience4j.

So far I have the following syntax to wire up an external call:

resilience.single(DependencyKeys.DEPENDENCY, this::someExpensiveCall);

Where the Resilience class provides the single method:

public <T> Single<T> single(ResilienceKey key, Callable<T> callable) {
    return Completable.complete()
            .subscribeOn(Schedulers.computation())
            .observeOn(configuration.scheduler(key))
            .andThen(Single.defer(() -> Single.fromCallable(callable)
                    .lift(CircuitBreakerOperator.of(configuration.circuitBreaker(key)))
                    .lift(RateLimiterOperator.of(configuration.rateLimiter(key)))
                    .lift(BulkheadOperator.of(configuration.bulkhead(key)))
            ))
            .observeOn(Schedulers.computation());
}

How could this look to better resemble what you get with Hystrix in terms of circuit breaking and running the code on different thread pools, but in a more sane way. I really don't like starting the chain off with a Completable.complete() just so I can force the observeOn before the actual callable is wrapped.

Guzel answered 17/1, 2019 at 15:16 Comment(0)
R
3

I think there is no direct replacement of HystrixCommand in Resilience4j. The most similar thing would be CircuitBreaker.decorateCompletionStage or CircuitBreaker.executeCompletionStage. Using this methods you can decorate any type on CompletableFuture supplier. Other option would be to rely on our integration with different async modules like rxjava2 or reactor. And of course if none of this options doesn't fit you, please don't forget that Resilience4j is very unopinionated, modular and composable library. You can fit our circuit breaker in any kind of library on concurrency paradigm by using our 3 lowest level methods:

  1. CircuitBreaker.isCallPermitted
  2. CircuitBreaker.onError
  3. CircuitBreaker.onSuccess

Same things are true for our other core components. I hope this answer help at least a little bit. If you have any other questions, I'll be happy to help. Happy hacking 😉

Rab answered 20/1, 2019 at 12:42 Comment(1)
I appreciate the response! I'm using the rxjava2 integration, the .lift(CircuitBreakerOperator.of(configuration.circuitBreaker(key))) operators are effectively wrapping the deferred async function. I guess the question I'm really asking is: assuming this works, is it best practice from an RxJava2 and Resilience4j point of view.Guzel

© 2022 - 2024 — McMap. All rights reserved.