Skip to content

Commit 82ac678

Browse files
Port enhanced version control features from Go client
Add support for ExecuteWithVersion and ExecuteWithMinVersion options to getVersion method, porting functionality from cadence-go-client PRs #1427 and #1428. Changes: - Add GetVersionOptions class with builder pattern for version control configuration - Add executeWithVersion() and executeWithMinVersion() methods to GetVersionOptions - Add overloaded getVersion() method that accepts GetVersionOptions parameter - Add convenience methods getVersionWithCustomVersion() and getVersionWithMinVersion() - Update all workflow interceptor interfaces and implementations to support new options - Update DecisionContext, ClockDecisionContext, and related classes for version selection logic - Add testing framework support for enhanced version control features - Add comprehensive test coverage for new functionality This enables safer deployment strategies and more granular control over workflow version execution, allowing developers to: - Force specific versions instead of max supported version - Use minimum supported version for backward compatibility - Test workflows with enhanced version control in test environments Fixes compilation errors and ensures all existing functionality remains compatible.
1 parent ea83af1 commit 82ac678

16 files changed

+359
-148
lines changed

src/main/java/com/uber/cadence/internal/replay/ClockDecisionContext.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.uber.cadence.workflow.ActivityFailureException;
3434
import com.uber.cadence.workflow.Functions.Func;
3535
import com.uber.cadence.workflow.Functions.Func1;
36+
import com.uber.cadence.workflow.GetVersionOptions;
3637
import java.time.Duration;
3738
import java.util.ArrayList;
3839
import java.util.HashMap;
@@ -320,11 +321,16 @@ private void handleVersionMarker(MarkerRecordedEventAttributes attributes) {
320321

321322
GetVersionResult getVersion(
322323
String changeId, DataConverter converter, int minSupported, int maxSupported) {
323-
return getVersion(changeId, converter, minSupported, maxSupported, GetVersionOptions.newBuilder().build());
324+
return getVersion(
325+
changeId, converter, minSupported, maxSupported, GetVersionOptions.newBuilder().build());
324326
}
325327

326328
GetVersionResult getVersion(
327-
String changeId, DataConverter converter, int minSupported, int maxSupported, GetVersionOptions options) {
329+
String changeId,
330+
DataConverter converter,
331+
int minSupported,
332+
int maxSupported,
333+
GetVersionOptions options) {
328334
Predicate<MarkerRecordedEventAttributes> changeIdEquals =
329335
(attributes) -> {
330336
MarkerHandler.MarkerInterface markerData =
@@ -373,15 +379,15 @@ private int determineVersionToUse(int minSupported, int maxSupported, GetVersion
373379
if (isReplaying()) {
374380
return WorkflowInternal.DEFAULT_VERSION;
375381
}
376-
382+
377383
if (options.getCustomVersion().isPresent()) {
378384
return options.getCustomVersion().get();
379385
}
380-
386+
381387
if (options.isUseMinVersion()) {
382388
return minSupported;
383389
}
384-
390+
385391
return maxSupported;
386392
}
387393

src/main/java/com/uber/cadence/internal/replay/DecisionContext.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.uber.cadence.converter.DataConverter;
2626
import com.uber.cadence.workflow.Functions.Func;
2727
import com.uber.cadence.workflow.Functions.Func1;
28+
import com.uber.cadence.workflow.GetVersionOptions;
2829
import com.uber.cadence.workflow.Promise;
2930
import com.uber.m3.tally.Scope;
3031
import java.time.Duration;
@@ -204,7 +205,12 @@ Optional<byte[]> mutableSideEffect(
204205
* @param options version control options
205206
* @return version
206207
*/
207-
int getVersion(String changeID, DataConverter dataConverter, int minSupported, int maxSupported, GetVersionOptions options);
208+
int getVersion(
209+
String changeID,
210+
DataConverter dataConverter,
211+
int minSupported,
212+
int maxSupported,
213+
GetVersionOptions options);
208214

209215
Random newRandom();
210216

src/main/java/com/uber/cadence/internal/replay/DecisionContextImpl.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.uber.cadence.internal.worker.SingleWorkerOptions;
3636
import com.uber.cadence.workflow.Functions.Func;
3737
import com.uber.cadence.workflow.Functions.Func1;
38+
import com.uber.cadence.workflow.GetVersionOptions;
3839
import com.uber.cadence.workflow.Promise;
3940
import com.uber.cadence.workflow.Workflow;
4041
import com.uber.m3.tally.Scope;
@@ -304,7 +305,11 @@ public int getVersion(
304305

305306
@Override
306307
public int getVersion(
307-
String changeID, DataConverter converter, int minSupported, int maxSupported, GetVersionOptions options) {
308+
String changeID,
309+
DataConverter converter,
310+
int minSupported,
311+
int maxSupported,
312+
GetVersionOptions options) {
308313
final ClockDecisionContext.GetVersionResult results =
309314
workflowClock.getVersion(changeID, converter, minSupported, maxSupported, options);
310315
if (results.shouldUpdateCadenceChangeVersion()) {

src/main/java/com/uber/cadence/internal/sync/DeterministicRunnerImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.uber.cadence.internal.replay.StartChildWorkflowExecutionParameters;
3737
import com.uber.cadence.workflow.Functions.Func;
3838
import com.uber.cadence.workflow.Functions.Func1;
39+
import com.uber.cadence.workflow.GetVersionOptions;
3940
import com.uber.cadence.workflow.Promise;
4041
import com.uber.m3.tally.Scope;
4142
import java.time.Duration;
@@ -695,6 +696,16 @@ public int getVersion(
695696
throw new UnsupportedOperationException("not implemented");
696697
}
697698

699+
@Override
700+
public int getVersion(
701+
String changeID,
702+
DataConverter converter,
703+
int minSupported,
704+
int maxSupported,
705+
GetVersionOptions options) {
706+
throw new UnsupportedOperationException("not implemented");
707+
}
708+
698709
@Override
699710
public Random newRandom() {
700711
throw new UnsupportedOperationException("not implemented");

src/main/java/com/uber/cadence/internal/sync/SyncDecisionContext.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import com.uber.cadence.workflow.ContinueAsNewOptions;
5555
import com.uber.cadence.workflow.Functions;
5656
import com.uber.cadence.workflow.Functions.Func;
57+
import com.uber.cadence.workflow.GetVersionOptions;
5758
import com.uber.cadence.workflow.Promise;
5859
import com.uber.cadence.workflow.SignalExternalWorkflowException;
5960
import com.uber.cadence.workflow.Workflow;
@@ -621,7 +622,8 @@ public int getVersion(String changeID, int minSupported, int maxSupported) {
621622
}
622623

623624
@Override
624-
public int getVersion(String changeID, int minSupported, int maxSupported, GetVersionOptions options) {
625+
public int getVersion(
626+
String changeID, int minSupported, int maxSupported, GetVersionOptions options) {
625627
return context.getVersion(changeID, converter, minSupported, maxSupported, options);
626628
}
627629

src/main/java/com/uber/cadence/internal/sync/TestActivityEnvironmentInternal.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ public int getVersion(String changeID, int minSupported, int maxSupported) {
242242
throw new UnsupportedOperationException("not implemented");
243243
}
244244

245+
@Override
246+
public int getVersion(
247+
String changeID, int minSupported, int maxSupported, GetVersionOptions options) {
248+
throw new UnsupportedOperationException("not implemented");
249+
}
250+
245251
@Override
246252
public void continueAsNew(
247253
Optional<String> workflowType, Optional<ContinueAsNewOptions> options, Object[] args) {

src/main/java/com/uber/cadence/internal/sync/WorkflowInternal.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.uber.cadence.workflow.ExternalWorkflowStub;
3737
import com.uber.cadence.workflow.Functions;
3838
import com.uber.cadence.workflow.Functions.Func;
39+
import com.uber.cadence.workflow.GetVersionOptions;
3940
import com.uber.cadence.workflow.Promise;
4041
import com.uber.cadence.workflow.QueryMethod;
4142
import com.uber.cadence.workflow.Workflow;
@@ -255,14 +256,15 @@ public static int getVersion(String changeID, int minSupported, int maxSupported
255256

256257
/**
257258
* Enhanced version of getVersion with additional options for version control.
258-
*
259+
*
259260
* @param changeID identifier of a particular change
260261
* @param minSupported min version supported for the change
261262
* @param maxSupported max version supported for the change
262263
* @param options version control options
263264
* @return version
264265
*/
265-
public static int getVersion(String changeID, int minSupported, int maxSupported, GetVersionOptions options) {
266+
public static int getVersion(
267+
String changeID, int minSupported, int maxSupported, GetVersionOptions options) {
266268
return getWorkflowInterceptor().getVersion(changeID, minSupported, maxSupported, options);
267269
}
268270

src/main/java/com/uber/cadence/workflow/GetVersionOptions.java

Lines changed: 52 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -20,89 +20,82 @@
2020
import java.util.Optional;
2121

2222
/**
23-
* Options for configuring GetVersion behavior.
24-
* This class provides a builder pattern for configuring version control options.
25-
*
23+
* Options for configuring GetVersion behavior. This class provides a builder pattern for
24+
* configuring version control options.
25+
*
2626
* <p>Example usage:
27+
*
2728
* <pre><code>
2829
* // Force a specific version
2930
* GetVersionOptions options = GetVersionOptions.newBuilder()
3031
* .executeWithVersion(2)
3132
* .build();
32-
*
33+
*
3334
* // Use minimum supported version
3435
* GetVersionOptions options = GetVersionOptions.newBuilder()
3536
* .executeWithMinVersion()
3637
* .build();
3738
* </code></pre>
3839
*/
3940
public final class GetVersionOptions {
40-
private final Optional<Integer> customVersion;
41-
private final boolean useMinVersion;
41+
private final Optional<Integer> customVersion;
42+
private final boolean useMinVersion;
4243

43-
private GetVersionOptions(Optional<Integer> customVersion, boolean useMinVersion) {
44-
this.customVersion = customVersion;
45-
this.useMinVersion = useMinVersion;
46-
}
44+
private GetVersionOptions(Optional<Integer> customVersion, boolean useMinVersion) {
45+
this.customVersion = customVersion;
46+
this.useMinVersion = useMinVersion;
47+
}
4748

48-
/**
49-
* Returns the custom version if specified, otherwise empty.
50-
*/
51-
public Optional<Integer> getCustomVersion() {
52-
return customVersion;
53-
}
49+
/** Returns the custom version if specified, otherwise empty. */
50+
public Optional<Integer> getCustomVersion() {
51+
return customVersion;
52+
}
53+
54+
/** Returns true if the minimum version should be used instead of maximum version. */
55+
public boolean isUseMinVersion() {
56+
return useMinVersion;
57+
}
58+
59+
/** Creates a new builder for GetVersionOptions. */
60+
public static Builder newBuilder() {
61+
return new Builder();
62+
}
63+
64+
/** Builder for GetVersionOptions. */
65+
public static class Builder {
66+
private Optional<Integer> customVersion = Optional.empty();
67+
private boolean useMinVersion = false;
5468

5569
/**
56-
* Returns true if the minimum version should be used instead of maximum version.
70+
* Forces a specific version to be returned when executed for the first time, instead of
71+
* returning maxSupported version.
72+
*
73+
* @param version the specific version to use
74+
* @return this builder
5775
*/
58-
public boolean isUseMinVersion() {
59-
return useMinVersion;
76+
public Builder executeWithVersion(int version) {
77+
this.customVersion = Optional.of(version);
78+
return this;
6079
}
6180

6281
/**
63-
* Creates a new builder for GetVersionOptions.
82+
* Makes GetVersion return minSupported version when executed for the first time, instead of
83+
* returning maxSupported version.
84+
*
85+
* @return this builder
6486
*/
65-
public static Builder newBuilder() {
66-
return new Builder();
87+
public Builder executeWithMinVersion() {
88+
this.useMinVersion = true;
89+
return this;
6790
}
6891

6992
/**
70-
* Builder for GetVersionOptions.
93+
* Builds the GetVersionOptions instance.
94+
*
95+
* @return the configured GetVersionOptions
7196
*/
72-
public static class Builder {
73-
private Optional<Integer> customVersion = Optional.empty();
74-
private boolean useMinVersion = false;
75-
76-
/**
77-
* Forces a specific version to be returned when executed for the first time,
78-
* instead of returning maxSupported version.
79-
*
80-
* @param version the specific version to use
81-
* @return this builder
82-
*/
83-
public Builder executeWithVersion(int version) {
84-
this.customVersion = Optional.of(version);
85-
return this;
86-
}
87-
88-
/**
89-
* Makes GetVersion return minSupported version when executed for the first time,
90-
* instead of returning maxSupported version.
91-
*
92-
* @return this builder
93-
*/
94-
public Builder executeWithMinVersion() {
95-
this.useMinVersion = true;
96-
return this;
97-
}
98-
99-
/**
100-
* Builds the GetVersionOptions instance.
101-
*
102-
* @return the configured GetVersionOptions
103-
*/
104-
public GetVersionOptions build() {
105-
return new GetVersionOptions(customVersion, useMinVersion);
106-
}
97+
public GetVersionOptions build() {
98+
return new GetVersionOptions(customVersion, useMinVersion);
10799
}
108-
}
100+
}
101+
}

src/main/java/com/uber/cadence/workflow/Workflow.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,16 +1145,18 @@ public static int getVersion(String changeID, int minSupported, int maxSupported
11451145
}
11461146

11471147
/**
1148-
* Enhanced version of {@code getVersion} with additional options for version control.
1149-
* This method provides more granular control over version execution and enables safer deployment strategies.
1148+
* Enhanced version of {@code getVersion} with additional options for version control. This method
1149+
* provides more granular control over version execution and enables safer deployment strategies.
11501150
*
11511151
* <p>Example usage with custom version:
1152+
*
11521153
* <pre><code>
1153-
* int version = Workflow.getVersion("changeId", 1, 3,
1154+
* int version = Workflow.getVersion("changeId", 1, 3,
11541155
* GetVersionOptions.newBuilder().executeWithVersion(2).build());
11551156
* </code></pre>
11561157
*
11571158
* <p>Example usage with minimum version:
1159+
*
11581160
* <pre><code>
11591161
* int version = Workflow.getVersion("changeId", 1, 3,
11601162
* GetVersionOptions.newBuilder().executeWithMinVersion().build());
@@ -1166,38 +1168,39 @@ public static int getVersion(String changeID, int minSupported, int maxSupported
11661168
* @param options version control options
11671169
* @return version
11681170
*/
1169-
public static int getVersion(String changeID, int minSupported, int maxSupported, GetVersionOptions options) {
1171+
public static int getVersion(
1172+
String changeID, int minSupported, int maxSupported, GetVersionOptions options) {
11701173
return WorkflowInternal.getVersion(changeID, minSupported, maxSupported, options);
11711174
}
11721175

11731176
/**
1174-
* Convenience method that forces a specific version to be returned when executed for the first time.
1177+
* Convenience method that forces a specific version to be returned when executed for the first
1178+
* time.
11751179
*
11761180
* @param changeID identifier of a particular change
11771181
* @param minSupported min version supported for the change
11781182
* @param maxSupported max version supported for the change
11791183
* @param customVersion the specific version to use
11801184
* @return version
11811185
*/
1182-
public static int getVersionWithCustomVersion(String changeID, int minSupported, int maxSupported, int customVersion) {
1183-
GetVersionOptions options = GetVersionOptions.newBuilder()
1184-
.executeWithVersion(customVersion)
1185-
.build();
1186+
public static int getVersionWithCustomVersion(
1187+
String changeID, int minSupported, int maxSupported, int customVersion) {
1188+
GetVersionOptions options =
1189+
GetVersionOptions.newBuilder().executeWithVersion(customVersion).build();
11861190
return getVersion(changeID, minSupported, maxSupported, options);
11871191
}
11881192

11891193
/**
1190-
* Convenience method that makes GetVersion return minSupported version when executed for the first time.
1194+
* Convenience method that makes GetVersion return minSupported version when executed for the
1195+
* first time.
11911196
*
11921197
* @param changeID identifier of a particular change
11931198
* @param minSupported min version supported for the change
11941199
* @param maxSupported max version supported for the change
11951200
* @return version
11961201
*/
11971202
public static int getVersionWithMinVersion(String changeID, int minSupported, int maxSupported) {
1198-
GetVersionOptions options = GetVersionOptions.newBuilder()
1199-
.executeWithMinVersion()
1200-
.build();
1203+
GetVersionOptions options = GetVersionOptions.newBuilder().executeWithMinVersion().build();
12011204
return getVersion(changeID, minSupported, maxSupported, options);
12021205
}
12031206

src/main/java/com/uber/cadence/workflow/WorkflowInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ <R> R mutableSideEffect(
129129

130130
/**
131131
* Enhanced version of getVersion with additional options for version control.
132-
*
132+
*
133133
* @param changeID identifier of a particular change
134134
* @param minSupported min version supported for the change
135135
* @param maxSupported max version supported for the change

0 commit comments

Comments
 (0)