Thanks for raising a Resilience4j issue.
Please provide a brief description of your problem along with the versions you are using.
If possible, please also consider putting together a complete JUnit test that reproduces the issue.
Resilience4j version:
1.2.0
Java version:
1.8
Problem description:
I am unable to find an example with clarity or documentation with clarity as what is ThreadPoolBuilkhead, BulkHead and Semaphore Bulkhead are the same?. I am using annotation based BulkHead pattern. I have the following configuration.
resilience4j.bulkhead:
configs:
default:
registerHealthIndicator: true
maxConcurrentCalls: 5
resilience4j.thread-pool-bulkhead:
configs:
default:
registerHealthIndicator: true
maxThreadPoolSize: 1
coreThreadPoolSize: 1
queueCapacity: 1
I have lost bit clarity on what are the key differences between the two builkhead implementations when it comes to usecases. The documentation doesn't give info regarding the same. So I need help interns of documentation or a simple clarification would help me a lot in using this library with more understanding.
Thanks
Krishna
Bulkhead -> Semaphore-based Bulkhead
ThreadPoolBulkhead -> Threadpool-based Bulkhead
The Semaphore-based Bulkhead runs your code in the current Thread and controls the number of concurrent threads by a Semaphore.
The Threadpool-based Bulkhead runs your code in a Thread from a Thread Pool and controls the number of concurrent threads by a bounded queue and thread pool.
Thank you RobWin for the explanation, it was very helpful. I tried ThreadPool with @BulkHead annotation and I get the following error. is ThreadPoolBulkHead is supported in the current release?
My Code:
@Bulkhead(name = "", fallbackMethod = "bulkHeadFallback", type = Bulkhead.Type.THREADPOOL) // if the name is empty, it takes default config values
public ResponseEntity<BarcodeResponse> getBarcodeResponse(AnalyseIdentifier analyseIdentifier,
{
// call to some remote servcie
}
Error:
ThreadPool bulkhead is only applicable for completable futures
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
at jp.co.toshibatec.ngp.conductor.aspect.LoggingAccess.time(LoggingAccess.java:160)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at jp.co.toshibatec.ngp.conductor.plugins.item_bundle.web.ItemController$$EnhancerBySpringCGLIB$$b74a21ee.itemOperation(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
Your response would be highly appreciated
Yes that's correct. The ThreadPoolBulkhead runs tasks in a thread pool and returns a CompletionStage (CompletableFuture). The method鈥檚 return type must be CompletableFuture<BarcodeResponse> instead of BarcodeResponse, a requirement for any asynchronous service. Your code must do return CompletableFuture.completedFuture(response);
It can't return a ResponseEntity<BarcodeResponse>.
It's comparable to Spring's @Async annotation. Please see: https://spring.io/guides/gs/async-method/
Thanks RobWin. You are a champ
Most helpful comment
Yes that's correct. The ThreadPoolBulkhead runs tasks in a thread pool and returns a CompletionStage (CompletableFuture). The method鈥檚 return type must be
CompletableFuture<BarcodeResponse>instead ofBarcodeResponse, a requirement for any asynchronous service. Your code must doreturn CompletableFuture.completedFuture(response);It can't return a
ResponseEntity<BarcodeResponse>.It's comparable to Spring's
@Asyncannotation. Please see: https://spring.io/guides/gs/async-method/