diff --git a/src/main/idls b/src/main/idls index f5ac3a987..0e56e5790 160000 --- a/src/main/idls +++ b/src/main/idls @@ -1 +1 @@ -Subproject commit f5ac3a987dcaf996cf44c72064195faf76c381f3 +Subproject commit 0e56e57909d9fa738eaa8d7a9561ea16acdf51e4 diff --git a/src/main/java/com/uber/cadence/client/WorkflowOptions.java b/src/main/java/com/uber/cadence/client/WorkflowOptions.java index 42260a4a7..73e0c6b4e 100644 --- a/src/main/java/com/uber/cadence/client/WorkflowOptions.java +++ b/src/main/java/com/uber/cadence/client/WorkflowOptions.java @@ -25,6 +25,7 @@ import com.cronutils.model.definition.CronDefinitionBuilder; import com.cronutils.parser.CronParser; import com.google.common.base.Strings; +import com.uber.cadence.CronOverlapPolicy; import com.uber.cadence.WorkflowIdReusePolicy; import com.uber.cadence.common.CronSchedule; import com.uber.cadence.common.MethodRetry; @@ -64,6 +65,7 @@ public static WorkflowOptions merge( .setRetryOptions(RetryOptions.merge(methodRetry, o.getRetryOptions())) .setCronSchedule(OptionsUtils.merge(cronAnnotation, o.getCronSchedule(), String.class)) .setMemo(o.getMemo()) + .setCronOverlapPolicy(o.getCronOverlapPolicy()) .setSearchAttributes(o.getSearchAttributes()) .setContextPropagators(o.getContextPropagators()) .setDelayStart(o.delayStart) @@ -86,6 +88,8 @@ public static final class Builder { private String cronSchedule; + private CronOverlapPolicy cronOverlapPolicy; + private Map memo; private Map searchAttributes; @@ -107,6 +111,7 @@ public Builder(WorkflowOptions o) { this.taskList = o.taskList; this.retryOptions = o.retryOptions; this.cronSchedule = o.cronSchedule; + this.cronOverlapPolicy = o.cronOverlapPolicy; this.memo = o.memo; this.searchAttributes = o.searchAttributes; this.contextPropagators = o.contextPropagators; @@ -194,6 +199,11 @@ public Builder setCronSchedule(String cronSchedule) { return this; } + public Builder setCronOverlapPolicy(CronOverlapPolicy cronOverlapPolicy) { + this.cronOverlapPolicy = cronOverlapPolicy; + return this; + } + /** * Specifies additional non-indexed information in result of list workflow. The type of value * can be any object that are serializable by {@link com.uber.cadence.converter.DataConverter} @@ -235,7 +245,8 @@ public WorkflowOptions build() { memo, searchAttributes, contextPropagators, - delayStart); + delayStart, + cronOverlapPolicy); } /** @@ -290,7 +301,8 @@ public WorkflowOptions validateBuildWithDefaults() { memo, searchAttributes, contextPropagators, - delayStart); + delayStart, + cronOverlapPolicy); } } @@ -308,6 +320,8 @@ public WorkflowOptions validateBuildWithDefaults() { private String cronSchedule; + private CronOverlapPolicy cronOverlapPolicy; + private Map memo; private Map searchAttributes; @@ -327,7 +341,8 @@ private WorkflowOptions( Map memo, Map searchAttributes, List contextPropagators, - Duration delayStart) { + Duration delayStart, + CronOverlapPolicy cronOverlapPolicy) { this.workflowId = workflowId; this.workflowIdReusePolicy = workflowIdReusePolicy; this.executionStartToCloseTimeout = executionStartToCloseTimeout; @@ -339,6 +354,7 @@ private WorkflowOptions( this.searchAttributes = searchAttributes; this.contextPropagators = contextPropagators; this.delayStart = delayStart; + this.cronOverlapPolicy = cronOverlapPolicy; } public String getWorkflowId() { @@ -369,6 +385,10 @@ public String getCronSchedule() { return cronSchedule; } + public CronOverlapPolicy getCronOverlapPolicy() { + return cronOverlapPolicy; + } + public Map getMemo() { return memo; } @@ -397,6 +417,7 @@ public boolean equals(Object o) { && Objects.equals(taskList, that.taskList) && Objects.equals(retryOptions, that.retryOptions) && Objects.equals(cronSchedule, that.cronSchedule) + && cronOverlapPolicy == that.cronOverlapPolicy && Objects.equals(memo, that.memo) && Objects.equals(searchAttributes, that.searchAttributes) && Objects.equals(contextPropagators, that.contextPropagators) @@ -413,6 +434,7 @@ public int hashCode() { taskList, retryOptions, cronSchedule, + cronOverlapPolicy, memo, searchAttributes, contextPropagators, @@ -439,6 +461,8 @@ public String toString() { + ", cronSchedule='" + cronSchedule + '\'' + + ", cronOverlapPolicy=" + + cronOverlapPolicy + ", memo='" + memo + '\'' diff --git a/src/main/java/com/uber/cadence/internal/common/StartWorkflowExecutionParameters.java b/src/main/java/com/uber/cadence/internal/common/StartWorkflowExecutionParameters.java index 9171c2740..c057eb5cb 100644 --- a/src/main/java/com/uber/cadence/internal/common/StartWorkflowExecutionParameters.java +++ b/src/main/java/com/uber/cadence/internal/common/StartWorkflowExecutionParameters.java @@ -17,6 +17,7 @@ package com.uber.cadence.internal.common; +import com.uber.cadence.CronOverlapPolicy; import com.uber.cadence.WorkflowIdReusePolicy; import com.uber.cadence.WorkflowType; import com.uber.cadence.client.WorkflowOptions; @@ -56,6 +57,8 @@ public final class StartWorkflowExecutionParameters { private Duration delayStart; + private CronOverlapPolicy cronOverlapPolicy; + /** * Returns the value of the WorkflowId property for this object. * @@ -317,6 +320,20 @@ public Duration getDelayStart() { return delayStart; } + public CronOverlapPolicy getCronOverlapPolicy() { + return cronOverlapPolicy; + } + + public void setCronOverlapPolicy(CronOverlapPolicy cronOverlapPolicy) { + this.cronOverlapPolicy = cronOverlapPolicy; + } + + public StartWorkflowExecutionParameters withCronOverlapPolicy( + CronOverlapPolicy cronOverlapPolicy) { + this.cronOverlapPolicy = cronOverlapPolicy; + return this; + } + public StartWorkflowExecutionParameters withRetryParameters(RetryParameters retryParameters) { this.retryParameters = retryParameters; return this; @@ -352,6 +369,7 @@ public static StartWorkflowExecutionParameters fromWorkflowOptions(WorkflowOptio if (options.getCronSchedule() != null) { parameters.setCronSchedule(options.getCronSchedule()); } + parameters.setCronOverlapPolicy(options.getCronOverlapPolicy()); return parameters; } @@ -386,6 +404,8 @@ public String toString() { + ", cronSchedule='" + cronSchedule + '\'' + + ", cronOverlapPolicy=" + + cronOverlapPolicy + ", memo='" + memo + '\'' @@ -413,6 +433,7 @@ public boolean equals(Object o) { && workflowIdReusePolicy == that.workflowIdReusePolicy && Objects.equals(retryParameters, that.retryParameters) && Objects.equals(cronSchedule, that.cronSchedule) + && cronOverlapPolicy == that.cronOverlapPolicy && Objects.equals(memo, that.memo) && Objects.equals(searchAttributes, that.searchAttributes) && Objects.equals(context, that.context) @@ -431,6 +452,7 @@ public int hashCode() { workflowIdReusePolicy, retryParameters, cronSchedule, + cronOverlapPolicy, memo, searchAttributes, context, @@ -452,6 +474,7 @@ public StartWorkflowExecutionParameters copy() { result.setRetryParameters(retryParameters.copy()); } result.setCronSchedule(cronSchedule); + result.setCronOverlapPolicy(cronOverlapPolicy); result.setMemo(memo); result.setSearchAttributes(searchAttributes); result.setContext(context); diff --git a/src/main/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParameters.java b/src/main/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParameters.java index 5758ff905..48360c7b3 100644 --- a/src/main/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParameters.java +++ b/src/main/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParameters.java @@ -17,6 +17,7 @@ package com.uber.cadence.internal.replay; +import com.uber.cadence.CronOverlapPolicy; import com.uber.cadence.ParentClosePolicy; import com.uber.cadence.WorkflowIdReusePolicy; import com.uber.cadence.WorkflowType; @@ -51,6 +52,8 @@ public static final class Builder { private String cronSchedule; + private CronOverlapPolicy cronOverlapPolicy; + private Map memo; private Map searchAttributes; @@ -115,6 +118,11 @@ public Builder setCronSchedule(String cronSchedule) { return this; } + public Builder setCronOverlapPolicy(CronOverlapPolicy cronOverlapPolicy) { + this.cronOverlapPolicy = cronOverlapPolicy; + return this; + } + public Builder setMemo(Map memo) { this.memo = memo; return this; @@ -148,6 +156,7 @@ public StartChildWorkflowExecutionParameters build() { workflowIdReusePolicy, retryParameters, cronSchedule, + cronOverlapPolicy, memo, searchAttributes, context, @@ -177,6 +186,8 @@ public StartChildWorkflowExecutionParameters build() { private final String cronSchedule; + private final CronOverlapPolicy cronOverlapPolicy; + private Map memo; private Map searchAttributes; @@ -197,6 +208,7 @@ private StartChildWorkflowExecutionParameters( WorkflowIdReusePolicy workflowIdReusePolicy, RetryParameters retryParameters, String cronSchedule, + CronOverlapPolicy cronOverlapPolicy, Map memo, Map searchAttributes, Map context, @@ -212,6 +224,7 @@ private StartChildWorkflowExecutionParameters( this.workflowIdReusePolicy = workflowIdReusePolicy; this.retryParameters = retryParameters; this.cronSchedule = cronSchedule; + this.cronOverlapPolicy = cronOverlapPolicy; this.memo = memo; this.searchAttributes = searchAttributes; this.context = context; @@ -262,6 +275,10 @@ public String getCronSchedule() { return cronSchedule; } + public CronOverlapPolicy getCronOverlapPolicy() { + return cronOverlapPolicy; + } + public Map getMemo() { return memo; } @@ -278,6 +295,28 @@ public ParentClosePolicy getParentClosePolicy() { return parentClosePolicy; } + public StartChildWorkflowExecutionParameters copy() { + StartChildWorkflowExecutionParameters result = + new StartChildWorkflowExecutionParameters( + domain, + input, + control, + executionStartToCloseTimeoutSeconds, + taskList, + taskStartToCloseTimeoutSeconds, + workflowId, + workflowType, + workflowIdReusePolicy, + retryParameters, + cronSchedule, + cronOverlapPolicy, + memo, + searchAttributes, + context, + parentClosePolicy); + return result; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -286,18 +325,19 @@ public boolean equals(Object o) { return executionStartToCloseTimeoutSeconds == that.executionStartToCloseTimeoutSeconds && taskStartToCloseTimeoutSeconds == that.taskStartToCloseTimeoutSeconds && Objects.equals(domain, that.domain) - && Objects.equals(control, that.control) && Arrays.equals(input, that.input) + && Objects.equals(control, that.control) && Objects.equals(taskList, that.taskList) && Objects.equals(workflowId, that.workflowId) && Objects.equals(workflowType, that.workflowType) && workflowIdReusePolicy == that.workflowIdReusePolicy && Objects.equals(retryParameters, that.retryParameters) && Objects.equals(cronSchedule, that.cronSchedule) + && cronOverlapPolicy == that.cronOverlapPolicy && Objects.equals(memo, that.memo) && Objects.equals(searchAttributes, that.searchAttributes) && Objects.equals(context, that.context) - && Objects.equals(parentClosePolicy, that.parentClosePolicy); + && parentClosePolicy == that.parentClosePolicy; } @Override @@ -314,6 +354,7 @@ public int hashCode() { workflowIdReusePolicy, retryParameters, cronSchedule, + cronOverlapPolicy, memo, searchAttributes, context, @@ -349,13 +390,16 @@ public String toString() { + workflowIdReusePolicy + ", retryParameters=" + retryParameters - + ", cronSchedule=" + + ", cronSchedule='" + cronSchedule + + '\'' + + ", cronOverlapPolicy=" + + cronOverlapPolicy + ", memo=" + memo + ", searchAttributes=" + searchAttributes - + ", context='" + + ", context=" + context + ", parentClosePolicy=" + parentClosePolicy diff --git a/src/main/java/com/uber/cadence/internal/sync/SyncDecisionContext.java b/src/main/java/com/uber/cadence/internal/sync/SyncDecisionContext.java index c204ff22a..f6d5b9585 100644 --- a/src/main/java/com/uber/cadence/internal/sync/SyncDecisionContext.java +++ b/src/main/java/com/uber/cadence/internal/sync/SyncDecisionContext.java @@ -460,6 +460,7 @@ private Promise executeChildWorkflowOnce( .setWorkflowIdReusePolicy(options.getWorkflowIdReusePolicy()) .setRetryParameters(retryParameters) .setCronSchedule(options.getCronSchedule()) + .setCronOverlapPolicy(options.getCronOverlapPolicy()) .setMemo(options.getMemo()) .setSearchAttributes(options.getSearchAttributes()) .setContext(extractContextsAndConvertToBytes(propagators)) diff --git a/src/main/java/com/uber/cadence/workflow/ChildWorkflowOptions.java b/src/main/java/com/uber/cadence/workflow/ChildWorkflowOptions.java index 53e09a6d9..e82eb6f3d 100644 --- a/src/main/java/com/uber/cadence/workflow/ChildWorkflowOptions.java +++ b/src/main/java/com/uber/cadence/workflow/ChildWorkflowOptions.java @@ -19,6 +19,7 @@ import static com.uber.cadence.internal.common.OptionsUtils.roundUpToSeconds; +import com.uber.cadence.CronOverlapPolicy; import com.uber.cadence.ParentClosePolicy; import com.uber.cadence.WorkflowIdReusePolicy; import com.uber.cadence.common.CronSchedule; @@ -56,6 +57,7 @@ public static ChildWorkflowOptions merge( .setTaskList(OptionsUtils.merge(a.taskList(), o.getTaskList(), String.class)) .setRetryOptions(RetryOptions.merge(r, o.getRetryOptions())) .setCronSchedule(OptionsUtils.merge(cronAnnotation, o.getCronSchedule(), String.class)) + .setCronOverlapPolicy(o.getCronOverlapPolicy()) .setParentClosePolicy(o.getParentClosePolicy()) .setMemo(o.getMemo()) .setSearchAttributes(o.getSearchAttributes()) @@ -81,6 +83,8 @@ public static final class Builder { private String cronSchedule; + private CronOverlapPolicy cronOverlapPolicy; + private ParentClosePolicy parentClosePolicy; private Map memo; @@ -103,6 +107,7 @@ public Builder(ChildWorkflowOptions source) { this.taskList = source.getTaskList(); this.retryOptions = source.getRetryOptions(); this.cronSchedule = source.getCronSchedule(); + this.cronOverlapPolicy = source.getCronOverlapPolicy(); this.parentClosePolicy = source.getParentClosePolicy(); this.memo = source.getMemo(); this.searchAttributes = source.getSearchAttributes(); @@ -199,6 +204,11 @@ public Builder setCronSchedule(String cronSchedule) { return this; } + public Builder setCronOverlapPolicy(CronOverlapPolicy cronOverlapPolicy) { + this.cronOverlapPolicy = cronOverlapPolicy; + return this; + } + /** Specifies how this workflow reacts to the death of the parent workflow. */ public Builder setParentClosePolicy(ParentClosePolicy parentClosePolicy) { this.parentClosePolicy = parentClosePolicy; @@ -233,6 +243,7 @@ public ChildWorkflowOptions build() { taskList, retryOptions, cronSchedule, + cronOverlapPolicy, parentClosePolicy, memo, searchAttributes, @@ -249,6 +260,7 @@ public ChildWorkflowOptions validateAndBuildWithDefaults() { taskList, retryOptions, cronSchedule, + cronOverlapPolicy, parentClosePolicy, memo, searchAttributes, @@ -272,6 +284,8 @@ public ChildWorkflowOptions validateAndBuildWithDefaults() { private final String cronSchedule; + private final CronOverlapPolicy cronOverlapPolicy; + private final ParentClosePolicy parentClosePolicy; private final Map memo; @@ -289,6 +303,7 @@ private ChildWorkflowOptions( String taskList, RetryOptions retryOptions, String cronSchedule, + CronOverlapPolicy cronOverlapPolicy, ParentClosePolicy parentClosePolicy, Map memo, Map searchAttributes, @@ -301,6 +316,7 @@ private ChildWorkflowOptions( this.taskList = taskList; this.retryOptions = retryOptions; this.cronSchedule = cronSchedule; + this.cronOverlapPolicy = cronOverlapPolicy; this.parentClosePolicy = parentClosePolicy; this.memo = memo; this.searchAttributes = searchAttributes; @@ -339,6 +355,10 @@ public String getCronSchedule() { return cronSchedule; } + public CronOverlapPolicy getCronOverlapPolicy() { + return cronOverlapPolicy; + } + public ParentClosePolicy getParentClosePolicy() { return parentClosePolicy; } @@ -369,6 +389,7 @@ public boolean equals(Object o) { && Objects.equals(taskList, that.taskList) && Objects.equals(retryOptions, that.retryOptions) && Objects.equals(cronSchedule, that.cronSchedule) + && cronOverlapPolicy == that.cronOverlapPolicy && Objects.equals(parentClosePolicy, that.parentClosePolicy) && Objects.equals(memo, that.memo) && Objects.equals(searchAttributes, that.searchAttributes) @@ -386,6 +407,7 @@ public int hashCode() { taskList, retryOptions, cronSchedule, + cronOverlapPolicy, parentClosePolicy, memo, searchAttributes, @@ -414,6 +436,8 @@ public String toString() { + retryOptions + ", cronSchedule=" + cronSchedule + + ", cronOverlapPolicy=" + + cronOverlapPolicy + ", parentClosePolicy=" + parentClosePolicy + ", memo='" diff --git a/src/test/java/com/uber/cadence/client/WorkflowOptionsTest.java b/src/test/java/com/uber/cadence/client/WorkflowOptionsTest.java index 050a307b8..79cc6c665 100644 --- a/src/test/java/com/uber/cadence/client/WorkflowOptionsTest.java +++ b/src/test/java/com/uber/cadence/client/WorkflowOptionsTest.java @@ -17,6 +17,11 @@ package com.uber.cadence.client; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import com.uber.cadence.CronOverlapPolicy; import com.uber.cadence.WorkflowIdReusePolicy; import com.uber.cadence.common.CronSchedule; import com.uber.cadence.common.MethodRetry; @@ -44,6 +49,7 @@ public void testOnlyOptionsAndEmptyAnnotationsPresent() throws NoSuchMethodExcep .setExecutionStartToCloseTimeout(Duration.ofSeconds(321)) .setTaskStartToCloseTimeout(Duration.ofSeconds(13)) .setWorkflowIdReusePolicy(WorkflowIdReusePolicy.RejectDuplicate) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) .setMemo(getTestMemo()) .setSearchAttributes(getTestSearchAttributes()) .build(); @@ -52,6 +58,7 @@ public void testOnlyOptionsAndEmptyAnnotationsPresent() throws NoSuchMethodExcep .getMethod("defaultWorkflowOptions") .getAnnotation(WorkflowMethod.class); Assert.assertEquals(o, WorkflowOptions.merge(a, null, null, o)); + Assert.assertEquals(CronOverlapPolicy.BUFFERONE, o.getCronOverlapPolicy()); } @WorkflowMethod( @@ -192,6 +199,97 @@ public void testInvalidCronScheduleAnnotation() throws NoSuchMethodException { Assert.fail("invalid cron schedule not caught"); } + @Test + public void testCronOverlapPolicy() { + WorkflowOptions options = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .build(); + + assertEquals(CronOverlapPolicy.BUFFERONE, options.getCronOverlapPolicy()); + } + + @Test + public void testCronOverlapPolicyInMerge() { + WorkflowOptions base = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.SKIPPED) + .build(); + + WorkflowOptions override = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .build(); + + WorkflowOptions merged = WorkflowOptions.merge(null, null, null, override); + assertEquals(CronOverlapPolicy.BUFFERONE, merged.getCronOverlapPolicy()); + + WorkflowOptions mergedWithBase = WorkflowOptions.merge(null, null, null, base); + assertEquals(CronOverlapPolicy.SKIPPED, mergedWithBase.getCronOverlapPolicy()); + } + + @Test + public void testCronOverlapPolicyEqualsAndHashCode() { + WorkflowOptions options1 = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .build(); + + WorkflowOptions options2 = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .build(); + + WorkflowOptions options3 = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.SKIPPED) + .build(); + + assertEquals(options1, options2); + assertNotEquals(options1, options3); + assertEquals(options1.hashCode(), options2.hashCode()); + assertNotEquals(options1.hashCode(), options3.hashCode()); + } + + @Test + public void testCronOverlapPolicyToString() { + WorkflowOptions options = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .build(); + + String toString = options.toString(); + assertTrue(toString.contains("cronOverlapPolicy=BUFFERONE")); + } + + @Test + public void testCronOverlapPolicyCopy() { + WorkflowOptions original = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .build(); + + WorkflowOptions copy = new WorkflowOptions.Builder(original).build(); + assertEquals(original.getCronOverlapPolicy(), copy.getCronOverlapPolicy()); + assertEquals(original, copy); + } + private Map getTestMemo() { Map memo = new HashMap<>(); memo.put("testKey", "testObject"); diff --git a/src/test/java/com/uber/cadence/internal/common/StartWorkflowExecutionParametersTest.java b/src/test/java/com/uber/cadence/internal/common/StartWorkflowExecutionParametersTest.java index fd675f850..2db423296 100644 --- a/src/test/java/com/uber/cadence/internal/common/StartWorkflowExecutionParametersTest.java +++ b/src/test/java/com/uber/cadence/internal/common/StartWorkflowExecutionParametersTest.java @@ -17,7 +17,10 @@ import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.*; +import com.uber.cadence.CronOverlapPolicy; import com.uber.cadence.WorkflowType; +import com.uber.cadence.client.WorkflowOptions; +import java.time.Duration; import org.junit.Before; import org.junit.Test; @@ -64,6 +67,7 @@ public void testToString() { + "maximumAttempts=0, " + "nonRetriableErrorReasons=null, expirationIntervalInSeconds=0}, " + "cronSchedule='* * * * *', " + + "cronOverlapPolicy=null, " + "memo='null', searchAttributes='null, context='null, delayStart='null'}"; assertEquals(expectedString, params1.toString()); @@ -124,5 +128,112 @@ public void testCopy() { params1.getRetryParameters().getExpirationIntervalInSeconds(), copy.getRetryParameters().getExpirationIntervalInSeconds()); assertEquals(params1.getCronSchedule(), copy.getCronSchedule()); + assertEquals(params1.getCronOverlapPolicy(), copy.getCronOverlapPolicy()); + } + + @Test + public void testCronOverlapPolicyField() { + StartWorkflowExecutionParameters params = new StartWorkflowExecutionParameters(); + params.setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE); + assertEquals(CronOverlapPolicy.BUFFERONE, params.getCronOverlapPolicy()); + } + + @Test + public void testCronOverlapPolicyInEqualsAndHashCode() { + StartWorkflowExecutionParameters params1 = new StartWorkflowExecutionParameters(); + params1.setWorkflowId("workflow123"); + params1.setWorkflowType(new WorkflowType().setName("sampleWorkflow")); + params1.setTaskList("taskList1"); + params1.setInput(new byte[] {1, 2, 3}); + params1.setExecutionStartToCloseTimeoutSeconds(60); + params1.setTaskStartToCloseTimeoutSeconds(30); + params1.setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE); + + StartWorkflowExecutionParameters params2 = new StartWorkflowExecutionParameters(); + params2.setWorkflowId("workflow123"); + params2.setWorkflowType(new WorkflowType().setName("sampleWorkflow")); + params2.setTaskList("taskList1"); + params2.setInput(new byte[] {1, 2, 3}); + params2.setExecutionStartToCloseTimeoutSeconds(60); + params2.setTaskStartToCloseTimeoutSeconds(30); + params2.setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE); + + StartWorkflowExecutionParameters params3 = new StartWorkflowExecutionParameters(); + params3.setWorkflowId("workflow123"); + params3.setWorkflowType(new WorkflowType().setName("sampleWorkflow")); + params3.setTaskList("taskList1"); + params3.setInput(new byte[] {1, 2, 3}); + params3.setExecutionStartToCloseTimeoutSeconds(60); + params3.setTaskStartToCloseTimeoutSeconds(30); + params3.setCronOverlapPolicy(CronOverlapPolicy.SKIPPED); + + assertEquals(params1, params2); + assertNotEquals(params1, params3); + assertEquals(params1.hashCode(), params2.hashCode()); + assertNotEquals(params1.hashCode(), params3.hashCode()); + } + + @Test + public void testCronOverlapPolicyInToString() { + StartWorkflowExecutionParameters params = new StartWorkflowExecutionParameters(); + params.setWorkflowId("workflow123"); + params.setWorkflowType(new WorkflowType().setName("sampleWorkflow")); + params.setTaskList("taskList1"); + params.setInput(new byte[] {1, 2, 3}); + params.setExecutionStartToCloseTimeoutSeconds(60); + params.setTaskStartToCloseTimeoutSeconds(30); + params.setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE); + + String toString = params.toString(); + assertTrue(toString.contains("cronOverlapPolicy=BUFFERONE")); + } + + @Test + public void testCronOverlapPolicyInCopy() { + StartWorkflowExecutionParameters original = new StartWorkflowExecutionParameters(); + original.setWorkflowId("workflow123"); + original.setWorkflowType(new WorkflowType().setName("sampleWorkflow")); + original.setTaskList("taskList1"); + original.setInput(new byte[] {1, 2, 3}); + original.setExecutionStartToCloseTimeoutSeconds(60); + original.setTaskStartToCloseTimeoutSeconds(30); + original.setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE); + + StartWorkflowExecutionParameters copy = original.copy(); + assertEquals(original.getCronOverlapPolicy(), copy.getCronOverlapPolicy()); + assertEquals(original, copy); + } + + @Test + public void testFromWorkflowOptionsWithCronOverlapPolicy() { + WorkflowOptions options = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .build(); + + StartWorkflowExecutionParameters params = + StartWorkflowExecutionParameters.fromWorkflowOptions(options); + assertEquals(CronOverlapPolicy.BUFFERONE, params.getCronOverlapPolicy()); + } + + @Test + public void testFromWorkflowOptionsWithoutCronOverlapPolicy() { + WorkflowOptions options = + new WorkflowOptions.Builder() + .setTaskList("test-task-list") + .setExecutionStartToCloseTimeout(Duration.ofSeconds(10)) + .build(); + + StartWorkflowExecutionParameters params = + StartWorkflowExecutionParameters.fromWorkflowOptions(options); + assertEquals(null, params.getCronOverlapPolicy()); // default value + } + + @Test + public void testCronOverlapPolicyDefaultValue() { + StartWorkflowExecutionParameters params = new StartWorkflowExecutionParameters(); + assertEquals(null, params.getCronOverlapPolicy()); // should default to null } } diff --git a/src/test/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParametersTest.java b/src/test/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParametersTest.java index 6e0b36248..bd6e87c2a 100644 --- a/src/test/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParametersTest.java +++ b/src/test/java/com/uber/cadence/internal/replay/StartChildWorkflowExecutionParametersTest.java @@ -17,7 +17,9 @@ import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertNotNull; import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertNotEquals; +import com.uber.cadence.CronOverlapPolicy; import com.uber.cadence.ParentClosePolicy; import com.uber.cadence.WorkflowIdReusePolicy; import com.uber.cadence.WorkflowType; @@ -41,6 +43,7 @@ public void testBuilderAndGetters() { WorkflowIdReusePolicy reusePolicy = WorkflowIdReusePolicy.AllowDuplicate; RetryParameters retryParameters = new RetryParameters(); String cronSchedule = "* * * * *"; + CronOverlapPolicy cronOverlapPolicy = CronOverlapPolicy.BUFFERONE; Map memo = new HashMap<>(); memo.put("key1", "value1"); Map searchAttributes = new HashMap<>(); @@ -62,6 +65,7 @@ public void testBuilderAndGetters() { .setWorkflowIdReusePolicy(reusePolicy) .setRetryParameters(retryParameters) .setCronSchedule(cronSchedule) + .setCronOverlapPolicy(cronOverlapPolicy) .setMemo(memo) .setSearchAttributes(searchAttributes) .setContext(context) @@ -78,6 +82,7 @@ public void testBuilderAndGetters() { assertEquals(reusePolicy, parameters.getWorkflowIdReusePolicy()); assertEquals(retryParameters, parameters.getRetryParameters()); assertEquals(cronSchedule, parameters.getCronSchedule()); + assertEquals(cronOverlapPolicy, parameters.getCronOverlapPolicy()); assertEquals(memo, parameters.getMemo()); assertEquals(searchAttributes, parameters.getSearchAttributes()); assertEquals(context, parameters.getContext()); @@ -172,4 +177,274 @@ public void testToString() { assertTrue(parameters.toString().contains("testControl")); assertTrue(parameters.toString().contains("1000")); } + + @Test + public void testCronOverlapPolicyField() { + String domain = "testDomain"; + String control = "testControl"; + long executionTimeout = 1000L; + byte[] input = {1, 2, 3}; + String taskList = "testTaskList"; + long taskTimeout = 2000L; + String workflowId = "testWorkflowId"; + WorkflowType workflowType = new WorkflowType().setName("testWorkflowType"); + WorkflowIdReusePolicy reusePolicy = WorkflowIdReusePolicy.AllowDuplicate; + RetryParameters retryParameters = new RetryParameters(); + String cronSchedule = "* * * * *"; + CronOverlapPolicy cronOverlapPolicy = CronOverlapPolicy.BUFFERONE; + Map memo = new HashMap<>(); + memo.put("key1", "value1"); + Map searchAttributes = new HashMap<>(); + searchAttributes.put("key2", "value2"); + Map context = new HashMap<>(); + context.put("key3", new byte[] {4, 5, 6}); + ParentClosePolicy parentClosePolicy = ParentClosePolicy.TERMINATE; + + StartChildWorkflowExecutionParameters parameters = + new StartChildWorkflowExecutionParameters.Builder() + .setDomain(domain) + .setControl(control) + .setExecutionStartToCloseTimeoutSeconds(executionTimeout) + .setInput(input) + .setTaskList(taskList) + .setTaskStartToCloseTimeoutSeconds(taskTimeout) + .setWorkflowId(workflowId) + .setWorkflowType(workflowType) + .setWorkflowIdReusePolicy(reusePolicy) + .setRetryParameters(retryParameters) + .setCronSchedule(cronSchedule) + .setCronOverlapPolicy(cronOverlapPolicy) + .setMemo(memo) + .setSearchAttributes(searchAttributes) + .setContext(context) + .setParentClosePolicy(parentClosePolicy) + .build(); + + assertEquals(CronOverlapPolicy.BUFFERONE, parameters.getCronOverlapPolicy()); + } + + @Test + public void testCronOverlapPolicyInEqualsAndHashCode() { + String domain = "testDomain"; + String control = "testControl"; + long executionTimeout = 1000L; + byte[] input = {1, 2, 3}; + String taskList = "testTaskList"; + long taskTimeout = 2000L; + String workflowId = "testWorkflowId"; + WorkflowType workflowType = new WorkflowType().setName("testWorkflowType"); + WorkflowIdReusePolicy reusePolicy = WorkflowIdReusePolicy.AllowDuplicate; + RetryParameters retryParameters = new RetryParameters(); + String cronSchedule = "* * * * *"; + CronOverlapPolicy cronOverlapPolicy = CronOverlapPolicy.BUFFERONE; + Map memo = new HashMap<>(); + memo.put("key1", "value1"); + Map searchAttributes = new HashMap<>(); + searchAttributes.put("key2", "value2"); + Map context = new HashMap<>(); + context.put("key3", new byte[] {4, 5, 6}); + ParentClosePolicy parentClosePolicy = ParentClosePolicy.TERMINATE; + + StartChildWorkflowExecutionParameters params1 = + new StartChildWorkflowExecutionParameters.Builder() + .setDomain(domain) + .setControl(control) + .setExecutionStartToCloseTimeoutSeconds(executionTimeout) + .setInput(input) + .setTaskList(taskList) + .setTaskStartToCloseTimeoutSeconds(taskTimeout) + .setWorkflowId(workflowId) + .setWorkflowType(workflowType) + .setWorkflowIdReusePolicy(reusePolicy) + .setRetryParameters(retryParameters) + .setCronSchedule(cronSchedule) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .setMemo(memo) + .setSearchAttributes(searchAttributes) + .setContext(context) + .setParentClosePolicy(parentClosePolicy) + .build(); + + StartChildWorkflowExecutionParameters params2 = + new StartChildWorkflowExecutionParameters.Builder() + .setDomain(domain) + .setControl(control) + .setExecutionStartToCloseTimeoutSeconds(executionTimeout) + .setInput(input) + .setTaskList(taskList) + .setTaskStartToCloseTimeoutSeconds(taskTimeout) + .setWorkflowId(workflowId) + .setWorkflowType(workflowType) + .setWorkflowIdReusePolicy(reusePolicy) + .setRetryParameters(retryParameters) + .setCronSchedule(cronSchedule) + .setCronOverlapPolicy(CronOverlapPolicy.BUFFERONE) + .setMemo(memo) + .setSearchAttributes(searchAttributes) + .setContext(context) + .setParentClosePolicy(parentClosePolicy) + .build(); + + StartChildWorkflowExecutionParameters params3 = + new StartChildWorkflowExecutionParameters.Builder() + .setDomain(domain) + .setControl(control) + .setExecutionStartToCloseTimeoutSeconds(executionTimeout) + .setInput(input) + .setTaskList(taskList) + .setTaskStartToCloseTimeoutSeconds(taskTimeout) + .setWorkflowId(workflowId) + .setWorkflowType(workflowType) + .setWorkflowIdReusePolicy(reusePolicy) + .setRetryParameters(retryParameters) + .setCronSchedule(cronSchedule) + .setCronOverlapPolicy(CronOverlapPolicy.SKIPPED) + .setMemo(memo) + .setSearchAttributes(searchAttributes) + .setContext(context) + .setParentClosePolicy(parentClosePolicy) + .build(); + + assertEquals(params1, params2); + assertNotEquals(params1, params3); + assertEquals(params1.hashCode(), params2.hashCode()); + assertNotEquals(params1.hashCode(), params3.hashCode()); + } + + @Test + public void testCronOverlapPolicyInToString() { + String domain = "testDomain"; + String control = "testControl"; + long executionTimeout = 1000L; + byte[] input = {1, 2, 3}; + String taskList = "testTaskList"; + long taskTimeout = 2000L; + String workflowId = "testWorkflowId"; + WorkflowType workflowType = new WorkflowType().setName("testWorkflowType"); + WorkflowIdReusePolicy reusePolicy = WorkflowIdReusePolicy.AllowDuplicate; + RetryParameters retryParameters = new RetryParameters(); + String cronSchedule = "* * * * *"; + CronOverlapPolicy cronOverlapPolicy = CronOverlapPolicy.BUFFERONE; + Map memo = new HashMap<>(); + memo.put("key1", "value1"); + Map searchAttributes = new HashMap<>(); + searchAttributes.put("key2", "value2"); + Map context = new HashMap<>(); + context.put("key3", new byte[] {4, 5, 6}); + ParentClosePolicy parentClosePolicy = ParentClosePolicy.TERMINATE; + + StartChildWorkflowExecutionParameters parameters = + new StartChildWorkflowExecutionParameters.Builder() + .setDomain(domain) + .setControl(control) + .setExecutionStartToCloseTimeoutSeconds(executionTimeout) + .setInput(input) + .setTaskList(taskList) + .setTaskStartToCloseTimeoutSeconds(taskTimeout) + .setWorkflowId(workflowId) + .setWorkflowType(workflowType) + .setWorkflowIdReusePolicy(reusePolicy) + .setRetryParameters(retryParameters) + .setCronSchedule(cronSchedule) + .setCronOverlapPolicy(cronOverlapPolicy) + .setMemo(memo) + .setSearchAttributes(searchAttributes) + .setContext(context) + .setParentClosePolicy(parentClosePolicy) + .build(); + + String toString = parameters.toString(); + assertTrue(toString.contains("cronOverlapPolicy=" + cronOverlapPolicy)); + } + + @Test + public void testCronOverlapPolicyInCopy() { + String domain = "testDomain"; + String control = "testControl"; + long executionTimeout = 1000L; + byte[] input = {1, 2, 3}; + String taskList = "testTaskList"; + long taskTimeout = 2000L; + String workflowId = "testWorkflowId"; + WorkflowType workflowType = new WorkflowType().setName("testWorkflowType"); + WorkflowIdReusePolicy reusePolicy = WorkflowIdReusePolicy.AllowDuplicate; + RetryParameters retryParameters = new RetryParameters(); + String cronSchedule = "* * * * *"; + CronOverlapPolicy cronOverlapPolicy = CronOverlapPolicy.BUFFERONE; + Map memo = new HashMap<>(); + memo.put("key1", "value1"); + Map searchAttributes = new HashMap<>(); + searchAttributes.put("key2", "value2"); + Map context = new HashMap<>(); + context.put("key3", new byte[] {4, 5, 6}); + ParentClosePolicy parentClosePolicy = ParentClosePolicy.TERMINATE; + + StartChildWorkflowExecutionParameters original = + new StartChildWorkflowExecutionParameters.Builder() + .setDomain(domain) + .setControl(control) + .setExecutionStartToCloseTimeoutSeconds(executionTimeout) + .setInput(input) + .setTaskList(taskList) + .setTaskStartToCloseTimeoutSeconds(taskTimeout) + .setWorkflowId(workflowId) + .setWorkflowType(workflowType) + .setWorkflowIdReusePolicy(reusePolicy) + .setRetryParameters(retryParameters) + .setCronSchedule(cronSchedule) + .setCronOverlapPolicy(cronOverlapPolicy) + .setMemo(memo) + .setSearchAttributes(searchAttributes) + .setContext(context) + .setParentClosePolicy(parentClosePolicy) + .build(); + + StartChildWorkflowExecutionParameters copy = original.copy(); + assertEquals(original.getCronOverlapPolicy(), copy.getCronOverlapPolicy()); + assertEquals(original, copy); + } + + @Test + public void testCronOverlapPolicyDefaultValue() { + String domain = "testDomain"; + String control = "testControl"; + long executionTimeout = 1000L; + byte[] input = {1, 2, 3}; + String taskList = "testTaskList"; + long taskTimeout = 2000L; + String workflowId = "testWorkflowId"; + WorkflowType workflowType = new WorkflowType().setName("testWorkflowType"); + WorkflowIdReusePolicy reusePolicy = WorkflowIdReusePolicy.AllowDuplicate; + RetryParameters retryParameters = new RetryParameters(); + String cronSchedule = "* * * * *"; + CronOverlapPolicy cronOverlapPolicy = CronOverlapPolicy.BUFFERONE; + Map memo = new HashMap<>(); + memo.put("key1", "value1"); + Map searchAttributes = new HashMap<>(); + searchAttributes.put("key2", "value2"); + Map context = new HashMap<>(); + context.put("key3", new byte[] {4, 5, 6}); + ParentClosePolicy parentClosePolicy = ParentClosePolicy.TERMINATE; + + StartChildWorkflowExecutionParameters parameters = + new StartChildWorkflowExecutionParameters.Builder() + .setDomain(domain) + .setControl(control) + .setExecutionStartToCloseTimeoutSeconds(executionTimeout) + .setInput(input) + .setTaskList(taskList) + .setTaskStartToCloseTimeoutSeconds(taskTimeout) + .setWorkflowId(workflowId) + .setWorkflowType(workflowType) + .setWorkflowIdReusePolicy(reusePolicy) + .setRetryParameters(retryParameters) + .setCronSchedule(cronSchedule) + .setMemo(memo) + .setSearchAttributes(searchAttributes) + .setContext(context) + .setParentClosePolicy(parentClosePolicy) + .build(); + + assertEquals(0, parameters.getCronOverlapPolicy()); // should default to 0 + } }