Skip to content

Commit a60876b

Browse files
committed
poc uaa throttling
1 parent 0960613 commit a60876b

File tree

5 files changed

+349
-16
lines changed

5 files changed

+349
-16
lines changed

cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/util/RequestLogger.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class RequestLogger {
3434
private long requestSentTime;
3535

3636
public void request(HttpClientRequest request) {
37-
request(String.format("%-6s {}", request.method()), request.uri());
37+
request(String.format("%-6s {}", request.method()), request.resourceUrl());
3838
}
3939

4040
public void response(HttpClientResponse response) {

integration-test/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@
7070
<version>${project.version}</version>
7171
<scope>test</scope>
7272
</dependency>
73+
<dependency>
74+
<groupId>io.github.resilience4j</groupId>
75+
<artifactId>resilience4j-ratelimiter</artifactId>
76+
<version>1.7.0</version>
77+
</dependency>
78+
<dependency>
79+
<groupId>io.github.resilience4j</groupId>
80+
<artifactId>resilience4j-reactor</artifactId>
81+
<version>1.7.0</version>
82+
</dependency>
7383
<dependency>
7484
<groupId>org.cloudfoundry</groupId>
7585
<artifactId>cloudfoundry-util</artifactId>

integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,19 @@ NetworkingClient adminNetworkingClient(
192192

193193
@Bean
194194
@Qualifier("admin")
195-
ReactorUaaClient adminUaaClient(
195+
UaaClient adminUaaClient(
196196
ConnectionContext connectionContext,
197197
@Value("${test.admin.clientId}") String clientId,
198198
@Value("${test.admin.clientSecret}") String clientSecret) {
199-
return ReactorUaaClient.builder()
200-
.connectionContext(connectionContext)
201-
.tokenProvider(
202-
ClientCredentialsGrantTokenProvider.builder()
203-
.clientId(clientId)
204-
.clientSecret(clientSecret)
205-
.build())
206-
.build();
199+
return new ThrottlingUaaClient(
200+
ReactorUaaClient.builder()
201+
.connectionContext(connectionContext)
202+
.tokenProvider(
203+
ClientCredentialsGrantTokenProvider.builder()
204+
.clientId(clientId)
205+
.clientSecret(clientSecret)
206+
.build())
207+
.build());
207208
}
208209

209210
@Bean(initMethod = "block")
@@ -643,11 +644,12 @@ PasswordGrantTokenProvider tokenProvider(
643644
}
644645

645646
@Bean
646-
ReactorUaaClient uaaClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
647-
return ReactorUaaClient.builder()
648-
.connectionContext(connectionContext)
649-
.tokenProvider(tokenProvider)
650-
.build();
647+
UaaClient uaaClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
648+
return new ThrottlingUaaClient(
649+
ReactorUaaClient.builder()
650+
.connectionContext(connectionContext)
651+
.tokenProvider(tokenProvider)
652+
.build());
651653
}
652654

653655
@Bean(initMethod = "block")
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
package org.cloudfoundry;
2+
3+
import io.github.resilience4j.ratelimiter.RateLimiter;
4+
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
5+
import io.github.resilience4j.reactor.ratelimiter.operator.RateLimiterOperator;
6+
import java.time.Duration;
7+
import org.cloudfoundry.uaa.UaaClient;
8+
import org.cloudfoundry.uaa.authorizations.Authorizations;
9+
import org.cloudfoundry.uaa.clients.Clients;
10+
import org.cloudfoundry.uaa.groups.AddMemberRequest;
11+
import org.cloudfoundry.uaa.groups.AddMemberResponse;
12+
import org.cloudfoundry.uaa.groups.CheckMembershipRequest;
13+
import org.cloudfoundry.uaa.groups.CheckMembershipResponse;
14+
import org.cloudfoundry.uaa.groups.CreateGroupRequest;
15+
import org.cloudfoundry.uaa.groups.CreateGroupResponse;
16+
import org.cloudfoundry.uaa.groups.DeleteGroupRequest;
17+
import org.cloudfoundry.uaa.groups.DeleteGroupResponse;
18+
import org.cloudfoundry.uaa.groups.GetGroupRequest;
19+
import org.cloudfoundry.uaa.groups.GetGroupResponse;
20+
import org.cloudfoundry.uaa.groups.Groups;
21+
import org.cloudfoundry.uaa.groups.ListExternalGroupMappingsRequest;
22+
import org.cloudfoundry.uaa.groups.ListExternalGroupMappingsResponse;
23+
import org.cloudfoundry.uaa.groups.ListGroupsRequest;
24+
import org.cloudfoundry.uaa.groups.ListGroupsResponse;
25+
import org.cloudfoundry.uaa.groups.ListMembersRequest;
26+
import org.cloudfoundry.uaa.groups.ListMembersResponse;
27+
import org.cloudfoundry.uaa.groups.MapExternalGroupRequest;
28+
import org.cloudfoundry.uaa.groups.MapExternalGroupResponse;
29+
import org.cloudfoundry.uaa.groups.RemoveMemberRequest;
30+
import org.cloudfoundry.uaa.groups.RemoveMemberResponse;
31+
import org.cloudfoundry.uaa.groups.UnmapExternalGroupByGroupDisplayNameRequest;
32+
import org.cloudfoundry.uaa.groups.UnmapExternalGroupByGroupDisplayNameResponse;
33+
import org.cloudfoundry.uaa.groups.UnmapExternalGroupByGroupIdRequest;
34+
import org.cloudfoundry.uaa.groups.UnmapExternalGroupByGroupIdResponse;
35+
import org.cloudfoundry.uaa.groups.UpdateGroupRequest;
36+
import org.cloudfoundry.uaa.groups.UpdateGroupResponse;
37+
import org.cloudfoundry.uaa.identityproviders.IdentityProviders;
38+
import org.cloudfoundry.uaa.identityzones.IdentityZones;
39+
import org.cloudfoundry.uaa.serverinformation.ServerInformation;
40+
import org.cloudfoundry.uaa.tokens.Tokens;
41+
import org.cloudfoundry.uaa.users.ChangeUserPasswordRequest;
42+
import org.cloudfoundry.uaa.users.ChangeUserPasswordResponse;
43+
import org.cloudfoundry.uaa.users.CreateUserRequest;
44+
import org.cloudfoundry.uaa.users.CreateUserResponse;
45+
import org.cloudfoundry.uaa.users.DeleteUserRequest;
46+
import org.cloudfoundry.uaa.users.DeleteUserResponse;
47+
import org.cloudfoundry.uaa.users.ExpirePasswordRequest;
48+
import org.cloudfoundry.uaa.users.ExpirePasswordResponse;
49+
import org.cloudfoundry.uaa.users.GetUserVerificationLinkRequest;
50+
import org.cloudfoundry.uaa.users.GetUserVerificationLinkResponse;
51+
import org.cloudfoundry.uaa.users.InviteUsersRequest;
52+
import org.cloudfoundry.uaa.users.InviteUsersResponse;
53+
import org.cloudfoundry.uaa.users.ListUsersRequest;
54+
import org.cloudfoundry.uaa.users.ListUsersResponse;
55+
import org.cloudfoundry.uaa.users.LookupUserIdsRequest;
56+
import org.cloudfoundry.uaa.users.LookupUserIdsResponse;
57+
import org.cloudfoundry.uaa.users.UpdateUserRequest;
58+
import org.cloudfoundry.uaa.users.UpdateUserResponse;
59+
import org.cloudfoundry.uaa.users.UserInfoRequest;
60+
import org.cloudfoundry.uaa.users.UserInfoResponse;
61+
import org.cloudfoundry.uaa.users.Users;
62+
import org.cloudfoundry.uaa.users.VerifyUserRequest;
63+
import org.cloudfoundry.uaa.users.VerifyUserResponse;
64+
import reactor.core.publisher.Mono;
65+
66+
public class ThrottlingUaaClient implements UaaClient {
67+
68+
private final UaaClient delegate;
69+
70+
private final RateLimiter rateLimiter;
71+
private final ThrottledUsers users;
72+
private Groups groups;
73+
74+
public ThrottlingUaaClient(UaaClient delegate) {
75+
this.delegate = delegate;
76+
RateLimiterConfig config =
77+
RateLimiterConfig.custom()
78+
.limitForPeriod(5)
79+
.limitRefreshPeriod(Duration.ofSeconds(1))
80+
.build();
81+
this.rateLimiter = RateLimiter.of("uaa", config);
82+
this.users = new ThrottledUsers();
83+
this.groups = new ThrottledGroups();
84+
}
85+
86+
@Override
87+
public Authorizations authorizations() {
88+
return this.delegate.authorizations();
89+
}
90+
91+
@Override
92+
public Clients clients() {
93+
return this.delegate.clients();
94+
}
95+
96+
@Override
97+
public Mono<String> getUsername() {
98+
return this.delegate.getUsername();
99+
}
100+
101+
@Override
102+
public IdentityProviders identityProviders() {
103+
return this.delegate.identityProviders();
104+
}
105+
106+
@Override
107+
public IdentityZones identityZones() {
108+
return this.delegate.identityZones();
109+
}
110+
111+
@Override
112+
public ServerInformation serverInformation() {
113+
return this.delegate.serverInformation();
114+
}
115+
116+
@Override
117+
public Tokens tokens() {
118+
return this.delegate.tokens();
119+
}
120+
121+
@Override
122+
public Users users() {
123+
return users;
124+
}
125+
126+
@Override
127+
public Groups groups() {
128+
return groups;
129+
}
130+
131+
public class ThrottledUsers implements Users {
132+
133+
private final Users usersDelegate;
134+
135+
public ThrottledUsers() {
136+
this.usersDelegate = delegate.users();
137+
}
138+
139+
@Override
140+
public Mono<ChangeUserPasswordResponse> changePassword(ChangeUserPasswordRequest request) {
141+
return this.usersDelegate
142+
.changePassword(request)
143+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
144+
}
145+
146+
@Override
147+
public Mono<CreateUserResponse> create(CreateUserRequest request) {
148+
return this.usersDelegate
149+
.create(request)
150+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
151+
}
152+
153+
@Override
154+
public Mono<DeleteUserResponse> delete(DeleteUserRequest request) {
155+
return this.usersDelegate
156+
.delete(request)
157+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
158+
}
159+
160+
@Override
161+
public Mono<ExpirePasswordResponse> expirePassword(ExpirePasswordRequest request) {
162+
return this.usersDelegate
163+
.expirePassword(request)
164+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
165+
}
166+
167+
@Override
168+
public Mono<GetUserVerificationLinkResponse> getVerificationLink(
169+
GetUserVerificationLinkRequest request) {
170+
return this.usersDelegate
171+
.getVerificationLink(request)
172+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
173+
}
174+
175+
@Override
176+
public Mono<InviteUsersResponse> invite(InviteUsersRequest request) {
177+
return this.usersDelegate
178+
.invite(request)
179+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
180+
}
181+
182+
@Override
183+
public Mono<ListUsersResponse> list(ListUsersRequest request) {
184+
return this.usersDelegate
185+
.list(request)
186+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
187+
}
188+
189+
@Override
190+
public Mono<LookupUserIdsResponse> lookup(LookupUserIdsRequest request) {
191+
return this.usersDelegate
192+
.lookup(request)
193+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
194+
}
195+
196+
@Override
197+
public Mono<UpdateUserResponse> update(UpdateUserRequest request) {
198+
return this.usersDelegate
199+
.update(request)
200+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
201+
}
202+
203+
@Override
204+
public Mono<UserInfoResponse> userInfo(UserInfoRequest request) {
205+
return this.usersDelegate
206+
.userInfo(request)
207+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
208+
}
209+
210+
@Override
211+
public Mono<VerifyUserResponse> verify(VerifyUserRequest request) {
212+
return this.usersDelegate
213+
.verify(request)
214+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
215+
}
216+
}
217+
218+
public class ThrottledGroups implements Groups {
219+
220+
public final Groups groupsDelegate;
221+
222+
public ThrottledGroups() {
223+
this.groupsDelegate = delegate.groups();
224+
}
225+
226+
@Override
227+
public Mono<AddMemberResponse> addMember(AddMemberRequest request) {
228+
return this.groupsDelegate
229+
.addMember(request)
230+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
231+
}
232+
233+
@Override
234+
public Mono<CheckMembershipResponse> checkMembership(CheckMembershipRequest request) {
235+
return this.groupsDelegate
236+
.checkMembership(request)
237+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
238+
}
239+
240+
@Override
241+
public Mono<CreateGroupResponse> create(CreateGroupRequest request) {
242+
return this.groupsDelegate
243+
.create(request)
244+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
245+
}
246+
247+
@Override
248+
public Mono<DeleteGroupResponse> delete(DeleteGroupRequest request) {
249+
return this.groupsDelegate
250+
.delete(request)
251+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
252+
}
253+
254+
@Override
255+
public Mono<GetGroupResponse> get(GetGroupRequest request) {
256+
return this.groupsDelegate
257+
.get(request)
258+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
259+
}
260+
261+
@Override
262+
public Mono<ListGroupsResponse> list(ListGroupsRequest request) {
263+
return this.groupsDelegate
264+
.list(request)
265+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
266+
}
267+
268+
@Override
269+
public Mono<ListExternalGroupMappingsResponse> listExternalGroupMappings(
270+
ListExternalGroupMappingsRequest request) {
271+
return this.groupsDelegate
272+
.listExternalGroupMappings(request)
273+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
274+
}
275+
276+
@Override
277+
public Mono<ListMembersResponse> listMembers(ListMembersRequest request) {
278+
return this.groupsDelegate
279+
.listMembers(request)
280+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
281+
}
282+
283+
@Override
284+
public Mono<MapExternalGroupResponse> mapExternalGroup(MapExternalGroupRequest request) {
285+
return this.groupsDelegate
286+
.mapExternalGroup(request)
287+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
288+
}
289+
290+
@Override
291+
public Mono<RemoveMemberResponse> removeMember(RemoveMemberRequest request) {
292+
return this.groupsDelegate
293+
.removeMember(request)
294+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
295+
}
296+
297+
@Override
298+
public Mono<UnmapExternalGroupByGroupDisplayNameResponse>
299+
unmapExternalGroupByGroupDisplayName(
300+
UnmapExternalGroupByGroupDisplayNameRequest request) {
301+
return this.groupsDelegate
302+
.unmapExternalGroupByGroupDisplayName(request)
303+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
304+
}
305+
306+
@Override
307+
public Mono<UnmapExternalGroupByGroupIdResponse> unmapExternalGroupByGroupId(
308+
UnmapExternalGroupByGroupIdRequest request) {
309+
return this.groupsDelegate
310+
.unmapExternalGroupByGroupId(request)
311+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
312+
}
313+
314+
@Override
315+
public Mono<UpdateGroupResponse> update(UpdateGroupRequest request) {
316+
return this.groupsDelegate
317+
.update(request)
318+
.transformDeferred(RateLimiterOperator.of(rateLimiter));
319+
}
320+
}
321+
}

0 commit comments

Comments
 (0)