From 4a1ef9f0a27a665009398d0100a1715a668f1840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Ca=C3=A7ador?= Date: Mon, 21 Oct 2024 10:30:15 +0100 Subject: [PATCH] IWF-137: Update iwf-idl to latest to allow to use separate persistency loading policy for waitUntil (#248) --- iwf-idl | 2 +- .../io/iworkflow/integ/StateOptionsTest.java | 37 ++++ .../stateoptions/StateOptionsWorkflow.java | 159 ++++++++++++++++++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 src/test/java/io/iworkflow/integ/StateOptionsTest.java create mode 100644 src/test/java/io/iworkflow/integ/stateoptions/StateOptionsWorkflow.java diff --git a/iwf-idl b/iwf-idl index fdd0d8e..d1da138 160000 --- a/iwf-idl +++ b/iwf-idl @@ -1 +1 @@ -Subproject commit fdd0d8eae1326489e567bf0073263a3f14bad04e +Subproject commit d1da1384bca0c9317b916df3d6bbd3b848dc5150 diff --git a/src/test/java/io/iworkflow/integ/StateOptionsTest.java b/src/test/java/io/iworkflow/integ/StateOptionsTest.java new file mode 100644 index 0000000..e503423 --- /dev/null +++ b/src/test/java/io/iworkflow/integ/StateOptionsTest.java @@ -0,0 +1,37 @@ +package io.iworkflow.integ; + +import io.iworkflow.core.Client; +import io.iworkflow.core.ClientOptions; +import io.iworkflow.core.ImmutableWorkflowOptions; +import io.iworkflow.core.WorkflowOptions; +import io.iworkflow.gen.models.IDReusePolicy; +import io.iworkflow.integ.stateoptions.StateOptionsWorkflow; +import io.iworkflow.spring.TestSingletonWorkerService; +import io.iworkflow.spring.controller.WorkflowRegistry; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +public class StateOptionsTest { + @BeforeEach + public void setup() throws ExecutionException, InterruptedException { + TestSingletonWorkerService.startWorkerIfNotUp(); + } + @Test + public void testStateOptionsWorkflow() { + final Client client = new Client(WorkflowRegistry.registry, ClientOptions.localDefault); + final String wfId = "state-options-test-id" + System.currentTimeMillis() / 1000; + final WorkflowOptions startOptions = ImmutableWorkflowOptions.builder() + .workflowIdReusePolicy(IDReusePolicy.DISALLOW_REUSE) + .build(); + client.startWorkflow(StateOptionsWorkflow.class, wfId, 10, null, startOptions); + // wait for workflow to finish + final String output = client.getSimpleWorkflowResultWithWait(String.class, wfId); + + // If no exception thrown, then the test is successful + Assertions.assertEquals("success", output); + } +} + diff --git a/src/test/java/io/iworkflow/integ/stateoptions/StateOptionsWorkflow.java b/src/test/java/io/iworkflow/integ/stateoptions/StateOptionsWorkflow.java new file mode 100644 index 0000000..b38125d --- /dev/null +++ b/src/test/java/io/iworkflow/integ/stateoptions/StateOptionsWorkflow.java @@ -0,0 +1,159 @@ +package io.iworkflow.integ.stateoptions; + +import io.iworkflow.core.Context; +import io.iworkflow.core.ObjectWorkflow; +import io.iworkflow.core.StateDecision; +import io.iworkflow.core.StateDef; +import io.iworkflow.core.WorkflowState; +import io.iworkflow.core.command.CommandRequest; +import io.iworkflow.core.command.CommandResults; +import io.iworkflow.core.communication.Communication; +import io.iworkflow.core.persistence.DataAttributeDef; +import io.iworkflow.core.persistence.Persistence; +import io.iworkflow.core.persistence.PersistenceFieldDef; +import io.iworkflow.gen.models.PersistenceLoadingPolicy; +import io.iworkflow.gen.models.PersistenceLoadingType; +import io.iworkflow.gen.models.WorkflowStateOptions; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Component +public class StateOptionsWorkflow implements ObjectWorkflow { + public static final String DA_WAIT_UNTIL = "DA_WAIT_UNTIL"; + public static final String DA_EXECUTE = "DA_EXECUTE"; + public static final String DA_BOTH = "DA_BOTH"; + + @Override + public List getPersistenceSchema() { + return Arrays.asList( + DataAttributeDef.create(String.class, DA_WAIT_UNTIL), + DataAttributeDef.create(String.class, DA_EXECUTE), + DataAttributeDef.create(String.class, DA_BOTH) + ); + } + + @Override + public List getWorkflowStates() { + return Arrays.asList( + StateDef.startingState(new StateOptionsWorkflowState1()), + StateDef.nonStartingState(new StateOptionsWorkflowState2()), + StateDef.nonStartingState(new StateOptionsWorkflowState3()) + ); + } +} + +class StateOptionsWorkflowState1 implements WorkflowState { + @Override + public Class getInputType() { + return Void.class; + } + + @Override + public CommandRequest waitUntil(final Context context, final Void input, Persistence persistence, final Communication communication) { + return CommandRequest.empty; + } + + @Override + public StateDecision execute(final Context context, final Void input, final CommandResults commandResults, Persistence persistence, final Communication communication) { + persistence.setDataAttribute(StateOptionsWorkflow.DA_EXECUTE, "execute"); + persistence.setDataAttribute(StateOptionsWorkflow.DA_WAIT_UNTIL, "wait_until"); + persistence.setDataAttribute(StateOptionsWorkflow.DA_BOTH, "both"); + + return StateDecision.singleNextState(StateOptionsWorkflowState2.class); + } +} + +class StateOptionsWorkflowState2 implements WorkflowState { + @Override + public Class getInputType() { + return Void.class; + } + + @Override + public CommandRequest waitUntil(final Context context, final Void input, Persistence persistence, final Communication communication) { + final String daWaitUntil = persistence.getDataAttribute(StateOptionsWorkflow.DA_WAIT_UNTIL, String.class); + + if (!daWaitUntil.equals("wait_until")) { + throw new RuntimeException("Expected DA_WAIT_UNTIL to be 'wait_until', got " + daWaitUntil); + } + + final String daExecute = persistence.getDataAttribute(StateOptionsWorkflow.DA_EXECUTE, String.class); + if (daExecute != null) { + throw new RuntimeException("Expected DA_EXECUTE to be null, got " + daExecute); + } + + return CommandRequest.empty; + } + + @Override + public StateDecision execute(final Context context, final Void input, final CommandResults commandResults, Persistence persistence, final Communication communication) { + final String daExecute = persistence.getDataAttribute(StateOptionsWorkflow.DA_EXECUTE, String.class); + + if (!daExecute.equals("execute")) { + throw new RuntimeException("Expected DA_EXECUTE to be 'execute', got " + daExecute); + } + + final String daWaitUntil = persistence.getDataAttribute(StateOptionsWorkflow.DA_WAIT_UNTIL, String.class); + if (daWaitUntil != null) { + throw new RuntimeException("Expected DA_WAIT_UNTIL to be null, got " + daWaitUntil); + } + + return StateDecision.singleNextState(StateOptionsWorkflowState3.class); + } + + @Override + public WorkflowStateOptions getStateOptions() { + return new WorkflowStateOptions() + .waitUntilApiDataAttributesLoadingPolicy( + new PersistenceLoadingPolicy() + .persistenceLoadingType(PersistenceLoadingType.PARTIAL_WITH_EXCLUSIVE_LOCK) + .partialLoadingKeys(Collections.singletonList(StateOptionsWorkflow.DA_WAIT_UNTIL)) + ) + .executeApiDataAttributesLoadingPolicy( + new PersistenceLoadingPolicy() + .persistenceLoadingType(PersistenceLoadingType.PARTIAL_WITH_EXCLUSIVE_LOCK) + .partialLoadingKeys(Collections.singletonList(StateOptionsWorkflow.DA_EXECUTE))); + } +} + +class StateOptionsWorkflowState3 implements WorkflowState { + @Override + public Class getInputType() { + return Void.class; + } + + @Override + public CommandRequest waitUntil(final Context context, final Void input, Persistence persistence, final Communication communication) { + final String str = persistence.getDataAttribute(StateOptionsWorkflow.DA_BOTH, String.class); + + if (!str.equals("both")) { + throw new RuntimeException("Expected DA_BOTH to be 'both', got " + str); + } + + return CommandRequest.empty; + } + + @Override + public StateDecision execute(final Context context, final Void input, final CommandResults commandResults, Persistence persistence, final Communication communication) { + final String str = persistence.getDataAttribute(StateOptionsWorkflow.DA_BOTH, String.class); + + if (!str.equals("both")) { + throw new RuntimeException("Expected DA_BOTH to be 'both', got " + str); + } + + return StateDecision.gracefulCompleteWorkflow("success"); + } + + @Override + public WorkflowStateOptions getStateOptions() { + return new WorkflowStateOptions() + .dataAttributesLoadingPolicy( + new PersistenceLoadingPolicy() + .persistenceLoadingType(PersistenceLoadingType.PARTIAL_WITH_EXCLUSIVE_LOCK) + .partialLoadingKeys(Collections.singletonList(StateOptionsWorkflow.DA_BOTH)) + ); + } +} \ No newline at end of file