Skip to content

Instantly share code, notes, and snippets.

@wreulicke
Last active January 21, 2019 07:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wreulicke/06706e0a336a2e0d4f17f42b85342b4f to your computer and use it in GitHub Desktop.
Save wreulicke/06706e0a336a2e0d4f17f42b85342b4f to your computer and use it in GitHub Desktop.
concurrency-limitsをOkHttpClientのInterceptorとして実装してみた
public class OkHttpClientLimiterBuilder extends
AbstractPartitionedLimiter.Builder<OkHttpClientLimiterBuilder, OkhttpClientRequestContext> {
private boolean blockOnLimit = false;
public OkHttpClientLimiterBuilder partitionByHeaderName(String headerName) {
return partitionResolver(context -> context.request().header(headerName));
}
public OkHttpClientLimiterBuilder partitionByHost() {
return partitionResolver(context -> context.request().url().host());
}
public <T> OkHttpClientLimiterBuilder blockOnLimit(boolean blockOnLimit) {
this.blockOnLimit = blockOnLimit;
return this;
}
@Override
protected OkHttpClientLimiterBuilder self() {
return this;
}
public Limiter<OkhttpClientRequestContext> build() {
Limiter<OkhttpClientRequestContext> limiter = super.build();
if (blockOnLimit) {
limiter = BlockingLimiter.wrap(limiter);
}
return limiter;
}
}
public class OkHttpClientLimitInterceptor implements Interceptor {
private final Limiter<OkhttpClientRequestContext> contextLimiter;
public OkHttpClientLimitInterceptor(
Limiter<OkhttpClientRequestContext> contextLimiter) {
this.contextLimiter = contextLimiter;
}
@Override
public Response intercept(Chain chain) throws IOException {
OkhttpClientRequestContext context = new OkhttpClientRequestContext(chain.request());
Optional<Limiter.Listener> listerOpt = contextLimiter.acquire(context);
if (listerOpt.isPresent()) {
Limiter.Listener listener = listerOpt.get();
try {
Response response = chain.proceed(chain.request());
if (response.isSuccessful()) {
listener.onSuccess();
} else if (response.code() == 503) {
listener.onDropped();
} else {
listener.onIgnore();
}
return response;
} catch (IOException e) {
listener.onIgnore();
throw e;
}
} else {
return new Response.Builder()
.code(503)
.protocol(Protocol.HTTP_1_1) // dummy
.request(chain.request())
.message("Client concurrency limit reached")
.body(ResponseBody.create(null, new byte[0]))
.build();
}
}
}
public class OkhttpClientRequestContext {
private final Request request;
public OkhttpClientRequestContext(Request request) {
this.request = request;
}
Request request() {
return request;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment