55import io .iworkflow .core .ClientOptions ;
66import io .iworkflow .core .ClientSideException ;
77import io .iworkflow .core .ImmutableStopWorkflowOptions ;
8+ import io .iworkflow .core .ImmutableWorkflowOptions ;
89import io .iworkflow .gen .models .ErrorResponse ;
10+ import io .iworkflow .gen .models .WorkflowConfig ;
911import io .iworkflow .gen .models .WorkflowStopType ;
1012import io .iworkflow .integ .persistence .BasicPersistenceWorkflow ;
1113import io .iworkflow .integ .rpc .NoStateWorkflow ;
1719import org .junit .jupiter .api .BeforeEach ;
1820import org .junit .jupiter .api .Test ;
1921
22+ import java .util .ArrayList ;
2023import java .util .Arrays ;
2124import java .util .Map ;
2225import java .util .concurrent .ExecutionException ;
26+ import java .util .concurrent .ExecutorService ;
27+ import java .util .concurrent .Executors ;
28+ import java .util .concurrent .Future ;
2329
2430import static io .iworkflow .integ .persistence .BasicPersistenceWorkflow .TEST_SEARCH_ATTRIBUTE_INT ;
2531import static io .iworkflow .integ .persistence .BasicPersistenceWorkflow .TEST_SEARCH_ATTRIBUTE_KEYWORD ;
@@ -37,6 +43,63 @@ public void setup() throws ExecutionException, InterruptedException {
3743 TestSingletonWorkerService .startWorkerIfNotUp ();
3844 }
3945
46+ @ Test
47+ public void testRPCLocking () throws InterruptedException , ExecutionException {
48+ final Client client = new Client (WorkflowRegistry .registry , ClientOptions .localDefault );
49+ final String wfId = "testRPCLocking" + System .currentTimeMillis () / 1000 ;
50+ client .startWorkflow (
51+ NoStateWorkflow .class , wfId , 1000 , 999 ,
52+ ImmutableWorkflowOptions .builder ()
53+ .workflowConfigOverride (
54+ new WorkflowConfig ()
55+ .continueAsNewThreshold (1 )
56+ )
57+ .build ());
58+
59+ final NoStateWorkflow rpcStub = client .newRpcStub (NoStateWorkflow .class , wfId , "" );
60+
61+ ExecutorService executor = Executors .newFixedThreadPool (10 );
62+ final ArrayList <Future <String >> futures = new ArrayList <>();
63+ int total = 1000 ;
64+ for (int i = 0 ; i < total ; i ++) {
65+
66+ final Future <String > future = executor .submit (() -> {
67+ try {
68+ return client .invokeRPC (rpcStub ::increaseCounter );
69+ } catch (ClientSideException e ) {
70+ if (e .getStatusCode () != 450 ) {
71+ throw e ;
72+ }
73+ }
74+ return "fail" ;
75+ }
76+ );
77+ futures .add (future );
78+ }
79+
80+ int succ = 0 ;
81+ for (int i = 0 ; i < total ; i ++) {
82+ ;
83+ try {
84+ final String done = futures .get (i ).get ();
85+ if (done .equals ("done" )) {
86+ succ ++;
87+ }
88+ } catch (Exception ignored ) {
89+ }
90+ }
91+
92+ Assertions .assertTrue (succ > 0 );
93+ Assertions .assertEquals (succ , client .invokeRPC (rpcStub ::getCounter ));
94+
95+ executor .shutdown ();
96+
97+ // TODO make sure continue as new is happening when no state is executed
98+ // https://github.com/indeedeng/iwf/issues/339
99+
100+ client .stopWorkflow (wfId , null );
101+ }
102+
40103 @ Test
41104 public void testRPCWorkflowFunc1 () throws InterruptedException {
42105 final Client client = new Client (WorkflowRegistry .registry , ClientOptions .localDefault );
0 commit comments