-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add and improve handling workflow uncompleted status return (#132)
- Loading branch information
1 parent
ae0386b
commit 2ec5b62
Showing
14 changed files
with
452 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule iwf-idl
updated
from d2a70a to 516ea1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
src/main/java/io/iworkflow/core/WorkflowUncompletedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package io.iworkflow.core; | ||
|
||
import io.iworkflow.gen.models.StateCompletionOutput; | ||
import io.iworkflow.gen.models.WorkflowErrorType; | ||
import io.iworkflow.gen.models.WorkflowStatus; | ||
|
||
import java.util.List; | ||
|
||
public class WorkflowUncompletedException extends RuntimeException { | ||
private final String runId; | ||
private final WorkflowStatus closedStatus; | ||
private final WorkflowErrorType errorType; | ||
private final String errorMessage; | ||
private final List<StateCompletionOutput> stateResults; | ||
private final ObjectEncoder encoder; | ||
|
||
public WorkflowUncompletedException( | ||
final String runId, final WorkflowStatus closedStatus, final WorkflowErrorType errorType, final String errorMessage, | ||
final List<StateCompletionOutput> stateResults, final ObjectEncoder encoder) { | ||
this.runId = runId; | ||
this.closedStatus = closedStatus; | ||
this.errorType = errorType; | ||
this.errorMessage = errorMessage; | ||
this.stateResults = stateResults; | ||
this.encoder = encoder; | ||
} | ||
|
||
public String getRunId() { | ||
return runId; | ||
} | ||
|
||
public WorkflowStatus getClosedStatus() { | ||
return closedStatus; | ||
} | ||
|
||
// Today, this only applies to FAILED as closedStatus to differentiate different failed types | ||
public WorkflowErrorType getErrorSubType() { | ||
return errorType; | ||
} | ||
|
||
public String getErrorMessage() { | ||
return errorMessage; | ||
} | ||
|
||
public int getStateResultsSize() { | ||
if (stateResults == null) { | ||
return 0; | ||
} | ||
return stateResults.size(); | ||
} | ||
|
||
public <T> T getStateResult(final int index, Class<T> type) { | ||
final StateCompletionOutput output = stateResults.get(index); | ||
return encoder.decode(output.getCompletedStateOutput(), type); | ||
} | ||
|
||
} |
144 changes: 144 additions & 0 deletions
144
src/test/java/io/iworkflow/integ/WorkflowUncompletedTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package io.iworkflow.integ; | ||
|
||
import io.iworkflow.core.Client; | ||
import io.iworkflow.core.ClientOptions; | ||
import io.iworkflow.core.WorkflowUncompletedException; | ||
import io.iworkflow.gen.models.WorkflowErrorType; | ||
import io.iworkflow.gen.models.WorkflowStatus; | ||
import io.iworkflow.integ.forcefail.ForceFailWorkflow; | ||
import io.iworkflow.integ.signal.BasicSignalWorkflow; | ||
import io.iworkflow.integ.stateapifail.StateApiFailWorkflow; | ||
import io.iworkflow.integ.stateapitimeout.StateApiTimeoutFailWorkflow; | ||
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 WorkflowUncompletedTest { | ||
|
||
@BeforeEach | ||
public void setup() throws ExecutionException, InterruptedException { | ||
TestSingletonWorkerService.startWorkerIfNotUp(); | ||
} | ||
|
||
@Test | ||
public void testWorkflowTimeout() throws InterruptedException { | ||
final Client client = new Client(WorkflowRegistry.registry, ClientOptions.localDefault); | ||
final String wfId = "testWorkflowTimeout" + System.currentTimeMillis() / 1000; | ||
final Integer input = 1; | ||
final String runId = client.startWorkflow( | ||
BasicSignalWorkflow.class, wfId, 1, input); | ||
|
||
try { | ||
client.getSimpleWorkflowResultWithWait(Integer.class, wfId); | ||
} catch (WorkflowUncompletedException e) { | ||
Assertions.assertEquals(runId, e.getRunId()); | ||
Assertions.assertEquals(WorkflowStatus.TIMEOUT, e.getClosedStatus()); | ||
Assertions.assertNull(e.getErrorSubType()); | ||
Assertions.assertNull(e.getErrorMessage()); | ||
Assertions.assertEquals(0, e.getStateResultsSize()); | ||
return; | ||
} | ||
Assertions.fail("no exception caught"); | ||
} | ||
|
||
@Test | ||
public void testWorkflowCanceled() throws InterruptedException { | ||
final Client client = new Client(WorkflowRegistry.registry, ClientOptions.localDefault); | ||
final String wfId = "testWorkflowTimeout" + System.currentTimeMillis() / 1000; | ||
final Integer input = 1; | ||
final String runId = client.startWorkflow( | ||
BasicSignalWorkflow.class, wfId, 10, input); | ||
|
||
client.stopWorkflow(wfId, ""); | ||
|
||
try { | ||
client.getSimpleWorkflowResultWithWait(Integer.class, wfId); | ||
} catch (WorkflowUncompletedException e) { | ||
Assertions.assertEquals(runId, e.getRunId()); | ||
Assertions.assertEquals(WorkflowStatus.CANCELED, e.getClosedStatus()); | ||
Assertions.assertNull(e.getErrorSubType()); | ||
Assertions.assertNull(e.getErrorMessage()); | ||
Assertions.assertEquals(0, e.getStateResultsSize()); | ||
return; | ||
} | ||
Assertions.fail("no exception caught"); | ||
} | ||
|
||
@Test | ||
public void testForceFailWorkflow() throws InterruptedException { | ||
final Client client = new Client(WorkflowRegistry.registry, ClientOptions.localDefault); | ||
final long startTs = System.currentTimeMillis(); | ||
final String wfId = "testForceFailWorkflow" + startTs / 1000; | ||
final Integer input = 5; | ||
|
||
final String runId = client.startWorkflow( | ||
ForceFailWorkflow.class, wfId, 10, input); | ||
|
||
try { | ||
client.getSimpleWorkflowResultWithWait(Integer.class, wfId); | ||
} catch (WorkflowUncompletedException e) { | ||
Assertions.assertEquals(runId, e.getRunId()); | ||
Assertions.assertEquals(WorkflowStatus.FAILED, e.getClosedStatus()); | ||
Assertions.assertEquals(WorkflowErrorType.STATE_DECISION_FAILING_WORKFLOW_ERROR_TYPE, e.getErrorSubType()); | ||
Assertions.assertNull(e.getErrorMessage()); | ||
Assertions.assertEquals(1, e.getStateResultsSize()); | ||
String out = e.getStateResult(0, String.class); | ||
Assertions.assertEquals("a failing message", out); | ||
return; | ||
} | ||
Assertions.fail("no exception caught"); | ||
} | ||
|
||
@Test | ||
public void testStateApiFailWorkflow() throws InterruptedException { | ||
final Client client = new Client(WorkflowRegistry.registry, ClientOptions.localDefault); | ||
final long startTs = System.currentTimeMillis(); | ||
final String wfId = "testStateApiFailWorkflow" + startTs / 1000; | ||
final Integer input = 5; | ||
|
||
final String runId = client.startWorkflow( | ||
StateApiFailWorkflow.class, wfId, 10, input); | ||
|
||
try { | ||
client.getSimpleWorkflowResultWithWait(Integer.class, wfId); | ||
} catch (WorkflowUncompletedException e) { | ||
Assertions.assertEquals(runId, e.getRunId()); | ||
Assertions.assertEquals(WorkflowStatus.FAILED, e.getClosedStatus()); | ||
Assertions.assertEquals(WorkflowErrorType.STATE_API_FAIL_MAX_OUT_RETRY_ERROR_TYPE, e.getErrorSubType()); | ||
Assertions.assertTrue(e.getErrorMessage().contains("/api/v1/workflowState/decide")); | ||
Assertions.assertEquals(0, e.getStateResultsSize()); | ||
return; | ||
} | ||
Assertions.fail("no exception caught"); | ||
} | ||
|
||
@Test | ||
public void testStateApiTimeoutWorkflow() throws InterruptedException { | ||
final Client client = new Client(WorkflowRegistry.registry, ClientOptions.localDefault); | ||
final long startTs = System.currentTimeMillis(); | ||
final String wfId = "testStateApiTimeoutWorkflow" + startTs / 1000; | ||
final Integer input = 5; | ||
|
||
final String runId = client.startWorkflow( | ||
StateApiTimeoutFailWorkflow.class, wfId, 10, input); | ||
|
||
try { | ||
client.getSimpleWorkflowResultWithWait(Integer.class, wfId); | ||
} catch (WorkflowUncompletedException e) { | ||
Assertions.assertEquals(runId, e.getRunId()); | ||
Assertions.assertEquals(WorkflowStatus.FAILED, e.getClosedStatus()); | ||
Assertions.assertEquals(WorkflowErrorType.STATE_API_FAIL_MAX_OUT_RETRY_ERROR_TYPE, e.getErrorSubType()); | ||
Assertions.assertTrue( | ||
e.getErrorMessage().contains("activity StartToClose timeout"), | ||
e.getErrorMessage() | ||
); | ||
Assertions.assertEquals(0, e.getStateResultsSize()); | ||
return; | ||
} | ||
Assertions.fail("no exception caught"); | ||
} | ||
} |
Oops, something went wrong.