Skip to content

Commit a00e957

Browse files
dchakrav-githubdiwakar
andauthored
Renaming call chain methods to spell out intent clearly (#246)
Co-authored-by: diwakar <diwakar@amazon.com>
1 parent 257eb75 commit a00e957

File tree

7 files changed

+75
-69
lines changed

7 files changed

+75
-69
lines changed

src/main/java/software/amazon/cloudformation/proxy/AmazonWebServicesClientProxy.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,19 +223,20 @@ class CallContext<ClientT, ModelT, CallbackT extends StdCallbackContext>
223223
}
224224

225225
@Override
226-
public <RequestT> Caller<RequestT, ClientT, ModelT, CallbackT> translate(Function<ModelT, RequestT> maker) {
226+
public <
227+
RequestT> Caller<RequestT, ClientT, ModelT, CallbackT> translateToServiceRequest(Function<ModelT, RequestT> maker) {
227228
return new Caller<RequestT, ClientT, ModelT, CallbackT>() {
228229

229230
@Override
230-
public Caller<RequestT, ClientT, ModelT, CallbackT> backoff(Delay delay) {
231+
public Caller<RequestT, ClientT, ModelT, CallbackT> backoffDelay(Delay delay) {
231232
CallContext.this.delay = delay;
232233
return this;
233234
}
234235

235236
@Override
236237
public <ResponseT>
237238
Stabilizer<RequestT, ResponseT, ClientT, ModelT, CallbackT>
238-
call(BiFunction<RequestT, ProxyClient<ClientT>, ResponseT> caller) {
239+
makeServiceCall(BiFunction<RequestT, ProxyClient<ClientT>, ResponseT> caller) {
239240
return new Stabilizer<RequestT, ResponseT, ClientT, ModelT, CallbackT>() {
240241

241242
private Callback<RequestT, ResponseT, ClientT, ModelT, CallbackT, Boolean> waitFor;

src/main/java/software/amazon/cloudformation/proxy/CallChain.java

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
*
3232
* <ol>
3333
* <li>{@link CallChain#initiate(String, ProxyClient, Object, StdCallbackContext)}
34-
* <li>{@link RequestMaker#translate(Function)}
35-
* <li>{@link Caller#call(BiFunction)}
34+
* <li>{@link RequestMaker#translateToServiceRequest(Function)}
35+
* <li>{@link Caller#makeServiceCall(BiFunction)}
3636
* <li>{@link Completed#done(Function)}
3737
* </ol>
3838
*
@@ -144,7 +144,7 @@ interface Initiator<ClientT, ModelT, CallbackT extends StdCallbackContext> {
144144
*/
145145
interface RequestMaker<ClientT, ModelT, CallbackT extends StdCallbackContext> {
146146
/**
147-
* use {@link #translate(Function)}
147+
* use {@link #translateToServiceRequest(Function)}
148148
*
149149
* Take a reference to the tranlater that take the resource model POJO as input
150150
* and provide a request object as needed to make the Service call.
@@ -155,7 +155,7 @@ interface RequestMaker<ClientT, ModelT, CallbackT extends StdCallbackContext> {
155155
*/
156156
@Deprecated
157157
default <RequestT> Caller<RequestT, ClientT, ModelT, CallbackT> request(Function<ModelT, RequestT> maker) {
158-
return translate(maker);
158+
return translateToServiceRequest(maker);
159159
}
160160

161161
/**
@@ -166,7 +166,7 @@ default <RequestT> Caller<RequestT, ClientT, ModelT, CallbackT> request(Function
166166
* @param <RequestT>, the web service request created
167167
* @return returns the next step, to actually call the service.
168168
*/
169-
<RequestT> Caller<RequestT, ClientT, ModelT, CallbackT> translate(Function<ModelT, RequestT> maker);
169+
<RequestT> Caller<RequestT, ClientT, ModelT, CallbackT> translateToServiceRequest(Function<ModelT, RequestT> maker);
170170
}
171171

172172
/**
@@ -181,16 +181,23 @@ default <RequestT> Caller<RequestT, ClientT, ModelT, CallbackT> request(Function
181181
* responses
182182
*/
183183
interface Caller<RequestT, ClientT, ModelT, CallbackT extends StdCallbackContext> {
184+
@Deprecated
185+
default <ResponseT>
186+
Stabilizer<RequestT, ResponseT, ClientT, ModelT, CallbackT>
187+
call(BiFunction<RequestT, ProxyClient<ClientT>, ResponseT> caller) {
188+
return makeServiceCall(caller);
189+
}
190+
184191
<ResponseT>
185192
Stabilizer<RequestT, ResponseT, ClientT, ModelT, CallbackT>
186-
call(BiFunction<RequestT, ProxyClient<ClientT>, ResponseT> caller);
193+
makeServiceCall(BiFunction<RequestT, ProxyClient<ClientT>, ResponseT> caller);
187194

188195
@Deprecated
189196
default Caller<RequestT, ClientT, ModelT, CallbackT> retry(Delay delay) {
190-
return backoff(delay);
197+
return backoffDelay(delay);
191198
}
192199

193-
Caller<RequestT, ClientT, ModelT, CallbackT> backoff(Delay delay);
200+
Caller<RequestT, ClientT, ModelT, CallbackT> backoffDelay(Delay delay);
194201

195202
}
196203

@@ -214,18 +221,6 @@ default Caller<RequestT, ClientT, ModelT, CallbackT> retry(Delay delay) {
214221
@FunctionalInterface
215222
interface Callback<RequestT, ResponseT, ClientT, ModelT, CallbackT extends StdCallbackContext, ReturnT> {
216223
ReturnT invoke(RequestT request, ResponseT response, ProxyClient<ClientT> client, ModelT model, CallbackT context);
217-
218-
static <RequestT, ResponseT, ClientT, ModelT, CallbackT extends StdCallbackContext>
219-
Callback<RequestT, ResponseT, ClientT, ModelT, CallbackT, ProgressEvent<ModelT, CallbackT>>
220-
progress() {
221-
return (r1, r2, c1, m1, c2) -> ProgressEvent.progress(m1, c2);
222-
}
223-
224-
static <RequestT, ResponseT, ClientT, ModelT, CallbackT extends StdCallbackContext>
225-
Callback<RequestT, ResponseT, ClientT, ModelT, CallbackT, ProgressEvent<ModelT, CallbackT>>
226-
success() {
227-
return (r1, r2, c1, m1, c2) -> ProgressEvent.success(m1, c2);
228-
}
229224
}
230225

231226
/**

src/main/java/software/amazon/cloudformation/proxy/package-info.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,9 @@
172172
* indicate successful completion.
173173
* {@link software.amazon.cloudformation.proxy.OperationStatus#IN_PROGRESS}
174174
* indicates that we can the proceed to next part of API calls to make for
175-
* resource configuration. E.g. for CloudWatchLogs LogGroup we first
176-
* create the LogGroup, then we update retention policy, associated KMS key and
177-
* finally delegate to Read Handler to return the complete state for the
178-
* resource
175+
* resource configuration. E.g. for CloudWatchLogs LogGroup we first create the
176+
* LogGroup, then we update retention policy, associated KMS key and finally
177+
* delegate to Read Handler to return the complete state for the resource
179178
*
180179
* <pre>
181180
* <code>
@@ -194,11 +193,10 @@
194193
* error with
195194
* {@link software.amazon.cloudformation.proxy.OperationStatus#FAILED} status
196195
* and an appropriate error message
197-
* software.amazon.cloudformation.proxy.ProgressEvent#getMessage() E.g.
198-
* if associateKMSKey had an error to associate KMS key for CloudWatchLogs to
199-
* use, the chain would exit with FAILED stauts and appropriate exception
200-
* message. Both
201-
* {@link software.amazon.cloudformation.proxy.OperationStatus#SUCCESS} and
196+
* software.amazon.cloudformation.proxy.ProgressEvent#getMessage() E.g. if
197+
* associateKMSKey had an error to associate KMS key for CloudWatchLogs to use,
198+
* the chain would exit with FAILED stauts and appropriate exception message.
199+
* Both {@link software.amazon.cloudformation.proxy.OperationStatus#SUCCESS} and
202200
* {@link software.amazon.cloudformation.proxy.OperationStatus#FAILED} are pivot
203201
* points in the chain that will skip the remainder of the chain.</li>
204202
* </ol>

src/test/java/software/amazon/cloudformation/proxy/AmazonWebServicesClientProxyTest.java

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ public void badRequest() {
244244
when(sdkHttpResponse.statusCode()).thenReturn(400);
245245
final ProgressEvent<Model,
246246
StdCallbackContext> result = proxy.initiate("client:createRespository", proxy.newProxy(() -> null), model, context)
247-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build()).call((r, c) -> {
247+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
248+
.makeServiceCall((r, c) -> {
248249
throw new BadRequestException(mock(AwsServiceException.Builder.class)) {
249250
private static final long serialVersionUID = 1L;
250251

@@ -273,7 +274,8 @@ public void notFound() {
273274
when(sdkHttpResponse.statusCode()).thenReturn(404);
274275
ProgressEvent<Model,
275276
StdCallbackContext> result = proxy.initiate("client:createRespository", proxy.newProxy(() -> null), model, context)
276-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build()).call((r, c) -> {
277+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
278+
.makeServiceCall((r, c) -> {
277279
throw new NotFoundException(mock(AwsServiceException.Builder.class)) {
278280
private static final long serialVersionUID = 1L;
279281

@@ -302,7 +304,8 @@ public void accessDenied() {
302304
when(sdkHttpResponse.statusCode()).thenReturn(401);
303305
ProgressEvent<Model,
304306
StdCallbackContext> result = proxy.initiate("client:createRespository", proxy.newProxy(() -> null), model, context)
305-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build()).call((r, c) -> {
307+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
308+
.makeServiceCall((r, c) -> {
306309
throw new AccessDenied(AwsServiceException.builder()) {
307310
private static final long serialVersionUID = 1L;
308311

@@ -354,8 +357,9 @@ public void throttleHandlingSuccess() {
354357

355358
ProgressEvent<Model,
356359
StdCallbackContext> result = proxy.initiate("client:createRepository", svcClient, model, context)
357-
.translate(m -> (requests[0] = new CreateRequest.Builder().repoName(m.getRepoName()).build()))
358-
.backoff(Constant.of().delay(Duration.ofSeconds(1)).timeout(Duration.ofSeconds(3)).build()).call((r, c) -> {
360+
.translateToServiceRequest(m -> (requests[0] = new CreateRequest.Builder().repoName(m.getRepoName()).build()))
361+
.backoffDelay(Constant.of().delay(Duration.ofSeconds(1)).timeout(Duration.ofSeconds(3)).build())
362+
.makeServiceCall((r, c) -> {
359363
if (attempt[0]-- > 0) {
360364
throw new ThrottleException(builder) {
361365
private static final long serialVersionUID = 1L;
@@ -371,8 +375,10 @@ public AwsErrorDetails awsErrorDetails() {
371375
})
372376
.done((request, response, client1, model1, context1) -> proxy
373377
.initiate("client:readRepository", client1, model1, context1)
374-
.translate(m -> (describeRequests[0] = new DescribeRequest.Builder().repoName(m.getRepoName()).build()))
375-
.call((r, c) -> (describeResponses[0] = c.injectCredentialsAndInvokeV2(r, c.client()::describeRepository)))
378+
.translateToServiceRequest(
379+
m -> (describeRequests[0] = new DescribeRequest.Builder().repoName(m.getRepoName()).build()))
380+
.makeServiceCall(
381+
(r, c) -> (describeResponses[0] = c.injectCredentialsAndInvokeV2(r, c.client()::describeRepository)))
376382
.done(r -> {
377383
Model resultModel = new Model();
378384
resultModel.setRepoName(r.getRepoName());
@@ -421,8 +427,9 @@ public void throttledExceedRuntimeBailout() {
421427

422428
final ProgressEvent<Model,
423429
StdCallbackContext> result = proxy.initiate("client:createRepository", svcClient, model, context)
424-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
425-
.backoff(Constant.of().delay(Duration.ofSeconds(5)).timeout(Duration.ofSeconds(10)).build()).call((r, c) -> {
430+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
431+
.backoffDelay(Constant.of().delay(Duration.ofSeconds(5)).timeout(Duration.ofSeconds(10)).build())
432+
.makeServiceCall((r, c) -> {
426433
throw new ThrottleException(AwsServiceException.builder()) {
427434
private static final long serialVersionUID = 1L;
428435

@@ -453,9 +460,9 @@ public void serviceCallWithStabilization() {
453460
ProxyClient<ServiceClient> svcClient = proxy.newProxy(() -> client);
454461
ProgressEvent<Model,
455462
StdCallbackContext> result = proxy.initiate("client:createRepository", svcClient, model, context)
456-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
457-
.backoff(Constant.of().delay(Duration.ofSeconds(5)).timeout(Duration.ofSeconds(15)).build())
458-
.call((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
463+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
464+
.backoffDelay(Constant.of().delay(Duration.ofSeconds(5)).timeout(Duration.ofSeconds(15)).build())
465+
.makeServiceCall((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
459466
.stabilize((request, response, client1, model1, context1) -> attempt[0]-- > 0)
460467
.retryErrorFilter((request, exception, client1, model1, context1) -> exception instanceof ThrottleException)
461468
.done(ign -> ProgressEvent.success(model, context));
@@ -492,9 +499,9 @@ public AwsErrorDetails awsErrorDetails() {
492499

493500
final ProgressEvent<Model,
494501
StdCallbackContext> result = proxy.initiate("client:createRepository", svcClient, model, context)
495-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
496-
.backoff(Constant.of().delay(Duration.ofSeconds(5)).timeout(Duration.ofSeconds(10)).build())
497-
.call((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
502+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
503+
.backoffDelay(Constant.of().delay(Duration.ofSeconds(5)).timeout(Duration.ofSeconds(10)).build())
504+
.makeServiceCall((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
498505
.retryErrorFilter((request, response, client1, model1, context1) -> response instanceof ThrottleException)
499506
.done(ign -> ProgressEvent.success(model, context));
500507

@@ -515,11 +522,13 @@ public void throwNotRetryableException() {
515522
StdCallbackContext context = new StdCallbackContext();
516523
ServiceClient client = mock(ServiceClient.class);
517524
ProxyClient<ServiceClient> svcClient = proxy.newProxy(() -> client);
518-
ProgressEvent<Model, StdCallbackContext> result = proxy.initiate("client:createRepository", svcClient, model, context)
519-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build()).call((r, g) -> {
520-
NonRetryableException e = NonRetryableException.builder().build();
521-
throw e;
522-
}).success();
525+
ProgressEvent<Model,
526+
StdCallbackContext> result = proxy.initiate("client:createRepository", svcClient, model, context)
527+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
528+
.makeServiceCall((r, g) -> {
529+
NonRetryableException e = NonRetryableException.builder().build();
530+
throw e;
531+
}).success();
523532
assertThat(result.getStatus()).isEqualTo(OperationStatus.FAILED);
524533

525534
}
@@ -539,7 +548,8 @@ public void throwOtherException() {
539548
ProxyClient<ServiceClient> svcClient = proxy.newProxy(() -> client);
540549
assertThrows(ResourceAlreadyExistsException.class,
541550
() -> proxy.initiate("client:createRepository", svcClient, model, context)
542-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build()).call((r, g) -> {
551+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
552+
.makeServiceCall((r, g) -> {
543553
throw new ResourceAlreadyExistsException(new RuntimeException("Fail"));
544554
}).success());
545555
}
@@ -555,10 +565,12 @@ public void useInitiatorPattern() {
555565
ServiceClient client = mock(ServiceClient.class);
556566
final CallChain.Initiator<ServiceClient, Model, StdCallbackContext> invoker = proxy
557567
.newInitiator(() -> client, model, context).rebindModel(model).rebindCallback(context);
558-
assertThrows(ResourceAlreadyExistsException.class, () -> invoker.initiate("client:createRepository")
559-
.translate(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build()).call((r, g) -> {
560-
throw new ResourceAlreadyExistsException(new RuntimeException("Fail"));
561-
}).success());
568+
assertThrows(ResourceAlreadyExistsException.class,
569+
() -> invoker.initiate("client:createRepository")
570+
.translateToServiceRequest(m -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
571+
.makeServiceCall((r, g) -> {
572+
throw new ResourceAlreadyExistsException(new RuntimeException("Fail"));
573+
}).success());
562574
}
563575

564576
@Test

src/test/java/software/amazon/cloudformation/proxy/End2EndCallChainTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,16 @@ public void happyCase() {
9696

9797
ProgressEvent<Model,
9898
StdCallbackContext> event = proxy.initiate("client:createRepository", client, model, context)
99-
.translate((m) -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
100-
.call((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
99+
.translateToServiceRequest((m) -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
100+
.makeServiceCall((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
101101
.done(r -> ProgressEvent.success(model, context));
102102

103103
assertThat(event.getStatus()).isEqualTo(OperationStatus.SUCCESS);
104104

105105
// replay, should get the same result.
106106
event = proxy.initiate("client:createRepository", client, model, context)
107-
.translate((m) -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
108-
.call((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
107+
.translateToServiceRequest((m) -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
108+
.makeServiceCall((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
109109
.done(r -> ProgressEvent.success(model, context));
110110
//
111111
// Verify that we only got called. During replay we should have been skipped.
@@ -133,8 +133,8 @@ public AwsErrorDetails awsErrorDetails() {
133133
when(serviceClient.createRepository(any(CreateRequest.class))).thenThrow(exists);
134134
StdCallbackContext newContext = new StdCallbackContext();
135135
event = proxy.initiate("client:createRepository", client, model, newContext)
136-
.translate((m) -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
137-
.call((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
136+
.translateToServiceRequest((m) -> new CreateRequest.Builder().repoName(m.getRepoName()).build())
137+
.makeServiceCall((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
138138
.done(r -> ProgressEvent.success(model, context));
139139

140140
assertThat(event.getStatus()).isEqualTo(OperationStatus.FAILED);

src/test/java/software/amazon/cloudformation/proxy/handler/CreateHandler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ public ProgressEvent<Model, StdCallbackContext> handleRequest(final AmazonWebSer
4242
final StdCallbackContext cxt = context == null ? new StdCallbackContext() : context;
4343

4444
ProxyClient<ServiceClient> client = proxy.newProxy(() -> this.client);
45-
return proxy.initiate("client:createRepository", client, model, cxt).translate((m) -> {
45+
return proxy.initiate("client:createRepository", client, model, cxt).translateToServiceRequest((m) -> {
4646
CreateRequest.Builder builder = new CreateRequest.Builder();
4747
builder.repoName(m.getRepoName());
4848
return builder.build();
49-
}).backoff(Constant.of().delay(Duration.ofSeconds(3)).timeout(Duration.ofSeconds(9)).build())
50-
.call((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
49+
}).backoffDelay(Constant.of().delay(Duration.ofSeconds(3)).timeout(Duration.ofSeconds(9)).build())
50+
.makeServiceCall((r, c) -> c.injectCredentialsAndInvokeV2(r, c.client()::createRepository))
5151
.done((request1, response, client1, model1, context1) -> new ReadHandler(this.client).handleRequest(proxy, request,
5252
cxt, loggerProxy));
5353

0 commit comments

Comments
 (0)