Skip to content

Commit 54a2c50

Browse files
authored
Added in-memory Cadence service implementation to support unit testing. (#125)
1 parent 685d86b commit 54a2c50

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+6762
-102
lines changed

src/main/java/com/uber/cadence/activity/ActivityOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public Builder() {}
7373

7474
/** Copy Builder fields from the options. */
7575
public Builder(ActivityOptions options) {
76+
if (options == null) {
77+
return;
78+
}
7679
this.scheduleToStartTimeout = options.getScheduleToStartTimeout();
7780
this.scheduleToCloseTimeout = options.getScheduleToCloseTimeout();
7881
this.heartbeatTimeout = options.getHeartbeatTimeout();

src/main/java/com/uber/cadence/client/WorkflowClient.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import com.uber.cadence.activity.Activity;
2222
import com.uber.cadence.internal.sync.WorkflowClientInternal;
2323
import com.uber.cadence.serviceclient.IWorkflowService;
24-
import com.uber.cadence.serviceclient.WorkflowServiceTChannel;
2524
import com.uber.cadence.workflow.Functions;
2625
import com.uber.cadence.workflow.Functions.Func;
2726
import com.uber.cadence.workflow.Functions.Func1;
@@ -81,8 +80,7 @@ public interface WorkflowClient {
8180
* @param domain domain that worker uses to poll.
8281
*/
8382
static WorkflowClient newInstance(String domain) {
84-
return new WorkflowClientInternal(
85-
new WorkflowServiceTChannel(), domain, new WorkflowClientOptions.Builder().build());
83+
return WorkflowClientInternal.newInstance(domain);
8684
}
8785

8886
/**
@@ -94,7 +92,7 @@ static WorkflowClient newInstance(String domain) {
9492
* configuring client.
9593
*/
9694
static WorkflowClient newInstance(String domain, WorkflowClientOptions options) {
97-
return new WorkflowClientInternal(new WorkflowServiceTChannel(), domain, options);
95+
return WorkflowClientInternal.newInstance(domain, options);
9896
}
9997

10098
/**
@@ -105,10 +103,7 @@ static WorkflowClient newInstance(String domain, WorkflowClientOptions options)
105103
* @param domain domain that worker uses to poll.
106104
*/
107105
static WorkflowClient newInstance(String host, int port, String domain) {
108-
return new WorkflowClientInternal(
109-
new WorkflowServiceTChannel(host, port),
110-
domain,
111-
new WorkflowClientOptions.Builder().build());
106+
return WorkflowClientInternal.newInstance(host, port, domain);
112107
}
113108

114109
/**
@@ -122,7 +117,7 @@ static WorkflowClient newInstance(String host, int port, String domain) {
122117
*/
123118
static WorkflowClient newInstance(
124119
String host, int port, String domain, WorkflowClientOptions options) {
125-
return new WorkflowClientInternal(new WorkflowServiceTChannel(host, port), domain, options);
120+
return WorkflowClientInternal.newInstance(host, port, domain, options);
126121
}
127122

128123
/**
@@ -132,7 +127,7 @@ static WorkflowClient newInstance(
132127
* @param domain domain that worker uses to poll.
133128
*/
134129
static WorkflowClient newInstance(IWorkflowService service, String domain) {
135-
return new WorkflowClientInternal(service, domain, null);
130+
return WorkflowClientInternal.newInstance(service, domain);
136131
}
137132

138133
/**
@@ -145,9 +140,11 @@ static WorkflowClient newInstance(IWorkflowService service, String domain) {
145140
*/
146141
static WorkflowClient newInstance(
147142
IWorkflowService service, String domain, WorkflowClientOptions options) {
148-
return new WorkflowClientInternal(service, domain, options);
143+
return WorkflowClientInternal.newInstance(service, domain, options);
149144
}
150145

146+
String getDomain();
147+
151148
/**
152149
* Creates workflow client stub that can be used to start a single workflow execution. The first
153150
* call must be to a method annotated with @WorkflowMethod. After workflow is started it can be
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
7+
* use this file except in compliance with the License. A copy of the License is
8+
* located at
9+
*
10+
* http://aws.amazon.com/apache2.0
11+
*
12+
* or in the "license" file accompanying this file. This file is distributed on
13+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
* express or implied. See the License for the specific language governing
15+
* permissions and limitations under the License.
16+
*/
17+
18+
package com.uber.cadence.client;
19+
20+
import com.uber.cadence.WorkflowExecution;
21+
22+
/**
23+
* Thrown when workflow with the given id is not known to the cadence service. It could be because
24+
* id is not correct or workflow was purged from the service after reaching its retention limit.
25+
*/
26+
public final class WorkflowNotFoundException extends WorkflowException {
27+
28+
public WorkflowNotFoundException(
29+
WorkflowExecution execution, String workflowType, String message) {
30+
super(message, execution, workflowType, null);
31+
}
32+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
7+
* use this file except in compliance with the License. A copy of the License is
8+
* located at
9+
*
10+
* http://aws.amazon.com/apache2.0
11+
*
12+
* or in the "license" file accompanying this file. This file is distributed on
13+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
* express or implied. See the License for the specific language governing
15+
* permissions and limitations under the License.
16+
*/
17+
18+
package com.uber.cadence.client;
19+
20+
import com.uber.cadence.WorkflowExecution;
21+
22+
public final class WorkflowQueryException extends WorkflowException {
23+
24+
public WorkflowQueryException(WorkflowExecution execution, String message) {
25+
super(message, execution, null, null);
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
7+
* use this file except in compliance with the License. A copy of the License is
8+
* located at
9+
*
10+
* http://aws.amazon.com/apache2.0
11+
*
12+
* or in the "license" file accompanying this file. This file is distributed on
13+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
* express or implied. See the License for the specific language governing
15+
* permissions and limitations under the License.
16+
*/
17+
18+
package com.uber.cadence.client;
19+
20+
import com.uber.cadence.WorkflowExecution;
21+
22+
public final class WorkflowServiceException extends WorkflowException {
23+
24+
public WorkflowServiceException(WorkflowExecution execution, String message) {
25+
super(message, execution, null, null);
26+
}
27+
}

src/main/java/com/uber/cadence/converter/JsonDataConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public static DataConverter getInstance() {
8181
return INSTANCE;
8282
}
8383

84-
public JsonDataConverter() {
84+
private JsonDataConverter() {
8585
this((b) -> b);
8686
}
8787

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
7+
* use this file except in compliance with the License. A copy of the License is
8+
* located at
9+
*
10+
* http://aws.amazon.com/apache2.0
11+
*
12+
* or in the "license" file accompanying this file. This file is distributed on
13+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
* express or implied. See the License for the specific language governing
15+
* permissions and limitations under the License.
16+
*/
17+
18+
package com.uber.cadence.internal.common;
19+
20+
import com.uber.cadence.workflow.Functions;
21+
import java.lang.invoke.SerializedLambda;
22+
import java.lang.reflect.InvocationTargetException;
23+
import java.lang.reflect.Method;
24+
25+
public final class LambdaUtils {
26+
27+
/**
28+
* Get target of the method reference that was converted to a lambda.
29+
*
30+
* @param l lambda expression that could be a method reference.
31+
* @return either target of the method reference or null if it is not reference in form
32+
* object::method.
33+
*/
34+
public static Object getTarget(SerializedLambda l) {
35+
if (l == null) {
36+
return null;
37+
}
38+
// If lambda is a method call on an object then the first captured argument is the object.
39+
if (l.getCapturedArgCount() > 0) {
40+
return l.getCapturedArg(0);
41+
}
42+
return null;
43+
}
44+
45+
/**
46+
* Unfortunate sorcery to reflect on lambda. Works only if function that lambda implements is
47+
* serializable. This is why {@link Functions} is needed as all its functions are serializable.
48+
*
49+
* @param lambda lambda that potentially implements {@link java.io.Serializable}.
50+
* @return lambda in {@link SerializedLambda} form or null if its function doesn't implement
51+
* Serializable.
52+
*/
53+
public static SerializedLambda toSerializedLambda(Object lambda) {
54+
for (Class<?> cl = lambda.getClass(); cl != null; cl = cl.getSuperclass()) {
55+
try {
56+
Method m = cl.getDeclaredMethod("writeReplace");
57+
m.setAccessible(true);
58+
Object replacement = m.invoke(lambda);
59+
if (!(replacement instanceof SerializedLambda)) break; // custom interface implementation
60+
return (SerializedLambda) replacement;
61+
} catch (NoSuchMethodException e) {
62+
} catch (IllegalAccessException | InvocationTargetException e) {
63+
break;
64+
}
65+
}
66+
return null;
67+
}
68+
69+
/** Prohibits instantiation. */
70+
private LambdaUtils() {}
71+
}

src/main/java/com/uber/cadence/internal/common/Retryer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ private static <R> ValueExceptionPair<R> failOrRetry(
214214
}
215215
int maxAttempts = options.getMaximumAttempts();
216216
if ((maxAttempts > 0 && attempt >= maxAttempts)
217-
|| (elapsed >= options.getExpiration().toMillis()
217+
|| ((options.getExpiration() != null && elapsed >= options.getExpiration().toMillis())
218218
&& attempt >= options.getMinimumAttempts())) {
219219
return new ValueExceptionPair<>(null, e);
220220
}

0 commit comments

Comments
 (0)