11package org .hypertrace .circuitbreaker .grpcutils .resilience ;
22
33import com .google .common .annotations .VisibleForTesting ;
4- import com .google .inject .Singleton ;
5- import com .typesafe .config .Config ;
64import io .github .resilience4j .circuitbreaker .CircuitBreaker ;
75import io .github .resilience4j .circuitbreaker .CircuitBreakerConfig ;
86import io .github .resilience4j .circuitbreaker .CircuitBreakerRegistry ;
2018import java .util .Map ;
2119import java .util .concurrent .TimeUnit ;
2220import lombok .extern .slf4j .Slf4j ;
23- import org .hypertrace .circuitbreaker .grpcutils .CircuitBreakerConfigProvider ;
21+ import org .hypertrace .circuitbreaker .grpcutils .CircuitBreakerConfiguration ;
2422import org .hypertrace .circuitbreaker .grpcutils .CircuitBreakerInterceptor ;
23+ import org .hypertrace .core .grpcutils .context .RequestContext ;
2524
2625@ Slf4j
27- @ Singleton
2826public class ResilienceCircuitBreakerInterceptor extends CircuitBreakerInterceptor {
2927
30- public static final CallOptions .Key <String > CIRCUIT_BREAKER_KEY =
31- CallOptions .Key .createWithDefault ("circuitBreakerKey" , "default" );
3228 private final CircuitBreakerRegistry resilicenceCircuitBreakerRegistry ;
33- private final CircuitBreakerConfigProvider circuitBreakerConfigProvider ;
34- private final Map <String , CircuitBreakerConfig > resilienceCircuitBreakerConfig ;
29+ private final Map <String , CircuitBreakerConfig > resilienceCircuitBreakerConfigMap ;
3530 private final ResilienceCircuitBreakerProvider resilienceCircuitBreakerProvider ;
31+ private final CircuitBreakerConfiguration <?> circuitBreakerConfiguration ;
3632 private final Clock clock ;
3733
38- public ResilienceCircuitBreakerInterceptor (Config config , Clock clock ) {
39- this .circuitBreakerConfigProvider = new CircuitBreakerConfigProvider (config );
40- this .resilienceCircuitBreakerConfig =
34+ public ResilienceCircuitBreakerInterceptor (
35+ CircuitBreakerConfiguration <?> circuitBreakerConfiguration , Clock clock ) {
36+ this .circuitBreakerConfiguration = circuitBreakerConfiguration ;
37+ this .clock = clock ;
38+ this .resilienceCircuitBreakerConfigMap =
4139 ResilienceCircuitBreakerConfigParser .getCircuitBreakerConfigs (
42- circuitBreakerConfigProvider . getConfigMap ());
40+ circuitBreakerConfiguration . getCircuitBreakerThresholdsMap ());
4341 this .resilicenceCircuitBreakerRegistry =
44- new ResilienceCircuitBreakerRegistryProvider (resilienceCircuitBreakerConfig )
42+ new ResilienceCircuitBreakerRegistryProvider (resilienceCircuitBreakerConfigMap )
4543 .getCircuitBreakerRegistry ();
4644 this .resilienceCircuitBreakerProvider =
4745 new ResilienceCircuitBreakerProvider (
48- resilicenceCircuitBreakerRegistry , resilienceCircuitBreakerConfig );
49- this .clock = clock ;
46+ resilicenceCircuitBreakerRegistry , resilienceCircuitBreakerConfigMap );
5047 }
5148
5249 @ VisibleForTesting
5350 public ResilienceCircuitBreakerInterceptor (
54- Config config ,
5551 Clock clock ,
5652 CircuitBreakerRegistry resilicenceCircuitBreakerRegistry ,
57- ResilienceCircuitBreakerProvider resilienceCircuitBreakerProvider ) {
58- this .circuitBreakerConfigProvider = new CircuitBreakerConfigProvider (config );
59- this .resilienceCircuitBreakerConfig =
53+ ResilienceCircuitBreakerProvider resilienceCircuitBreakerProvider ,
54+ CircuitBreakerConfiguration <?> circuitBreakerConfiguration ) {
55+ this .circuitBreakerConfiguration = circuitBreakerConfiguration ;
56+ this .resilienceCircuitBreakerConfigMap =
6057 ResilienceCircuitBreakerConfigParser .getCircuitBreakerConfigs (
61- circuitBreakerConfigProvider . getConfigMap ());
58+ circuitBreakerConfiguration . getCircuitBreakerThresholdsMap ());
6259 this .resilicenceCircuitBreakerRegistry = resilicenceCircuitBreakerRegistry ;
6360 this .resilienceCircuitBreakerProvider = resilienceCircuitBreakerProvider ;
6461 this .clock = clock ;
6562 }
6663
6764 @ Override
6865 protected boolean isCircuitBreakerEnabled () {
69- return circuitBreakerConfigProvider . isCircuitBreakerEnabled ();
66+ return circuitBreakerConfiguration . isEnabled ();
7067 }
7168
7269 @ Override
7370 protected <ReqT , RespT > ClientCall <ReqT , RespT > createInterceptedCall (
7471 MethodDescriptor <ReqT , RespT > method , CallOptions callOptions , Channel next ) {
75- // Get circuit breaker key from CallOptions
76- String circuitBreakerKey = callOptions .getOption (CIRCUIT_BREAKER_KEY );
77- CircuitBreaker circuitBreaker =
78- resilienceCircuitBreakerProvider .getCircuitBreaker (circuitBreakerKey );
7972 return new ForwardingClientCall .SimpleForwardingClientCall <>(
8073 next .newCall (method , callOptions )) {
74+ CircuitBreaker circuitBreaker ;
75+ String circuitBreakerKey ;
76+
8177 @ Override
8278 public void start (Listener <RespT > responseListener , Metadata headers ) {
8379 Instant startTime = clock .instant ();
@@ -87,8 +83,22 @@ public void start(Listener<RespT> responseListener, Metadata headers) {
8783 super .start (wrappedListener , headers );
8884 }
8985
86+ @ SuppressWarnings ("unchecked" )
9087 @ Override
9188 public void sendMessage (ReqT message ) {
89+ CircuitBreakerConfiguration <ReqT > config =
90+ (CircuitBreakerConfiguration <ReqT >) circuitBreakerConfiguration ;
91+ if (config .getRequestClass () == null
92+ || (!message .getClass ().equals (config .getRequestClass ()))) {
93+ log .warn ("Invalid config for message type: {}" , message .getClass ());
94+ super .sendMessage (message );
95+ }
96+ if (config .getKeyFunction () != null ) {
97+ circuitBreakerKey = config .getKeyFunction ().apply (RequestContext .CURRENT .get (), message );
98+ } else {
99+ circuitBreakerKey = "default" ;
100+ }
101+ circuitBreaker = resilienceCircuitBreakerProvider .getCircuitBreaker (circuitBreakerKey );
92102 if (!circuitBreaker .tryAcquirePermission ()) {
93103 logCircuitBreakerRejection (circuitBreakerKey , circuitBreaker );
94104 String rejectionReason =
0 commit comments