Skip to content

Commit

Permalink
IWF-137: Update iwf-idl to latest to allow to use separate persistenc…
Browse files Browse the repository at this point in the history
…y loading policy for waitUntil (#248)
  • Loading branch information
samuel27m authored Oct 21, 2024
1 parent 6bb4a00 commit 4a1ef9f
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 1 deletion.
2 changes: 1 addition & 1 deletion iwf-idl
37 changes: 37 additions & 0 deletions src/test/java/io/iworkflow/integ/StateOptionsTest.java
Original file line number Diff line number Diff line change
@@ -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);
}
}

Original file line number Diff line number Diff line change
@@ -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<PersistenceFieldDef> 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<StateDef> getWorkflowStates() {
return Arrays.asList(
StateDef.startingState(new StateOptionsWorkflowState1()),
StateDef.nonStartingState(new StateOptionsWorkflowState2()),
StateDef.nonStartingState(new StateOptionsWorkflowState3())
);
}
}

class StateOptionsWorkflowState1 implements WorkflowState<Void> {
@Override
public Class<Void> 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<Void> {
@Override
public Class<Void> 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<Void> {
@Override
public Class<Void> 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))
);
}
}

0 comments on commit 4a1ef9f

Please sign in to comment.