|
22 | 22 | import com.uber.cadence.DomainAlreadyExistsError;
|
23 | 23 | import com.uber.cadence.RegisterDomainRequest;
|
24 | 24 | import com.uber.cadence.activity.ActivityMethod;
|
| 25 | +import com.uber.cadence.activity.ActivityOptions; |
25 | 26 | import com.uber.cadence.client.*;
|
| 27 | +import com.uber.cadence.common.RetryOptions; |
26 | 28 | import com.uber.cadence.internal.compatibility.Thrift2ProtoAdapter;
|
27 | 29 | import com.uber.cadence.internal.compatibility.proto.serviceclient.IGrpcServiceStubs;
|
28 | 30 | import com.uber.cadence.serviceclient.ClientOptions;
|
|
41 | 43 | import io.opentracing.mock.MockSpan;
|
42 | 44 | import io.opentracing.mock.MockTracer;
|
43 | 45 | import java.time.Duration;
|
44 |
| -import java.util.List; |
45 |
| -import java.util.Objects; |
| 46 | +import java.util.*; |
| 47 | +import java.util.concurrent.CompletableFuture; |
46 | 48 | import java.util.stream.Collectors;
|
47 | 49 | import org.junit.Assume;
|
48 | 50 | import org.junit.Test;
|
@@ -108,7 +110,16 @@ public Integer Double(Integer i) {
|
108 | 110 | }
|
109 | 111 |
|
110 | 112 | public static class TestWorkflowImpl implements TestWorkflow {
|
111 |
| - private final TestActivity activities = Workflow.newActivityStub(TestActivity.class); |
| 113 | + private final TestActivity activities = |
| 114 | + Workflow.newActivityStub( |
| 115 | + TestActivity.class, |
| 116 | + new ActivityOptions.Builder() |
| 117 | + .setRetryOptions( |
| 118 | + new RetryOptions.Builder() |
| 119 | + .setInitialInterval(Duration.ofSeconds(10)) |
| 120 | + .setMaximumAttempts(2) |
| 121 | + .build()) |
| 122 | + .build()); |
112 | 123 |
|
113 | 124 | @Override
|
114 | 125 | public Integer AddOneThenDouble(Integer n) {
|
@@ -153,6 +164,85 @@ public void testStartWorkflowGRPC() {
|
153 | 164 | testStartWorkflowHelper(service, mockTracer, true);
|
154 | 165 | }
|
155 | 166 |
|
| 167 | + @Test |
| 168 | + public void testStartMultipleWorkflowGRPC() { |
| 169 | + Assume.assumeTrue(useDockerService); |
| 170 | + MockTracer mockTracer = new MockTracer(); |
| 171 | + IWorkflowService service = |
| 172 | + new Thrift2ProtoAdapter( |
| 173 | + IGrpcServiceStubs.newInstance( |
| 174 | + ClientOptions.newBuilder().setTracer(mockTracer).setPort(7833).build())); |
| 175 | + try { |
| 176 | + service.RegisterDomain(new RegisterDomainRequest().setName(DOMAIN)); |
| 177 | + } catch (DomainAlreadyExistsError e) { |
| 178 | + logger.info("domain already registered"); |
| 179 | + } catch (Exception e) { |
| 180 | + fail("fail to register domain: " + e); |
| 181 | + } |
| 182 | + |
| 183 | + WorkflowClient client = |
| 184 | + WorkflowClient.newInstance( |
| 185 | + service, WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build()); |
| 186 | + |
| 187 | + WorkerFactory workerFactory = |
| 188 | + WorkerFactory.newInstance( |
| 189 | + client, WorkerFactoryOptions.newBuilder().setMaxWorkflowThreadCount(2).build()); |
| 190 | + Worker worker; |
| 191 | + worker = |
| 192 | + workerFactory.newWorker( |
| 193 | + TASK_LIST, WorkerOptions.newBuilder().setMaxConcurrentWorkflowExecutionSize(2).build()); |
| 194 | + worker.registerActivitiesImplementations(new TestActivityImpl(mockTracer, true)); |
| 195 | + worker.registerWorkflowImplementationTypes(TestWorkflowImpl.class, DoubleWorkflowImpl.class); |
| 196 | + workerFactory.start(); |
| 197 | + |
| 198 | + List<CompletableFuture<Void>> futures = new ArrayList<>(); |
| 199 | + |
| 200 | + for (int i = 0; i < 100; i++) { |
| 201 | + int finalI = i; |
| 202 | + futures.add( |
| 203 | + CompletableFuture.runAsync( |
| 204 | + () -> { |
| 205 | + Span rootSpan = mockTracer.buildSpan("workflow=" + finalI).start(); |
| 206 | + rootSpan.setBaggageItem(CONTEXT_KEY, CONTEXT_VALUE); |
| 207 | + mockTracer.activateSpan(rootSpan); |
| 208 | + client.newWorkflowStub(TestWorkflow.class).AddOneThenDouble(finalI); |
| 209 | + rootSpan.finish(); |
| 210 | + })); |
| 211 | + } |
| 212 | + try { |
| 213 | + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(); |
| 214 | + } catch (Exception e) { |
| 215 | + fail("workflow failure: " + e); |
| 216 | + } finally { |
| 217 | + // test debug log |
| 218 | + StringBuilder sb = new StringBuilder(); |
| 219 | + |
| 220 | + List<MockSpan> spans = mockTracer.finishedSpans(); |
| 221 | + spans.forEach( |
| 222 | + span -> { |
| 223 | + sb.append(span.toString()).append("\n"); |
| 224 | + }); |
| 225 | + logger.info("spans: " + sb); |
| 226 | + workerFactory.shutdown(); |
| 227 | + |
| 228 | + // assert activity span should have only 1 parent |
| 229 | + List<MockSpan> filtered = |
| 230 | + spans |
| 231 | + .stream() |
| 232 | + .filter( |
| 233 | + s -> |
| 234 | + s.operationName().contains("ExecuteActivity") |
| 235 | + || s.operationName().contains("ExecuteLocalActivity") |
| 236 | + || s.operationName().contains("ExecuteWorkflow")) |
| 237 | + .collect(Collectors.toList()); |
| 238 | + assertFalse(filtered.isEmpty()); |
| 239 | + filtered.forEach( |
| 240 | + s -> { |
| 241 | + assertEquals(1, s.references().size()); |
| 242 | + }); |
| 243 | + } |
| 244 | + } |
| 245 | + |
156 | 246 | @Test
|
157 | 247 | public void testSignalWithStartWorkflowTchannel() {
|
158 | 248 | Assume.assumeTrue(useDockerService);
|
|
0 commit comments