Skip to content

Commit 3fe2f37

Browse files
authored
Add descriptive error when orchestration type is not registered (#261)
1 parent 8bb8050 commit 3fe2f37

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,12 @@ private void processEvent(HistoryEvent e) {
882882
// Try getting the default orchestrator
883883
factory = TaskOrchestrationExecutor.this.orchestrationFactories.get("*");
884884
}
885-
// TODO: Throw if the factory is null (orchestration by that name doesn't exist)
885+
if (factory == null) {
886+
throw new IllegalStateException(String.format(
887+
"No orchestration factory registered for orchestration type '%s'. This usually means that a worker that doesn't support this orchestration type is connected to this task hub. Make sure the worker has a registered orchestration for '%s'.",
888+
name,
889+
name));
890+
}
886891
TaskOrchestration orchestrator = factory.create();
887892
orchestrator.run(this);
888893
break;
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.durabletask;
5+
6+
import com.google.protobuf.StringValue;
7+
import com.google.protobuf.Timestamp;
8+
import com.microsoft.durabletask.implementation.protobuf.OrchestratorService.*;
9+
import org.junit.jupiter.api.Test;
10+
11+
import java.time.Duration;
12+
import java.util.*;
13+
import java.util.logging.Logger;
14+
15+
import static org.junit.jupiter.api.Assertions.*;
16+
17+
/**
18+
* Unit tests for TaskOrchestrationExecutor.
19+
*/
20+
public class TaskOrchestrationExecutorTest {
21+
22+
private static final Logger logger = Logger.getLogger(TaskOrchestrationExecutorTest.class.getName());
23+
24+
@Test
25+
void execute_unregisteredOrchestrationType_failsWithDescriptiveMessage() {
26+
// Arrange: create executor with no registered orchestrations
27+
HashMap<String, TaskOrchestrationFactory> factories = new HashMap<>();
28+
TaskOrchestrationExecutor executor = new TaskOrchestrationExecutor(
29+
factories,
30+
new JacksonDataConverter(),
31+
Duration.ofDays(3),
32+
logger,
33+
null);
34+
35+
String unknownName = "NonExistentOrchestration";
36+
37+
// Build history events simulating an orchestration start
38+
HistoryEvent orchestratorStarted = HistoryEvent.newBuilder()
39+
.setEventId(-1)
40+
.setTimestamp(Timestamp.getDefaultInstance())
41+
.setOrchestratorStarted(OrchestratorStartedEvent.getDefaultInstance())
42+
.build();
43+
44+
HistoryEvent executionStarted = HistoryEvent.newBuilder()
45+
.setEventId(-1)
46+
.setTimestamp(Timestamp.getDefaultInstance())
47+
.setExecutionStarted(ExecutionStartedEvent.newBuilder()
48+
.setName(unknownName)
49+
.setVersion(StringValue.of(""))
50+
.setInput(StringValue.of("\"test-input\""))
51+
.setOrchestrationInstance(OrchestrationInstance.newBuilder()
52+
.setInstanceId("test-instance-id")
53+
.build())
54+
.build())
55+
.build();
56+
57+
HistoryEvent orchestratorCompleted = HistoryEvent.newBuilder()
58+
.setEventId(-1)
59+
.setTimestamp(Timestamp.getDefaultInstance())
60+
.setOrchestratorCompleted(OrchestratorCompletedEvent.getDefaultInstance())
61+
.build();
62+
63+
List<HistoryEvent> pastEvents = Arrays.asList(orchestratorStarted, executionStarted, orchestratorCompleted);
64+
List<HistoryEvent> newEvents = Collections.emptyList();
65+
66+
// Act
67+
TaskOrchestratorResult result = executor.execute(pastEvents, newEvents);
68+
69+
// Assert: the result should contain a CompleteOrchestrationAction with FAILED status
70+
// and a failure message mentioning the unknown orchestration name
71+
OrchestratorAction action = result.getActions().iterator().next();
72+
assertTrue(action.hasCompleteOrchestration(), "Expected a CompleteOrchestrationAction");
73+
74+
CompleteOrchestrationAction completeAction = action.getCompleteOrchestration();
75+
assertEquals(OrchestrationStatus.ORCHESTRATION_STATUS_FAILED, completeAction.getOrchestrationStatus());
76+
assertTrue(completeAction.hasFailureDetails(), "Expected failure details");
77+
78+
TaskFailureDetails failureDetails = completeAction.getFailureDetails();
79+
assertEquals("java.lang.IllegalStateException", failureDetails.getErrorType());
80+
assertTrue(failureDetails.getErrorMessage().contains(unknownName),
81+
"Error message should contain the orchestration name: " + failureDetails.getErrorMessage());
82+
assertTrue(failureDetails.getErrorMessage().contains("worker"),
83+
"Error message should mention workers: " + failureDetails.getErrorMessage());
84+
}
85+
}

0 commit comments

Comments
 (0)