Uber Cadence workflow versioning

549 views Asked by At

Cadence workflow versioning:

workflow impl has below code:

        int version1 = Workflow.getVersion("change123", Workflow.DEFAULT_VERSION, 1);
        logger.info("version1: {}", version1);

start of workflow 1 : o/p -- version1: 1

change in workflow impl :

        int version1 = Workflow.getVersion("change1234", Workflow.DEFAULT_VERSION, 2);
        logger.info("version1: {}", version1);       

start of workflow 2 : o/p -- version1: 2

change in workflow impl :

       int version1 = Workflow.getVersion("change12345", Workflow.DEFAULT_VERSION, 3);
       logger.info("version1: {}", version1);        

start of workflow 3 : o/p -- version1: 3

replay of workflow 2 : o/p --version1: -1

replay of workflow 1 : o/p --version1: -1

I was expecting below o/p

replay of workflow 2 : o/p -- version1: 2

replay of workflow 1 : o/p -- version1: 1

So this means we can only maintain two versions of the workflow code at a time,

the current version and all older version getVersion will give Workflow.DEFAULT_VERSION

Please correct me if I am wrong !!

1

There are 1 answers

0
Long Quanzheng On

The problem is that you are passing in the different changeIDs

To maintain different versions for the same part, you have to keep using the same changeID, unless the changeID is deprecated later but you want to make change again.

ChangID is the identifier in the workflow to differentiate the different parts of changes. For example, your workflow:

String resA = activities.executeA();

String resB = activities.executeB();

If you want to make change to executeA=>executeAA, then it becomes:

int versionA = Workflow.getVersion("changeToA", Workflow.DEFAULT_VERSION, 1);

if(versionA == 1){
  String resA = activities.executeAA();
}else{
  String resA = activities.executeA();
}


String resB = activities.executeB();

Then later on if you want to change executeAA=>executeAAA then it becomes:

int versionA = Workflow.getVersion("changeToA", Workflow.DEFAULT_VERSION, 2);

if(versionA == 2){
  String resA = activities.executeAAA();
}else if versionA == 1{
  String resA = activities.executeAA();
}else{
  String resA = activities.executeA();
}


String resB = activities.executeB();

So that you can maintain multiple versions.

And then if you want to make change to executeB=>executeBB, then you have to use another changeID:

int versionA = Workflow.getVersion("changeToA", Workflow.DEFAULT_VERSION, 2);

if(versionA == 2){
  String resA = activities.executeAAA();
}else if versionA == 1{
  String resA = activities.executeAA();
}else{
  String resA = activities.executeA();
}

int versionB = Workflow.getVersion("changeToB", Workflow.DEFAULT_VERSION, 1);

if(versionB == 1){
  String resB = activities.executeBB();
}else{
  String resB = activities.executeB();
}

The key here is to understand the changeID, it's indeed a little tricky, but once you get it, it's powerful.

In your code, because you always make a different changeID, the already started workflows(workflow1 and workflow2) will always get a DEFAULT_VERSION(-1).

Internally, when in executing mode(non-replay), getVersion will write a Marker event with the MaxVersion into history when executing the code.

When in replay mode, if a Marker existing(changeID must match, otherwise marker is ignored), then return the version from the Marker, If not existing(because workflow1 doesn't have the getVersion code in its executing mode), then uses the minVersion(in your case the DEFAULT_VERSION). (if the version from marker is lower than minVersion, it will return errors)

See more documents:

for golang

for java