Skip to content

Commit fb04187

Browse files
committed
added error handling for when an instance id doesn't exist
1 parent 4bfd85a commit fb04187

File tree

5 files changed

+90
-0
lines changed

5 files changed

+90
-0
lines changed

client/src/main/java/com/microsoft/durabletask/DurableTaskGrpcClient.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ public void rewindInstance(String instanceId, @Nullable String reason) {
374374
try {
375375
this.sidecarClient.rewindInstance(rewindRequestBuilder.build());
376376
} catch (StatusRuntimeException e) {
377+
if (e.getStatus().getCode() == Status.Code.NOT_FOUND) {
378+
throw new IllegalArgumentException(
379+
"No orchestration instance with ID '" + instanceId + "' was found.", e);
380+
}
377381
if (e.getStatus().getCode() == Status.Code.FAILED_PRECONDITION) {
378382
throw new IllegalStateException(
379383
"Orchestration instance '" + instanceId + "' is not in a failed state and cannot be rewound.", e);

endtoendtests/src/main/java/com/functions/RewindTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,35 @@ public String failOnceSubActivity(
228228
return input + "-sub-rewound-success";
229229
}
230230

231+
/**
232+
* HTTP trigger that attempts to rewind a non-existent orchestration instance.
233+
* This should result in an IllegalArgumentException being thrown by the client
234+
* when the server returns a NOT_FOUND gRPC status.
235+
*/
236+
@FunctionName("StartRewindNonExistentOrchestration")
237+
public HttpResponseMessage startRewindNonExistentOrchestration(
238+
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
239+
@DurableClientInput(name = "durableContext") DurableClientContext durableContext,
240+
final ExecutionContext context) {
241+
context.getLogger().info("Attempting to rewind a non-existent orchestration instance.");
242+
243+
DurableTaskClient client = durableContext.getClient();
244+
String nonExistentInstanceId = "non-existent-instance-" + System.currentTimeMillis();
245+
246+
try {
247+
client.rewindInstance(nonExistentInstanceId, "Testing rewind on non-existent instance");
248+
// If we get here, the rewind did not throw as expected
249+
return request.createResponseBuilder(com.microsoft.azure.functions.HttpStatus.INTERNAL_SERVER_ERROR)
250+
.body("IllegalArgumentException was not thrown")
251+
.build();
252+
} catch (IllegalArgumentException e) {
253+
context.getLogger().info("Rewind on non-existent instance threw expected exception: " + e.getMessage());
254+
return request.createResponseBuilder(com.microsoft.azure.functions.HttpStatus.OK)
255+
.body(e.getMessage())
256+
.build();
257+
}
258+
}
259+
231260
/**
232261
* HTTP trigger to reset the sub-orchestration failure flag.
233262
*/

endtoendtests/src/test/java/com/functions/EndToEndTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,20 @@ public void rewindFailedOrchestration() throws InterruptedException {
253253
assertTrue(output.contains("rewound-success"), "Output should indicate successful rewind: " + output);
254254
}
255255

256+
@Test
257+
public void rewindNonExistentOrchestration() throws InterruptedException {
258+
// Attempt to rewind a non-existent orchestration instance.
259+
// The trigger calls client.rewindInstance() with a fake instance ID and
260+
// expects an IllegalArgumentException (from gRPC NOT_FOUND status).
261+
String startOrchestrationPath = "/api/StartRewindNonExistentOrchestration";
262+
Response response = post(startOrchestrationPath);
263+
assertEquals(200, response.getStatusCode(),
264+
"Expected 200 OK indicating the IllegalArgumentException was caught. Body: " + response.getBody().asString());
265+
String body = response.getBody().asString();
266+
assertTrue(body.contains("No orchestration instance with ID") && body.contains("was found"),
267+
"Response should contain the not-found error message, but was: " + body);
268+
}
269+
256270
@Test
257271
public void rewindNonFailedOrchestration() throws InterruptedException {
258272
// Start a non-failing orchestration - the trigger waits for completion

samples-azure-functions/src/main/java/com/functions/RewindTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,35 @@ public String failOnceActivity(
9494
return input + "-rewound-success";
9595
}
9696

97+
/**
98+
* HTTP trigger that attempts to rewind a non-existent orchestration instance.
99+
* This should result in an IllegalArgumentException being thrown by the client
100+
* when the server returns a NOT_FOUND gRPC status.
101+
*/
102+
@FunctionName("StartRewindNonExistentOrchestration")
103+
public HttpResponseMessage startRewindNonExistentOrchestration(
104+
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
105+
@DurableClientInput(name = "durableContext") DurableClientContext durableContext,
106+
final ExecutionContext context) {
107+
context.getLogger().info("Attempting to rewind a non-existent orchestration instance.");
108+
109+
DurableTaskClient client = durableContext.getClient();
110+
String nonExistentInstanceId = "non-existent-instance-" + System.currentTimeMillis();
111+
112+
try {
113+
client.rewindInstance(nonExistentInstanceId, "Testing rewind on non-existent instance");
114+
// If we get here, the rewind did not throw as expected
115+
return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
116+
.body("IllegalArgumentException was not thrown")
117+
.build();
118+
} catch (IllegalArgumentException e) {
119+
context.getLogger().info("Rewind on non-existent instance threw expected exception: " + e.getMessage());
120+
return request.createResponseBuilder(HttpStatus.OK)
121+
.body(e.getMessage())
122+
.build();
123+
}
124+
}
125+
97126
/**
98127
* HTTP trigger to reset the failure flag (useful for testing).
99128
*/

samples-azure-functions/src/test/java/com/functions/EndToEndTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,20 @@ public void orchestrationPOJO() throws InterruptedException {
229229
assertEquals("\"TESTNAME\"", outputName);
230230
}
231231

232+
@Test
233+
public void rewindNonExistentOrchestration() throws InterruptedException {
234+
// Attempt to rewind a non-existent orchestration instance.
235+
// The trigger calls client.rewindInstance() with a fake instance ID and
236+
// expects an IllegalArgumentException (from gRPC NOT_FOUND status).
237+
String startOrchestrationPath = "/api/StartRewindNonExistentOrchestration";
238+
Response response = post(startOrchestrationPath);
239+
assertEquals(200, response.getStatusCode(),
240+
"Expected 200 OK indicating the IllegalArgumentException was caught. Body: " + response.getBody().asString());
241+
String body = response.getBody().asString();
242+
assertTrue(body.contains("No orchestration instance with ID") && body.contains("was found"),
243+
"Response should contain the not-found error message, but was: " + body);
244+
}
245+
232246
@Test
233247
public void rewindFailedOrchestration() throws InterruptedException {
234248
// Reset the failure flag before starting

0 commit comments

Comments
 (0)