|
18 | 18 |
|
19 | 19 | import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider; |
20 | 20 | import com.netflix.discovery.shared.resolver.DefaultEndpoint; |
| 21 | +import com.netflix.discovery.shared.transport.EurekaHttpClient; |
21 | 22 | import org.junit.jupiter.api.BeforeEach; |
| 23 | +import org.junit.jupiter.api.Test; |
| 24 | +import reactor.netty.http.client.HttpClient; |
| 25 | +import reactor.netty.resources.LoopResources; |
22 | 26 |
|
23 | 27 | import org.springframework.beans.factory.annotation.Autowired; |
24 | 28 | import org.springframework.beans.factory.annotation.Value; |
25 | 29 | import org.springframework.boot.test.context.SpringBootTest; |
26 | 30 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
27 | 31 | import org.springframework.cloud.commons.util.InetUtils; |
28 | 32 | import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; |
| 33 | +import org.springframework.http.HttpStatus; |
| 34 | +import org.springframework.http.client.reactive.ReactorClientHttpConnector; |
29 | 35 | import org.springframework.test.annotation.DirtiesContext; |
30 | 36 | import org.springframework.web.reactive.function.client.WebClient; |
31 | 37 |
|
| 38 | +import static org.assertj.core.api.Assertions.assertThat; |
| 39 | + |
32 | 40 | /** |
33 | 41 | * @author Daniel Lavoie |
34 | 42 | */ |
@@ -65,4 +73,29 @@ void setup() { |
65 | 73 | info = new EurekaConfigBasedInstanceInfoProvider(config).get(); |
66 | 74 | } |
67 | 75 |
|
| 76 | + @Test |
| 77 | + void cancelSucceedsAfterSharedReactorResourcesDisposed() { |
| 78 | + // Simulate the LoopResources shared between the reactive web server and a |
| 79 | + // WebClient (as Spring Boot's ReactorResourceFactory provides by default) |
| 80 | + LoopResources sharedResources = LoopResources.create("simulated-server"); |
| 81 | + WebClient.Builder sharedBuilder = WebClient.builder() |
| 82 | + .clientConnector(new ReactorClientHttpConnector(HttpClient.create().runOn(sharedResources))); |
| 83 | + |
| 84 | + WebClientTransportClientFactory factory = new WebClientTransportClientFactory(() -> sharedBuilder); |
| 85 | + EurekaHttpClient client = factory.newClient(new DefaultEndpoint(serviceUrl)); |
| 86 | + |
| 87 | + // Simulate the reactive web server shutting down (terminates the shared event |
| 88 | + // loop) |
| 89 | + sharedResources.dispose(); |
| 90 | + |
| 91 | + // cancel() must succeed because the factory uses its own dedicated Reactor Netty |
| 92 | + // resources that are independent of the shared (now disposed) web server |
| 93 | + // resources. |
| 94 | + // Without the fix this would throw RejectedExecutionException: event executor |
| 95 | + // terminated |
| 96 | + assertThat(client.cancel("test", "test").getStatusCode()).isEqualTo(HttpStatus.OK.value()); |
| 97 | + |
| 98 | + factory.shutdown(); |
| 99 | + } |
| 100 | + |
68 | 101 | } |
0 commit comments