Skip to content

Commit cf82e5e

Browse files
committed
refactor Invoke exceptions
1 parent 8d3c6b2 commit cf82e5e

14 files changed

Lines changed: 244 additions & 114 deletions

File tree

examples/src/test/java/com/amazonaws/lambda/durable/examples/InvokeExampleTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
// SPDX-License-Identifier: Apache-2.0
33
package com.amazonaws.lambda.durable.examples;
44

5+
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
57
import com.amazonaws.lambda.durable.model.ExecutionStatus;
68
import com.amazonaws.lambda.durable.testing.LocalDurableTestRunner;
79
import org.junit.jupiter.api.Test;
810
import software.amazon.awssdk.services.lambda.model.ErrorObject;
911

10-
import static org.junit.jupiter.api.Assertions.assertEquals;
11-
1212
class InvokeExampleTest {
1313

1414
@Test

sdk-integration-tests/src/test/java/com/amazonaws/lambda/durable/InvokeIntegrationTest.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
package com.amazonaws.lambda.durable;
44

55
import static org.junit.jupiter.api.Assertions.assertEquals;
6-
import static org.junit.jupiter.api.Assertions.assertFalse;
76
import static org.junit.jupiter.api.Assertions.assertNull;
8-
import static org.junit.jupiter.api.Assertions.assertTrue;
97

108
import com.amazonaws.lambda.durable.exception.InvokeFailedException;
119
import com.amazonaws.lambda.durable.model.ExecutionStatus;
@@ -106,11 +104,13 @@ void testInvokeWithFailedResults() {
106104
assertEquals(ExecutionStatus.PENDING, output1.getStatus());
107105
assertEquals(0, output1.getSucceededOperations().size());
108106

109-
runner.failChainedInvoke("invoke", ErrorObject.builder()
110-
.errorMessage("error output")
111-
.errorType("error type")
112-
.errorData("error data")
113-
.build());
107+
runner.failChainedInvoke(
108+
"invoke",
109+
ErrorObject.builder()
110+
.errorMessage("error output")
111+
.errorType("error type")
112+
.errorData("error data")
113+
.build());
114114
var output2 = runner.run(new TestInput("test"));
115115

116116
assertEquals(ExecutionStatus.FAILED, output2.getStatus());
@@ -139,19 +139,20 @@ void testInvokeWithStoppedResults() {
139139
assertEquals(ExecutionStatus.PENDING, output1.getStatus());
140140
assertEquals(0, output1.getSucceededOperations().size());
141141

142-
runner.stopChainedInvoke("invoke", ErrorObject.builder()
143-
.errorMessage("error output")
144-
.errorType("error type")
145-
.errorData("error data")
146-
.build());
142+
runner.stopChainedInvoke(
143+
"invoke",
144+
ErrorObject.builder()
145+
.errorMessage("error output")
146+
.errorType("error type")
147+
.errorData("error data")
148+
.build());
147149
var output2 = runner.run(new TestInput("test"));
148150

149151
assertEquals(ExecutionStatus.FAILED, output2.getStatus());
150152
// todo: the error object should equal to the error object returned by chained invoke
151153
ErrorObject error = output2.getError().orElseThrow();
152-
assertEquals("com.amazonaws.lambda.durable.exception.InvokeFailedException", error.errorType());
154+
assertEquals("com.amazonaws.lambda.durable.exception.InvokeStoppedException", error.errorType());
153155
assertEquals("error output", error.errorMessage());
154-
assertTrue(error.errorData().contains("STOPPED"));
155156
}
156157

157158
@Test
@@ -179,8 +180,7 @@ void testInvokeWithTimeoutResults() {
179180
assertEquals(ExecutionStatus.FAILED, output2.getStatus());
180181
// todo: the error object should equal to the error object returned by chained invoke
181182
ErrorObject error = output2.getError().orElseThrow();
182-
assertEquals("com.amazonaws.lambda.durable.exception.InvokeFailedException", error.errorType());
183+
assertEquals("com.amazonaws.lambda.durable.exception.InvokeTimedOutException", error.errorType());
183184
assertNull(error.errorMessage());
184-
assertTrue(error.errorData().contains("TIMED_OUT"));
185185
}
186186
}

sdk-testing/src/main/java/com/amazonaws/lambda/durable/testing/LocalDurableTestRunner.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import software.amazon.awssdk.services.lambda.model.OperationType;
2222

2323
public class LocalDurableTestRunner<I, O> {
24-
public record ChainedInvokeResult(OperationStatus operationStatus, String result, ErrorObject error) {}
25-
2624
private static final int MAX_INVOCATIONS = 100;
2725

2826
private final Class<I> inputType;
@@ -232,22 +230,22 @@ public void advanceTime() {
232230

233231
// Manual complete a chained invoke call
234232
public void completeChainedInvoke(String name, String result) {
235-
storage.completeChainedInvoke(name, new ChainedInvokeResult(OperationStatus.SUCCEEDED, result, null));
233+
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.SUCCEEDED, result, null));
236234
}
237235

238236
// Manual mark a chained invoke call TIMEOUT
239237
public void timeoutChainedInvoke(String name) {
240-
storage.completeChainedInvoke(name, new ChainedInvokeResult(OperationStatus.TIMED_OUT, null, null));
238+
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.TIMED_OUT, null, null));
241239
}
242240

243241
// Manual fail a chained invoke call
244242
public void failChainedInvoke(String name, ErrorObject error) {
245-
storage.completeChainedInvoke(name, new ChainedInvokeResult(OperationStatus.FAILED, null, error));
243+
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.FAILED, null, error));
246244
}
247245

248246
// Manual stop a chained invoke call
249247
public void stopChainedInvoke(String name, ErrorObject error) {
250-
storage.completeChainedInvoke(name, new ChainedInvokeResult(OperationStatus.STOPPED, null, error));
248+
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.STOPPED, null, error));
251249
}
252250

253251
private DurableExecutionInput createDurableInput(I input) {

sdk-testing/src/main/java/com/amazonaws/lambda/durable/testing/LocalMemoryExecutionClient.java

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -87,33 +87,34 @@ public void advanceReadyOperations() {
8787
});
8888
}
8989

90-
public void completeChainedInvoke(String name, LocalDurableTestRunner.ChainedInvokeResult result) {
91-
operations.replaceAll((id, op) -> {
92-
if (op.type() == OperationType.CHAINED_INVOKE
93-
&& op.status() == OperationStatus.STARTED
94-
&& op.name().equals(name)) {
95-
var newOp = op.toBuilder()
96-
.status(result.operationStatus())
97-
.chainedInvokeDetails(ChainedInvokeDetails.builder()
98-
.result(result.result())
99-
.error(result.error())
100-
.build())
101-
.build();
102-
var update = OperationUpdate.builder()
103-
.id(id)
104-
.name(op.name())
105-
.type(OperationType.CHAINED_INVOKE)
106-
.action(
107-
result.operationStatus() == OperationStatus.SUCCEEDED
108-
? OperationAction.SUCCEED
109-
: OperationAction.FAIL)
110-
.build();
111-
var event = eventProcessor.processUpdate(update, newOp);
112-
allEvents.add(event);
113-
return newOp;
114-
}
115-
return op;
116-
});
90+
public void completeChainedInvoke(String name, OperationResult result) {
91+
var op = getOperationByName(name);
92+
if (op == null) {
93+
throw new IllegalStateException("Operation not found: " + name);
94+
}
95+
if (op.type() == OperationType.CHAINED_INVOKE
96+
&& op.status() == OperationStatus.STARTED
97+
&& op.name().equals(name)) {
98+
var newOp = op.toBuilder()
99+
.status(result.operationStatus())
100+
.chainedInvokeDetails(ChainedInvokeDetails.builder()
101+
.result(result.result())
102+
.error(result.error())
103+
.build())
104+
.build();
105+
var update = OperationUpdate.builder()
106+
.id(op.id())
107+
.name(op.name())
108+
.type(OperationType.CHAINED_INVOKE)
109+
.action(
110+
result.operationStatus() == OperationStatus.SUCCEEDED
111+
? OperationAction.SUCCEED
112+
: OperationAction.FAIL)
113+
.build();
114+
var event = eventProcessor.processUpdate(update, newOp);
115+
allEvents.add(event);
116+
operations.put(op.id(), newOp);
117+
}
117118
}
118119

119120
public Operation getOperationByName(String name) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package com.amazonaws.lambda.durable.testing;
4+
5+
import software.amazon.awssdk.services.lambda.model.ErrorObject;
6+
import software.amazon.awssdk.services.lambda.model.OperationStatus;
7+
8+
/** The operation status and result/error from Step, Context, Callback and ChainedInvoke operations */
9+
public record OperationResult(OperationStatus operationStatus, String result, ErrorObject error) {}

sdk-testing/src/test/java/com/amazonaws/lambda/durable/testing/LocalMemoryExecutionClientTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.List;
88
import org.junit.jupiter.api.Test;
99
import software.amazon.awssdk.services.lambda.model.OperationAction;
10+
import software.amazon.awssdk.services.lambda.model.OperationStatus;
1011
import software.amazon.awssdk.services.lambda.model.OperationType;
1112
import software.amazon.awssdk.services.lambda.model.OperationUpdate;
1213

@@ -62,4 +63,15 @@ void testSimulateFireAndForgetCheckpointLossThrowsWhenOperationNotFound() {
6263
IllegalStateException.class, () -> client.simulateFireAndForgetCheckpointLoss("nonexistent-step"));
6364
assertEquals("Operation not found: nonexistent-step", exception.getMessage());
6465
}
66+
67+
@Test
68+
void testCompleteInvocationThrowsWhenOperationNotFound() {
69+
var client = new LocalMemoryExecutionClient();
70+
71+
var exception = assertThrows(
72+
IllegalStateException.class,
73+
() -> client.completeChainedInvoke(
74+
"nonexistent-invoke", new OperationResult(OperationStatus.TIMED_OUT, null, null)));
75+
assertEquals("Operation not found: nonexistent-invoke", exception.getMessage());
76+
}
6577
}

sdk/src/main/java/com/amazonaws/lambda/durable/exception/DurableExecutionException.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@
88
public class DurableExecutionException extends RuntimeException {
99
public DurableExecutionException(String message, Throwable cause, StackTraceElement[] stackTrace) {
1010
super(message, cause);
11-
this.setStackTrace(stackTrace);
11+
if (stackTrace != null) {
12+
this.setStackTrace(stackTrace);
13+
}
1214
}
1315

1416
public DurableExecutionException(String message, Throwable cause) {
15-
super(message, cause);
17+
this(message, cause, null);
1618
}
1719

1820
public DurableExecutionException(String message) {
19-
super(message);
21+
this(message, null, null);
2022
}
2123

2224
// StackTraceElement.toString() is implementation-dependent, so we'll define our
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package com.amazonaws.lambda.durable.exception;
4+
5+
import software.amazon.awssdk.services.lambda.model.ErrorObject;
6+
import software.amazon.awssdk.services.lambda.model.OperationStatus;
7+
8+
public class InvokeException extends DurableExecutionException {
9+
private final ErrorObject errorObject;
10+
private final OperationStatus operationStatus;
11+
12+
public InvokeException(OperationStatus operationStatus, ErrorObject errorObject) {
13+
super(
14+
errorObject != null ? errorObject.errorMessage() : null,
15+
null,
16+
errorObject != null ? DurableExecutionException.deserializeStackTrace(errorObject.stackTrace()) : null);
17+
this.operationStatus = operationStatus;
18+
this.errorObject = errorObject;
19+
}
20+
21+
public String getErrorData() {
22+
return errorObject == null ? null : errorObject.errorData();
23+
}
24+
25+
public String getErrorType() {
26+
return errorObject == null ? null : errorObject.errorType();
27+
}
28+
29+
public OperationStatus getOperationStatus() {
30+
return operationStatus;
31+
}
32+
}

sdk/src/main/java/com/amazonaws/lambda/durable/exception/InvokeFailedException.java

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,9 @@
55
import software.amazon.awssdk.services.lambda.model.ErrorObject;
66
import software.amazon.awssdk.services.lambda.model.OperationStatus;
77

8-
public class InvokeFailedException extends DurableExecutionException {
9-
private final ErrorObject errorObject;
10-
private final OperationStatus operationStatus;
8+
public class InvokeFailedException extends InvokeException {
119

12-
private InvokeFailedException(OperationStatus operationStatus, ErrorObject errorObject) {
13-
super(
14-
errorObject.errorMessage(),
15-
null,
16-
DurableExecutionException.deserializeStackTrace(errorObject.stackTrace()));
17-
this.operationStatus = operationStatus;
18-
this.errorObject = errorObject;
19-
}
20-
21-
private InvokeFailedException(OperationStatus operationStatus) {
22-
super(null, null);
23-
this.operationStatus = operationStatus;
24-
errorObject = null;
25-
}
26-
27-
public String getErrorData() {
28-
return errorObject == null ? null : errorObject.errorData();
29-
}
30-
31-
public String getErrorType() {
32-
return errorObject == null ? null : errorObject.errorType();
33-
}
34-
35-
public OperationStatus getOperationStatus() {
36-
return operationStatus;
37-
}
38-
39-
public static InvokeFailedException create(OperationStatus operationStatus, ErrorObject errorObject) {
40-
if (errorObject == null) {
41-
return new InvokeFailedException(operationStatus);
42-
} else {
43-
return new InvokeFailedException(operationStatus, errorObject);
44-
}
10+
public InvokeFailedException(ErrorObject errorObject) {
11+
super(OperationStatus.FAILED, errorObject);
4512
}
4613
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package com.amazonaws.lambda.durable.exception;
4+
5+
import software.amazon.awssdk.services.lambda.model.ErrorObject;
6+
import software.amazon.awssdk.services.lambda.model.OperationStatus;
7+
8+
public class InvokeStoppedException extends InvokeException {
9+
10+
public InvokeStoppedException(ErrorObject errorObject) {
11+
super(OperationStatus.STOPPED, errorObject);
12+
}
13+
}

0 commit comments

Comments
 (0)