-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c1288b3
commit 19d9c38
Showing
12 changed files
with
682 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Instance Migration Workaround for Camunda 8 | ||
|
||
Currently, Camunda 8 does not support instance migration. | ||
This prototype shows how we can use the Zeebe and Operate API to move process instances from one model version to another: | ||
1. The process instances must have entered a wait state, such as a user task or a service task for which the external task worker has been deactivated. | ||
2. For each instance of the old version, an instance in the new version is created. | ||
* Variables are copied | ||
* The instance is modified to start at a predefined point (i.e., the wait state) | ||
3. The old instance is canceled. | ||
|
||
This prototype considers the two latest versions of a model. Older versions are ignored. | ||
This prototype is heavily inspired by the [Camunda 7 to 8 migration tooling](https://github.com/camunda-community-hub/camunda-7-to-8-migration). | ||
## Configuration | ||
|
||
Everything is preconfigured for local testing (i.e., localhost addresses without encryption). | ||
You can configure the connection to Zeebe as described [here](https://github.com/camunda-community-hub/spring-zeebe). | ||
You can furthermore use the following properties to configure the connection to Operate: | ||
``` | ||
operate: | ||
url: https://bru-2.operate.camunda.io/757dbc30-5127-4bed-XXXX-XXXXXXXXXXXX | ||
# for self-managed setup configure | ||
keycloak: | ||
realm: camunda-platform | ||
url: https://mykeycloak.example.com | ||
``` | ||
|
||
## Version Information | ||
|
||
This prototype has been build for Camunda 8.1.8. | ||
It is compatible with both self-managed and SaaS deployments. | ||
|
||
Camunda 8.2 provides additional API endpoints, which can be used to improve this prototype: | ||
We can get the element ID of currently enabled flow nodes. | ||
With this information, activity "wait until all processes reached waiting state" becomes obsolete. |
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,34 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>com.camunda.consulting</groupId> | ||
<artifactId>c8instancemigration</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
|
||
<properties> | ||
<maven.compiler.source>17</maven.compiler.source> | ||
<maven.compiler.target>17</maven.compiler.target> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
<dependencies> | ||
<dependency> | ||
<groupId>io.camunda</groupId> | ||
<artifactId>spring-zeebe-starter</artifactId> | ||
<version>8.1.13</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.camunda</groupId> | ||
<artifactId>camunda-operate-client-java</artifactId> | ||
<version>8.1.7.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-test</artifactId> | ||
<scope>test</scope> | ||
<version>2.7.7</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
97 changes: 97 additions & 0 deletions
97
c8-1-instance-migration/src/main/java/com/camunda/consulting/Main.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,97 @@ | ||
package com.camunda.consulting; | ||
|
||
import io.camunda.operate.CamundaOperateClient; | ||
import io.camunda.operate.dto.ProcessDefinition; | ||
import io.camunda.operate.dto.ProcessInstance; | ||
import io.camunda.operate.dto.ProcessInstanceState; | ||
import io.camunda.operate.exception.OperateException; | ||
import io.camunda.operate.search.ProcessDefinitionFilter; | ||
import io.camunda.operate.search.ProcessInstanceFilter; | ||
import io.camunda.operate.search.SearchQuery; | ||
import io.camunda.operate.search.Sort; | ||
import io.camunda.operate.search.SortOrder; | ||
import io.camunda.operate.search.VariableFilter; | ||
import io.camunda.zeebe.client.ZeebeClient; | ||
import io.camunda.zeebe.client.api.response.ProcessInstanceEvent; | ||
import io.camunda.zeebe.spring.client.EnableZeebeClient; | ||
import io.camunda.zeebe.spring.client.annotation.JobWorker; | ||
import io.camunda.zeebe.spring.client.annotation.Variable; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@SpringBootApplication | ||
@EnableZeebeClient | ||
public class Main { | ||
public static void main(String[] args) { | ||
SpringApplication.run(Main.class); | ||
} | ||
|
||
private static Logger LOG = LoggerFactory.getLogger(Main.class); | ||
|
||
@Autowired | ||
ZeebeClient client; | ||
@Autowired | ||
CamundaOperateClient operate; | ||
|
||
@JobWorker | ||
public Map<String, Object> fetchInstances(@Variable String bpmnProcessId) throws OperateException { | ||
List<Long> processInstanceIds = new ArrayList<>(); | ||
ProcessDefinitionFilter filter = new ProcessDefinitionFilter.Builder().bpmnProcessId(bpmnProcessId).build(); | ||
Sort sort = new Sort("version", SortOrder.DESC); | ||
SearchQuery query = new SearchQuery.Builder().filter(filter).sort(sort).build(); | ||
List<ProcessDefinition> definitions = operate.searchProcessDefinitions(query); | ||
LOG.info("Found {} versions of process {}", definitions.size(), bpmnProcessId); | ||
if (definitions.size() >= 2) { | ||
ProcessInstanceFilter instanceFilter = new ProcessInstanceFilter.Builder().bpmnProcessId(bpmnProcessId).processVersion(definitions.get(1).getVersion()).state( | ||
ProcessInstanceState.ACTIVE).build(); | ||
processInstanceIds = operate.searchProcessInstances(new SearchQuery.Builder().filter(instanceFilter).build()).stream() | ||
.map(ProcessInstance::getKey).toList(); | ||
} | ||
LOG.info("{} process instances will be migrated to latest version", processInstanceIds.size()); | ||
return Map.of("processInstanceKeys", processInstanceIds); | ||
} | ||
|
||
@JobWorker | ||
public Map<String, Object> startInstance(@Variable Long processInstanceKey, @Variable String bpmnProcessId, @Variable String startBeforeElement) | ||
throws OperateException { | ||
Map<String, Object> variables = new HashMap<>(); | ||
VariableFilter filter = new VariableFilter.Builder().processInstanceKey(processInstanceKey).build(); | ||
List<io.camunda.operate.dto.Variable> vars = operate.searchVariables(new SearchQuery.Builder().filter(filter).build()); | ||
vars.forEach(var -> { | ||
if (var.getTruncated()) { | ||
try { | ||
io.camunda.operate.dto.Variable fullVar = operate.getVariable(var.getKey()); | ||
variables.put(fullVar.getName(), fullVar.getValue()); | ||
} catch (OperateException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} else { | ||
variables.put(var.getName(), var.getValue()); | ||
} | ||
}); | ||
variables.put("oldInstanceKey", processInstanceKey); | ||
ProcessInstanceEvent newInstance = client.newCreateInstanceCommand() | ||
.bpmnProcessId(bpmnProcessId) | ||
.latestVersion() | ||
.startBeforeElement(startBeforeElement) | ||
.variables(variables) | ||
.send() | ||
.join(); | ||
LOG.info("Migration of instance {} completed. New instance ID is {}.", processInstanceKey, newInstance.getProcessInstanceKey()); | ||
return Map.of("newInstanceKey", newInstance.getProcessInstanceKey()); | ||
} | ||
|
||
@JobWorker | ||
public void deleteOldInstance(@Variable Long processInstanceKey) { | ||
client.newCancelInstanceCommand(processInstanceKey).send().join(); | ||
LOG.info("Instance {} has been cancelled, because it has been migrated to a new process model version.", processInstanceKey); | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
c8-1-instance-migration/src/main/java/com/camunda/consulting/OperateClientConfiguration.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,72 @@ | ||
package com.camunda.consulting; | ||
|
||
import io.camunda.operate.CamundaOperateClient; | ||
import io.camunda.operate.auth.AuthInterface; | ||
import io.camunda.operate.auth.SaasAuthentication; | ||
import io.camunda.operate.auth.SelfManagedAuthentication; | ||
import io.camunda.operate.auth.SimpleAuthentication; | ||
import io.camunda.operate.exception.OperateException; | ||
import io.camunda.zeebe.spring.client.annotation.Deployment; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import java.util.Objects; | ||
|
||
@Configuration | ||
@Deployment(resources = {"classpath:c8-to-c8-instance_migration.bpmn"}) | ||
public class OperateClientConfiguration { | ||
@Value("${operate.keycloak.url:#{null}}") | ||
String keycloakUrl; | ||
@Value("${zeebe.client.cloud.client-id:#{null}}") | ||
String clientId; | ||
|
||
@Value("${zeebe.client.cloud.client-secret:#{null}}") | ||
String clientSecret; | ||
|
||
@Value("${operate.baseUrl:operate.camunda.io}") | ||
String baseUrl; | ||
|
||
@Value("${operate.authUrl:https://login.cloud.camunda.io/oauth/token}") | ||
String authUrl; | ||
|
||
@Value("${operate.url:http://localhost:8081}") | ||
String operateUrl; | ||
|
||
@Value("${operate.user:demo}") | ||
String operateUsr; | ||
|
||
@Value("${operate.password:demo}") | ||
String password; | ||
|
||
@Value("${operate.keycloak.realm:camunda-platform}") | ||
String keycloakRealm; | ||
|
||
@Bean | ||
public CamundaOperateClient operate() { | ||
AuthInterface auth = null; | ||
if (Objects.nonNull(clientSecret) && Objects.nonNull(clientId)) { | ||
if (Objects.nonNull(keycloakUrl)) { | ||
auth = new SelfManagedAuthentication() | ||
.clientId(clientId) | ||
.clientSecret(clientSecret) | ||
.keycloakRealm(keycloakRealm) | ||
.keycloakUrl(keycloakUrl); | ||
} else { | ||
auth = new SaasAuthentication(authUrl, baseUrl, clientId, clientSecret); | ||
} | ||
} else { | ||
auth = new SimpleAuthentication(operateUsr, password, operateUrl); | ||
} | ||
CamundaOperateClient client = null; | ||
try { | ||
client = new CamundaOperateClient.Builder().operateUrl(operateUrl) | ||
.authentication(auth) | ||
.build(); | ||
} catch (OperateException e) { | ||
throw new RuntimeException(e); | ||
} | ||
return client; | ||
} | ||
} |
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,3 @@ | ||
zeebe.client: | ||
broker.gateway-address: 127.0.0.1:26500 | ||
security.plaintext: true |
Oops, something went wrong.