Skip to content

Commit

Permalink
#2249 | Support concurrent access to requestInterceptor.
Browse files Browse the repository at this point in the history
  • Loading branch information
youssef3wi committed Feb 17, 2024
1 parent 8f189cc commit c1aa81e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
13 changes: 7 additions & 6 deletions core/src/main/java/feign/BaseBuilder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 The Feign Authors
* Copyright 2012-2024 The Feign Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -13,29 +13,30 @@
*/
package feign;

import static feign.ExceptionPropagationPolicy.NONE;
import feign.Feign.ResponseMappingDecoder;
import feign.Logger.NoOpLogger;
import feign.Request.Options;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.querymap.FieldQueryMapEncoder;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

import static feign.ExceptionPropagationPolicy.NONE;

public abstract class BaseBuilder<B extends BaseBuilder<B, T>, T> implements Cloneable {

private final B thisB;

protected final List<RequestInterceptor> requestInterceptors =
new ArrayList<>();
protected final List<ResponseInterceptor> responseInterceptors = new ArrayList<>();
protected final List<RequestInterceptor> requestInterceptors = new CopyOnWriteArrayList<>();
protected final List<ResponseInterceptor> responseInterceptors = new CopyOnWriteArrayList<>();
protected Logger.Level logLevel = Logger.Level.NONE;
protected Contract contract = new Contract.Default();
protected Retryer retryer = new Retryer.Default();
Expand Down
37 changes: 36 additions & 1 deletion core/src/test/java/feign/BaseBuilderTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 The Feign Authors
* Copyright 2012-2024 The Feign Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -18,6 +18,10 @@
import static org.mockito.Mockito.RETURNS_MOCKS;
import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

Expand Down Expand Up @@ -60,4 +64,35 @@ void checkEnrichTouchesAllBuilderFields()
}).responseInterceptor((ic, c) -> c.next(ic)), 12);
}

@Test
void concurrentAccessToInterceptors() throws IllegalAccessException, InterruptedException {
// Given
int numberOfIterations = 5000;
int numberOfThreads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
AsyncFeign.AsyncBuilder<?> builder = AsyncFeign.builder();

// When
for (int idx = 0; idx < numberOfIterations; idx++) { // to simulate increase iterations
service.submit(() -> {
try {
setupBuilder(builder);
} catch (InterruptedException ignored) {}

latch.countDown();
});
}

// Then
latch.await();
test(builder, 14);
}

private synchronized void setupBuilder(BaseBuilder<?, ?> builder) throws InterruptedException {
builder.requestInterceptor(template -> {});
wait(10);
builder.responseInterceptor((ic, c) -> c.next(ic));
}

}

0 comments on commit c1aa81e

Please sign in to comment.