Skip to content

Commit 8fa6a3c

Browse files
Improve error handling and refactor to use new names/paths from IDL (#43)
1 parent 31594a0 commit 8fa6a3c

File tree

6 files changed

+68
-51
lines changed

6 files changed

+68
-51
lines changed

iwf-idl

src/main/java/io/github/cadenceoss/iwf/core/Client.java

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.HashMap;
99
import java.util.List;
1010
import java.util.Map;
11+
import java.util.stream.Collectors;
1112

1213
public class Client {
1314
private final Registry registry;
@@ -42,7 +43,7 @@ public String StartWorkflow(
4243
final String wfType = workflowClass.getSimpleName();
4344
final StateDef stateDef = registry.getWorkflowState(wfType, startStateId);
4445
if (stateDef == null || !stateDef.getCanStartWorkflow()) {
45-
throw new RuntimeException("invalid start stateId " + startStateId);
46+
throw new IllegalArgumentException("invalid start stateId " + startStateId);
4647
}
4748

4849
WorkflowStartResponse workflowStartResponse = defaultApi.apiV1WorkflowStartPost(new WorkflowStartRequest()
@@ -64,11 +65,11 @@ public String StartWorkflow(
6465
* @return
6566
* @param <T> type of the output
6667
*/
67-
public <T> T GetSimpleWorkflowResultWithLongWait(
68+
public <T> T GetSimpleWorkflowResultWithWait(
6869
Class<T> valueClass,
6970
final String workflowId,
7071
final String workflowRunId) {
71-
WorkflowGetResponse workflowGetResponse = defaultApi.apiV1WorkflowGetWithLongWaitPost(
72+
WorkflowGetResponse workflowGetResponse = defaultApi.apiV1WorkflowGetWithWaitPost(
7273
new WorkflowGetRequest()
7374
.needsResults(true)
7475
.workflowId(workflowId)
@@ -79,17 +80,15 @@ public <T> T GetSimpleWorkflowResultWithLongWait(
7980
Preconditions.checkNotNull(workflowGetResponse.getResults(), checkErrorMessage);
8081
Preconditions.checkArgument(workflowGetResponse.getResults().size() == 1, checkErrorMessage);
8182
Preconditions.checkNotNull(workflowGetResponse.getResults().get(0).getCompletedStateOutput(), checkErrorMessage);
82-
83-
//TODO validate encoding type
84-
83+
8584
final StateCompletionOutput output = workflowGetResponse.getResults().get(0);
8685
return objectEncoder.decode(output.getCompletedStateOutput(), valueClass);
8786
}
8887

89-
public <T> T GetSimpleWorkflowResultWithLongWait(
88+
public <T> T GetSimpleWorkflowResultWithWait(
9089
Class<T> valueClass,
9190
final String workflowId) {
92-
return GetSimpleWorkflowResultWithLongWait(valueClass, workflowId, "");
91+
return GetSimpleWorkflowResultWithWait(valueClass, workflowId, "");
9392
}
9493

9594
/**
@@ -98,9 +97,9 @@ public <T> T GetSimpleWorkflowResultWithLongWait(
9897
* @param workflowRunId
9998
* @return a list of the state output for completion states. User code will figure how to use ObjectEncoder to decode the output
10099
*/
101-
public List<StateCompletionOutput> GetComplexWorkflowResultWithLongWait(
100+
public List<StateCompletionOutput> GetComplexWorkflowResultWithWait(
102101
final String workflowId, final String workflowRunId) {
103-
WorkflowGetResponse workflowGetResponse = defaultApi.apiV1WorkflowGetWithLongWaitPost(
102+
WorkflowGetResponse workflowGetResponse = defaultApi.apiV1WorkflowGetWithWaitPost(
104103
new WorkflowGetRequest()
105104
.needsResults(true)
106105
.workflowId(workflowId)
@@ -110,8 +109,8 @@ public List<StateCompletionOutput> GetComplexWorkflowResultWithLongWait(
110109
return workflowGetResponse.getResults();
111110
}
112111

113-
public List<StateCompletionOutput> GetComplexWorkflowResultWithLongWait(final String workflowId) {
114-
return GetComplexWorkflowResultWithLongWait(workflowId, "");
112+
public List<StateCompletionOutput> GetComplexWorkflowResultWithWait(final String workflowId) {
113+
return GetComplexWorkflowResultWithWait(workflowId, "");
115114
}
116115
public void SignalWorkflow(
117116
final Class<? extends Workflow> workflowClass,
@@ -120,17 +119,20 @@ public void SignalWorkflow(
120119
final String signalChannelName,
121120
final Object signalValue) {
122121
final String wfType = workflowClass.getSimpleName();
123-
if (registry.getSignalChannelNameToSignalTypeMap(wfType) == null) {
124-
throw new RuntimeException(String.format("Workflow %s doesn't have any registered signal channels", wfType));
125-
}
126122

127123
Map<String, Class<?>> nameToTypeMap = registry.getSignalChannelNameToSignalTypeMap(wfType);
124+
if (nameToTypeMap == null) {
125+
throw new IllegalArgumentException(
126+
String.format("Workflow %s is not registered", wfType)
127+
);
128+
}
129+
128130
if (!nameToTypeMap.containsKey(signalChannelName)) {
129-
throw new RuntimeException(String.format("Workflow %s doesn't have signal %s", wfType, signalChannelName));
131+
throw new IllegalArgumentException(String.format("Workflow %s doesn't have signal %s", wfType, signalChannelName));
130132
}
131133
Class<?> signalType = nameToTypeMap.get(signalChannelName);
132134
if (!signalType.isInstance(signalValue)) {
133-
throw new RuntimeException(String.format("Signal value is not of type %s", signalType.getName()));
135+
throw new IllegalArgumentException(String.format("Signal value is not of type %s", signalType.getName()));
134136
}
135137

136138
defaultApi.apiV1WorkflowSignalPost(new WorkflowSignalRequest()
@@ -178,31 +180,38 @@ public String ResetWorkflow(
178180
return resp.getWorkflowRunId();
179181
}
180182

181-
public Map<String, Object> queryWorkflow(
183+
public Map<String, Object> getWorkflowQueryAttributes(
184+
final Class<? extends Workflow> workflowClass,
185+
final String workflowId,
186+
final String workflowRunId,
187+
List<String> attributeKeys) {
188+
if (attributeKeys == null || attributeKeys.isEmpty()) {
189+
throw new IllegalArgumentException("attributeKeys must contain at least one entry, or use getAllQueryAttributes API to get all");
190+
}
191+
return doGetWorkflowQueryAttributes(workflowClass, workflowId, workflowRunId, attributeKeys);
192+
}
193+
194+
private Map<String, Object> doGetWorkflowQueryAttributes(
182195
final Class<? extends Workflow> workflowClass,
183196
final String workflowId,
184197
final String workflowRunId,
185198
List<String> attributeKeys) {
186199
final String wfType = workflowClass.getSimpleName();
187-
if (registry.getWorkflow(wfType) == null) {
188-
throw new RuntimeException(
200+
201+
Map<String, Class<?>> queryAttributeKeyToTypeMap = registry.getQueryAttributeKeyToTypeMap(wfType);
202+
if (queryAttributeKeyToTypeMap == null) {
203+
throw new IllegalArgumentException(
189204
String.format("Workflow %s is not registered", wfType)
190205
);
191206
}
192-
if (registry.getQueryAttributeKeyToTypeMap(wfType) == null) {
193-
throw new RuntimeException(
194-
String.format("Workflow %s doesn't have any registered query attribute", wfType)
195-
);
196-
}
197207

198-
Map<String, Class<?>> queryAttributeKeyToTypeMap = registry.getQueryAttributeKeyToTypeMap(wfType);
199208
// if attribute keys is null or empty, iwf server will return all query attributes
200209
if (attributeKeys != null && !attributeKeys.isEmpty()) {
201210
List<String> nonExistingQueryAttributeList = attributeKeys.stream()
202211
.filter(s -> !queryAttributeKeyToTypeMap.containsKey(s))
203-
.toList();
212+
.collect(Collectors.toList());
204213
if (!nonExistingQueryAttributeList.isEmpty()) {
205-
throw new RuntimeException(
214+
throw new IllegalArgumentException(
206215
String.format(
207216
"Query attributes not registered: %s",
208217
String.join(", ", nonExistingQueryAttributeList)
@@ -211,15 +220,15 @@ public Map<String, Object> queryWorkflow(
211220
}
212221
}
213222

214-
WorkflowQueryResponse response = defaultApi.apiV1WorkflowQueryPost(
215-
new WorkflowQueryRequest()
223+
WorkflowGetQueryAttributesResponse response = defaultApi.apiV1WorkflowQueryattributesGetPost(
224+
new WorkflowGetQueryAttributesRequest()
216225
.workflowId(workflowId)
217226
.workflowRunId(workflowRunId)
218227
.attributeKeys(attributeKeys)
219228
);
220229

221230
if (response.getQueryAttributes() == null) {
222-
throw new RuntimeException("query attributes not returned");
231+
throw new InternalServiceException("query attributes not returned");
223232
}
224233
Map<String, Object> result = new HashMap<>();
225234
for (KeyValue keyValue: response.getQueryAttributes()) {
@@ -233,10 +242,10 @@ public Map<String, Object> queryWorkflow(
233242
return result;
234243
}
235244

236-
public Map<String, Object> queryAllQueryAttributes(
245+
public Map<String, Object> getAllQueryAttributes(
237246
final Class<? extends Workflow> workflowClass,
238247
final String workflowId,
239248
final String workflowRunId) {
240-
return queryWorkflow(workflowClass, workflowId, workflowRunId, null);
249+
return doGetWorkflowQueryAttributes(workflowClass, workflowId, workflowRunId, null);
241250
}
242251
}

src/main/java/io/github/cadenceoss/iwf/core/Registry.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,20 @@ private void registerWorkflow(final Workflow wf) {
2626
String workflowType = wf.getClass().getSimpleName();
2727

2828
if (workflowStore.containsKey(workflowType)) {
29-
throw new RuntimeException(String.format("Workflow type %s already exists", workflowType));
29+
throw new WorkflowDefinitionException(String.format("Workflow type %s already exists", workflowType));
3030
}
3131
workflowStore.put(workflowType, wf);
3232
}
3333

3434
private void registerWorkflowState(final Workflow wf) {
3535
String workflowType = wf.getClass().getSimpleName();
36+
if(wf.getStates() == null || wf.getStates().size() == 0){
37+
throw new WorkflowDefinitionException(String.format("Workflow type %s must contain at least one state", workflowType));
38+
}
3639
for (StateDef stateDef: wf.getStates()) {
3740
String key = getStateDefKey(workflowType, stateDef.getWorkflowState().getStateId());
3841
if (workflowStateStore.containsKey(key)) {
39-
throw new RuntimeException(String.format("Workflow state definition %s already exists", key));
42+
throw new WorkflowDefinitionException(String.format("Workflow state definition %s already exists", key));
4043
} else {
4144
workflowStateStore.put(key, stateDef);
4245
}
@@ -45,11 +48,16 @@ private void registerWorkflowState(final Workflow wf) {
4548

4649
private void registerWorkflowSignal(final Workflow wf) {
4750
String workflowType = wf.getClass().getSimpleName();
51+
if (wf.getSignalChannels() == null || wf.getSignalChannels().isEmpty()) {
52+
signalTypeStore.put(workflowType, new HashMap<>());
53+
return;
54+
}
55+
4856
for (SignalChannelDef signalChannelDef: wf.getSignalChannels()) {
4957
Map<String, Class<?>> signalNameToTypeMap =
5058
signalTypeStore.computeIfAbsent(workflowType, s -> new HashMap<>());
5159
if (signalNameToTypeMap.containsKey(signalChannelDef.getSignalChannelName())) {
52-
throw new RuntimeException(
60+
throw new WorkflowDefinitionException(
5361
String.format("Signal channel name %s already exists", signalChannelDef.getSignalChannelName()));
5462
}
5563
signalNameToTypeMap.put(signalChannelDef.getSignalChannelName(), signalChannelDef.getSignalValueType());
@@ -67,7 +75,7 @@ private void registerWorkflowQueryAttributes(final Workflow wf) {
6775
Map<String, Class<?>> queryAttributeKeyToTypeMap =
6876
queryAttributeTypeStore.computeIfAbsent(workflowType, s -> new HashMap<>());
6977
if (queryAttributeKeyToTypeMap.containsKey(queryAttributeDef.getQueryAttributeKey())) {
70-
throw new RuntimeException(
78+
throw new WorkflowDefinitionException(
7179
String.format(
7280
"Query attribute key %s already exists",
7381
queryAttributeDef.getQueryAttributeKey())

src/main/java/io/github/cadenceoss/iwf/core/attributes/QueryAttributesRWImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ public QueryAttributesRWImpl(
2828
@Override
2929
public <T> T get(String key, Class<T> type) {
3030
if (!queryAttributeNameToTypeMap.containsKey(key)) {
31-
throw new RuntimeException(String.format("Query attribute %s is not registered", key));
31+
throw new IllegalArgumentException(String.format("Query attribute %s is not registered", key));
3232
}
3333
if (!queryAttributeNameToEncodedObjectMap.containsKey(key)) {
3434
return null;
3535
}
3636

3737
Class<?> registeredType = queryAttributeNameToTypeMap.get(key);
3838
if (!type.isAssignableFrom(registeredType)) {
39-
throw new RuntimeException(
39+
throw new IllegalArgumentException(
4040
String.format(
4141
"%s is not assignable from registered type %s",
4242
type.getName(),
@@ -50,12 +50,12 @@ public <T> T get(String key, Class<T> type) {
5050
@Override
5151
public void set(String key, Object value) {
5252
if (!queryAttributeNameToTypeMap.containsKey(key)) {
53-
throw new RuntimeException(String.format("Query attribute %s is not registered", key));
53+
throw new IllegalArgumentException(String.format("Query attribute %s is not registered", key));
5454
}
5555

5656
Class<?> registeredType = queryAttributeNameToTypeMap.get(key);
5757
if (!registeredType.isInstance(value)) {
58-
throw new RuntimeException(String.format("Input is not an instance of class %s", registeredType.getName()));
58+
throw new IllegalArgumentException(String.format("Input is not an instance of class %s", registeredType.getName()));
5959
}
6060

6161
this.queryAttributeNameToEncodedObjectMap.put(key, objectEncoder.encode(value));

src/test/java/io/github/cadenceoss/iwf/integ/basic/BasicQueryWorkflow.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44
import io.github.cadenceoss.iwf.core.Workflow;
55
import io.github.cadenceoss.iwf.core.attributes.QueryAttributeDef;
66

7+
import java.util.Arrays;
78
import java.util.List;
89

910
public class BasicQueryWorkflow implements Workflow {
1011
public static final String ATTRIBUTE_KEY = "text";
1112
@Override
1213
public List<StateDef> getStates() {
13-
return List.of(StateDef.startingState(new BasicQueryWorkflowState1()));
14+
return Arrays.asList(StateDef.startingState(new BasicQueryWorkflowState1()));
1415
}
1516

1617
@Override
1718
public List<QueryAttributeDef> getQueryAttributes() {
18-
return List.of(QueryAttributeDef.create(String.class, ATTRIBUTE_KEY));
19+
return Arrays.asList(QueryAttributeDef.create(String.class, ATTRIBUTE_KEY));
1920
}
2021
}

src/test/java/io/github/cadenceoss/iwf/integ/basic/BasicTest.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package io.github.cadenceoss.iwf.integ.basic;
22

33
import io.github.cadenceoss.iwf.core.*;
4-
import io.github.cadenceoss.iwf.gen.models.EncodedObject;
54
import io.github.cadenceoss.iwf.spring.TestSingletonWorkerService;
65
import org.junit.jupiter.api.Assertions;
76
import org.junit.jupiter.api.BeforeEach;
87
import org.junit.jupiter.api.Test;
98

10-
import java.util.List;
9+
import java.util.Arrays;
1110
import java.util.Map;
1211

1312
public class BasicTest {
@@ -29,7 +28,7 @@ public void testBasicWorkflow() throws InterruptedException {
2928
final Integer input = Integer.valueOf(0);
3029
client.StartWorkflow(BasicWorkflow.class, BasicWorkflowS1.StateId, input, wfId, startOptions);
3130
// wait for workflow to finish
32-
final Integer output = client.GetSimpleWorkflowResultWithLongWait(Integer.class, wfId);
31+
final Integer output = client.GetSimpleWorkflowResultWithWait(Integer.class, wfId);
3332
Assertions.assertEquals(input + 2, output);
3433
}
3534

@@ -47,7 +46,7 @@ public void testBasicSignalWorkflow() throws InterruptedException {
4746
BasicSignalWorkflow.class, BasicSignalWorkflowState1.STATE_ID, input, wfId, startOptions);
4847
client.SignalWorkflow(
4948
BasicSignalWorkflow.class, wfId, runId, BasicSignalWorkflowState1.SIGNAL_CHANNEL_NAME, Integer.valueOf(2));
50-
final Integer output = client.GetSimpleWorkflowResultWithLongWait(Integer.class, wfId);
49+
final Integer output = client.GetSimpleWorkflowResultWithWait(Integer.class, wfId);
5150
Assertions.assertEquals(3, output);
5251
}
5352

@@ -61,13 +60,13 @@ public void testBasicQueryWorkflow() throws InterruptedException {
6160
final WorkflowStartOptions startOptions = WorkflowStartOptions.minimum(10);
6261
final String runId = client.StartWorkflow(
6362
BasicQueryWorkflow.class, BasicQueryWorkflowState1.STATE_ID, "start", wfId, startOptions);
64-
final String output = client.GetSimpleWorkflowResultWithLongWait(String.class, wfId);
63+
final String output = client.GetSimpleWorkflowResultWithWait(String.class, wfId);
6564
Map<String, Object> map =
66-
client.queryWorkflow(BasicQueryWorkflow.class, wfId, runId, List.of(BasicQueryWorkflow.ATTRIBUTE_KEY));
65+
client.getWorkflowQueryAttributes(BasicQueryWorkflow.class, wfId, runId, Arrays.asList(BasicQueryWorkflow.ATTRIBUTE_KEY));
6766
Assertions.assertEquals(
6867
"query-start-query-decide", map.get(BasicQueryWorkflow.ATTRIBUTE_KEY));
6968
Map<String, Object> allQueryAttributes =
70-
client.queryAllQueryAttributes(BasicQueryWorkflow.class, wfId, runId);
69+
client.getAllQueryAttributes(BasicQueryWorkflow.class, wfId, runId);
7170
Assertions.assertEquals(
7271
"query-start-query-decide", allQueryAttributes.get(BasicQueryWorkflow.ATTRIBUTE_KEY));
7372
Assertions.assertEquals(

0 commit comments

Comments
 (0)