Skip to content

Commit 38b8eca

Browse files
committed
Merge branch '4.2.x' into 4.3.x
2 parents e362e73 + 12acc97 commit 38b8eca

File tree

3 files changed

+210
-13
lines changed

3 files changed

+210
-13
lines changed

pom.xml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,64 @@
2525
</developerConnection>
2626
<tag>HEAD</tag>
2727
</scm>
28+
<licenses>
29+
<license>
30+
<name>Apache License, Version 2.0</name>
31+
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
32+
</license>
33+
</licenses>
34+
<developers>
35+
<developer>
36+
<id>dsyer</id>
37+
<name>Dave Syer</name>
38+
<email>david.syer at broadcom.com</email>
39+
<organization>Broadcom, Inc.</organization>
40+
<organizationUrl>https://www.spring.io</organizationUrl>
41+
<roles>
42+
<role>lead</role>
43+
</roles>
44+
</developer>
45+
<developer>
46+
<id>sgibb</id>
47+
<name>Spencer Gibb</name>
48+
<email>spencer.gibb at broadcom.com</email>
49+
<organization>Broadcom, Inc.</organization>
50+
<organizationUrl>https://www.spring.io</organizationUrl>
51+
<roles>
52+
<role>lead</role>
53+
</roles>
54+
</developer>
55+
<developer>
56+
<id>mgrzejszczak</id>
57+
<name>Marcin Grzejszczak</name>
58+
<email>>marcin.grzejszczak at broadcom.com</email>
59+
<organization>Broadcom, Inc.</organization>
60+
<organizationUrl>https://www.spring.io</organizationUrl>
61+
<roles>
62+
<role>developer</role>
63+
</roles>
64+
</developer>
65+
<developer>
66+
<id>rbaxter</id>
67+
<name>Ryan Baxter</name>
68+
<email>ryan.baxter at broadcom.com</email>
69+
<organization>Broadcom, Inc.</organization>
70+
<organizationUrl>https://www.spring.io</organizationUrl>
71+
<roles>
72+
<role>developer</role>
73+
</roles>
74+
</developer>
75+
<developer>
76+
<id>omaciaszeksharma</id>
77+
<name>Olga Maciaszek-Sharma</name>
78+
<email>olga.maciaszek-sharma at broadcom.com</email>
79+
<organization>Broadcom, Inc.</organization>
80+
<organizationUrl>https://www.spring.io</organizationUrl>
81+
<roles>
82+
<role>developer</role>
83+
</roles>
84+
</developer>
85+
</developers>
2886
<properties>
2987
<bintray.package>commons</bintray.package>
3088
<evictor.version>1.0.0</evictor.version>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.loadbalancer.cache;
18+
19+
import java.time.Duration;
20+
import java.util.List;
21+
import java.util.concurrent.atomic.AtomicInteger;
22+
23+
import org.junit.jupiter.api.AfterEach;
24+
import org.junit.jupiter.api.Test;
25+
import reactor.core.publisher.Flux;
26+
27+
import org.springframework.cloud.client.DefaultServiceInstance;
28+
import org.springframework.cloud.client.ServiceInstance;
29+
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
30+
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME;
34+
35+
/**
36+
* @author wind57
37+
*/
38+
class CaffeineBasedLoadBalancerCacheManagerTests {
39+
40+
private static final String SERVICE_ID = "mock-service-id";
41+
42+
private final CaffeineBasedLoadBalancerCacheManager caffeineBasedLoadBalancerCacheManager = new CaffeineBasedLoadBalancerCacheManager(
43+
SERVICE_INSTANCE_CACHE_NAME, getLoadBalancerCacheProperties());
44+
45+
/**
46+
* <pre>
47+
* - cache has a TTL of 3 seconds
48+
* - we issue a GET and its not in the cache (counter is incremented)
49+
* - we issue a second GET and it's in the cache this time (counter stays the same)
50+
* </pre>
51+
*/
52+
@Test
53+
void testSecondGetRetrievedFromCache() {
54+
55+
ServiceInstanceListSupplier serviceInstanceListSupplier = new StubServiceInstanceListSupplier();
56+
57+
CachingServiceInstanceListSupplier cachingServiceInstanceListSupplier = new CachingServiceInstanceListSupplier(
58+
serviceInstanceListSupplier, caffeineBasedLoadBalancerCacheManager);
59+
60+
List<ServiceInstance> serviceInstances = cachingServiceInstanceListSupplier.get().blockFirst();
61+
assertThat(serviceInstances).hasSize(1);
62+
// the first time we retrieve, the entry is not in the cache
63+
assertThat(StubServiceInstanceListSupplier.counter.get()).isEqualTo(1);
64+
65+
List<ServiceInstance> serviceInstancesInTheCache = cachingServiceInstanceListSupplier.get().blockFirst();
66+
assertThat(serviceInstancesInTheCache).hasSize(1);
67+
// the second time we retrieve, the entry is in the cache
68+
// the underlying list supplier is not called
69+
assertThat(StubServiceInstanceListSupplier.counter.get()).isEqualTo(1);
70+
71+
}
72+
73+
/**
74+
* <pre>
75+
* - cache has a TTL of 3 seconds
76+
* - we issue a GET and its not in the cache (counter is incremented)
77+
* - we issue a second GET and it's in the cache this time (counter stays the same)
78+
* - we wait for 4 seconds (entry in the cache is evicted)
79+
* - we issue one more GET and this time its not in the cache (counter is incremented to 2)
80+
* </pre>
81+
*/
82+
@Test
83+
void testSecondGetNoInTheCache() throws Exception {
84+
85+
ServiceInstanceListSupplier serviceInstanceListSupplier = new StubServiceInstanceListSupplier();
86+
87+
CachingServiceInstanceListSupplier cachingServiceInstanceListSupplier = new CachingServiceInstanceListSupplier(
88+
serviceInstanceListSupplier, caffeineBasedLoadBalancerCacheManager);
89+
90+
List<ServiceInstance> serviceInstances = cachingServiceInstanceListSupplier.get().blockFirst();
91+
assertThat(serviceInstances).hasSize(1);
92+
// the first time we retrieve, the entry is not in the cache
93+
assertThat(StubServiceInstanceListSupplier.counter.get()).isEqualTo(1);
94+
95+
List<ServiceInstance> serviceInstancesInTheCache = cachingServiceInstanceListSupplier.get().blockFirst();
96+
assertThat(serviceInstancesInTheCache).hasSize(1);
97+
// the second time we retrieve, the entry is in the cache,
98+
// the underlying list supplier is not called
99+
assertThat(StubServiceInstanceListSupplier.counter.get()).isEqualTo(1);
100+
101+
Thread.sleep(4_000);
102+
103+
List<ServiceInstance> serviceInstancesNotInTheCache = cachingServiceInstanceListSupplier.get().blockFirst();
104+
assertThat(serviceInstancesNotInTheCache).hasSize(1);
105+
// the third time we retrieve, the entry is not in the cache,
106+
// the underlying list supplier is called
107+
assertThat(StubServiceInstanceListSupplier.counter.get()).isEqualTo(2);
108+
109+
}
110+
111+
@AfterEach
112+
void afterEach() {
113+
StubServiceInstanceListSupplier.counter.set(0);
114+
}
115+
116+
private static LoadBalancerCacheProperties getLoadBalancerCacheProperties() {
117+
LoadBalancerCacheProperties properties = new LoadBalancerCacheProperties();
118+
properties.setCapacity(100);
119+
properties.setTtl(Duration.ofSeconds(3));
120+
return properties;
121+
}
122+
123+
static class StubServiceInstanceListSupplier implements ServiceInstanceListSupplier {
124+
125+
static AtomicInteger counter = new AtomicInteger(0);
126+
127+
@Override
128+
public String getServiceId() {
129+
return SERVICE_ID;
130+
}
131+
132+
@Override
133+
public Flux<List<ServiceInstance>> get() {
134+
List<ServiceInstance> serviceInstances = List
135+
.of(new DefaultServiceInstance(SERVICE_ID, SERVICE_ID, "localhost", 80, false));
136+
return Flux.just(serviceInstances).doOnNext(x -> {
137+
counter.incrementAndGet();
138+
});
139+
}
140+
141+
}
142+
143+
}

spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/CachingServiceInstanceListSupplierTests.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,14 @@
4848
*
4949
* @author Olga Maciaszek-Sharma
5050
*/
51-
@SpringBootTest(classes = CachingServiceInstanceListSupplierTests.TestConfig.class)
51+
@SpringBootTest(classes = CachingServiceInstanceListSupplierTests.TestConfig.class,
52+
properties = { "loadbalancer.client.name=test" })
5253
class CachingServiceInstanceListSupplierTests {
5354

54-
public static final String SERVICE_ID = "test";
55-
56-
static {
57-
System.setProperty("loadbalancer.client.name", SERVICE_ID);
58-
}
55+
private static final String SERVICE_ID = "test";
5956

6057
@Autowired
61-
BlockingLoadBalancerClient blockingLoadBalancerClient;
58+
private BlockingLoadBalancerClient blockingLoadBalancerClient;
6259

6360
private static DefaultServiceInstance instance(String host, boolean secure) {
6461
return new DefaultServiceInstance(SERVICE_ID, SERVICE_ID, host, 80, secure);
@@ -74,10 +71,10 @@ void shouldNotHangOnCachingWhenDelegateReturnsInfiniteStream() {
7471

7572
@Configuration(proxyBeanMethods = false)
7673
@Import(LoadBalancerCacheAutoConfiguration.class)
77-
protected static class TestConfig {
74+
static class TestConfig {
7875

7976
@Bean
80-
public ReactiveDiscoveryClient reactiveDiscoveryClient() {
77+
ReactiveDiscoveryClient reactiveDiscoveryClient() {
8178
return new ReactiveDiscoveryClient() {
8279
@Override
8380
public String description() {
@@ -107,18 +104,17 @@ LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsPropertie
107104
}
108105

109106
@Bean
110-
BlockingLoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory,
111-
LoadBalancerProperties properties) {
107+
BlockingLoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {
112108
return new BlockingLoadBalancerClient(loadBalancerClientFactory);
113109
}
114110

115111
@Bean
116-
public LoadBalancerClientsProperties loadBalancerClientsProperties() {
112+
LoadBalancerClientsProperties loadBalancerClientsProperties() {
117113
return new LoadBalancerClientsProperties();
118114
}
119115

120116
@Bean
121-
public WebClient.Builder webClientBuilder() {
117+
WebClient.Builder webClientBuilder() {
122118
return WebClient.builder();
123119
}
124120

0 commit comments

Comments
 (0)