Skip to content

Commit 1e1fc48

Browse files
author
Camunda-ChrisAllen
committed
first commit
1 parent ca089bb commit 1e1fc48

38 files changed

+2198
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
## Use Case 1 - Using a Migration Island with Limited Batch Sizes
2+
3+
In this use case, we have a process that loses a User Task from version 1 to version 2.
4+
5+
**Version 1** looks like this. Notice on path 2 that there is a "User Task 0".
6+
7+
![src/main/resources/case1.png](src/main/resources/case1.png)
8+
9+
In **Version 2**, "user task 0" no longer exists, so we need to migrate all existing tokens on "user task 0" to "user task 2" over on path 3. The problem is that the development team is telling us that if we do this token migration directly then those process instances might not function properly. Some kind of "data massage" is required in order to make sure that migration from "user task 0" to "user task 2" happens without incident.
10+
11+
(NOTE: For the purposes of this exercise, the actual data that needs to be prepped for this to work correctly is irrelevant and out of scope. Let us just pretend that many things needs to be carefully changed for the migration to work correctly)
12+
13+
![src/main/resources/case1v2.png](src/main/resources/case1v2.png)
14+
15+
So the development team decides to use a "Migration Island" pattern for this migration. They will use the process migration functionality of Camunda to migrate tokens of "user task 0" from v1 to the "Migration Task" user task shown in version 2. The only purpose of this "island" is to accept tokens during a process migration process. The process model design should allow no other means to arrive at this island in the flow.
16+
17+
The DevOps team also has a concern during this migration. They are concerned that there might be over 50,000 instances to migrate on deployment night, and that the migration itself might cause unexpected load on the infrastructure. Therefore, they are asking the development team to migrate in controlled batches, setting a proper maximum number of process instances to migrate during each batch. For instance, let us say 500 at a time.
18+
19+
20+
21+
## Use Case 1 - Solution
22+
23+
The development team decides to create a process to handle the migration.
24+
25+
![](src/main/resources/migrate-case-1.png)
26+
27+
Migration is triggered by creating a process instance of this Migration process using the REST API. The payload that initializes process instance variables in our local example looks like this:
28+
29+
30+
31+
```
32+
{
33+
"variables": {
34+
"processDefKey": {
35+
"value": "use-case-1",
36+
"type": "String"
37+
},
38+
"fromVersion": {
39+
"value": 1,
40+
"type": "Integer"
41+
},
42+
"toVersion": {
43+
"value": 2,
44+
"type": "Integer"
45+
},
46+
"fromUserTaskKey": {
47+
"value": "user-task-0",
48+
"type": "String"
49+
},
50+
"toUserTaskKey": {
51+
"value": "migration-task",
52+
"type": "String"
53+
},
54+
"maxPerBatch": {
55+
"value": 50,
56+
"type": "Integer"
57+
},
58+
"skipIoMappings": {
59+
"value": true,
60+
"type": "Boolean"
61+
},
62+
"skipCustomListeners": {
63+
"value": true,
64+
"type": "Boolean"
65+
}
66+
}
67+
}
68+
```
69+
70+
Notice the "maxPerBatch" variable. In our local example, we will create 120 instances of version 1 with a token sitting on "user task 0". Then we will run this migration process, instructing it to migrate in batches of 50 at a time.
71+
72+
The migration process will loop for each batch of process instances to migrate. For each batch, it will:
73+
74+
- suspend the processes
75+
- execute the migration
76+
- activate the processes
77+
- using the API, complete the User migration task. This will trigger the "Prepare Data After Migration" service task, and allow the token to rest at it's final destination, the "user task 2" task.
78+
79+
### Steps to execute the solution locally
80+
81+
1. Start the Spring Boot application. The application class is CamundaApplication.java. Use either your IDE, or using maven with:
82+
83+
```
84+
mvn spring-boot:run
85+
```
86+
87+
This will start Camunda BPM, as well as auto-deploy the first version of the process (case1.bpmn).
88+
89+
2. Open Postman. Import the following 4 files into Postman. They are located in the src/test/resources directory:
90+
91+
![](src/main/resources/postman_1.png)
92+
93+
Once the environment file is loaded, make sure it is selected in your Postman IDE:
94+
95+
![](src/main/resources/postman_2.png)
96+
97+
Once all files are imported, you should see the following three collections:
98+
99+
![](src/main/resources/postman_3.png)
100+
101+
3. Notice that the "Step 1" collection for generating the data actually does the following:
102+
103+
- Starts a process instance that will go down path 1 after the gateway. That process will auto-complete.
104+
- Starts a process instance that will go down path 2 after the gateway. It will stop at "user task 1".
105+
- Get that task instance and complete it, to push the token to "user task 0".
106+
- Starts a process instance that will go down path 3, then push that token all the way to completion.
107+
108+
This means that every time we run this collection of calls, we will have two completed instances (path 1 and 3), and one incomplete instance with a token sitting at "user task 0".
109+
110+
We want to run this collection 120 times by using the Collection Runner. Select the "play" button in the upper right portion of the collection. It should take you to this interface:
111+
112+
![](src/main/resources/postman_4.png)
113+
114+
Select "Run", then enter "120" for iterations, with a delay of 20 milliseconds. Run the collection. When it is complete, log into Cockpit (http://localhost:8080/app/cockpit/default/) with demo/demo. Select the "use-case-1" process definition. You should see 120 tokens on "user task 0". If you are running Camunda EE and have History view, it should look like this:
115+
116+
![](src/main/resources/step1_complete.png)
117+
118+
4. In Postman, go to the "Deploy Version 2" request in the Step 2 collection. Select the "Body" tab of the request, and reload the file provided for the "data" parameter. It is the "case1_ver2_template.bpmn" file that is located in the root of the Spring Boot project. Once complete, select the "Save" button, then the "Run" button. This should deploy version 2 of the use-case-1 process. Confirm deployment by going into Cockpit to see both versions.
119+
120+
5. In Postman, go to the "Start process migrate-case-1" request in the "Case 1 - Step 3" collection. Run the request to start the migration. Observe the log in Spring Boot to watch the process navigation. When complete, go into Cockpit to see the results.
121+
122+
The migration should have run in three batches (50, 50, 20). History would show this:
123+
124+
![](src/main/resources/result_1.png)
125+
126+
127+
128+
Migration success would look like this:
129+
130+
131+
132+
![](src/main/resources/result-2.png)
133+
134+
135+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Camunda - Process Migration Patterns
2+
3+
The following example project shows how you can use the power of BPMN to handle more complex process version migration scenarios. To do that, we have created some examples of how you might build
4+
processes that migrate other processes from one version to another.
5+
6+
[Use Case 1 - Using a Migration Island with Limited Batch Sizes](Case1.md)
7+
8+
9+
10+
## Camunda Version
11+
12+
Spring Boot Application using [Camunda](http://docs.camunda.org).
13+
14+
This project has been generated by the Maven archetype
15+
[camunda-archetype-spring-boot-7.11.1](http://docs.camunda.org/latest/guides/user-guide/#process-applications-maven-project-templates-archetypes).
16+
17+
18+
19+
## How does it work? How to use it?
20+
21+
See the instructions on each individual Use Case.
22+
23+
24+
25+
## Environment Restrictions
26+
Built and tested against Camunda BPM version 7.11.0.
27+
28+
You must also use Postman in these examples.
29+
30+
31+
32+
## License
33+
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
34+
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.4.1">
3+
<bpmn:process id="use-case-1" name="use-case-1" isExecutable="true">
4+
<bpmn:startEvent id="StartEvent" name="Process&#10;started">
5+
<bpmn:extensionElements>
6+
<camunda:properties>
7+
<camunda:property name="simNextFire" value="${g.timesPerDay(&#34;processStarted&#34;,&#34;02:00&#34;,&#34;22:00&#34;, 77)}" />
8+
</camunda:properties>
9+
</bpmn:extensionElements>
10+
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
11+
</bpmn:startEvent>
12+
<bpmn:endEvent id="EndEvent" name="Process&#10;ended">
13+
<bpmn:incoming>SequenceFlow_06uzq6z</bpmn:incoming>
14+
</bpmn:endEvent>
15+
<bpmn:sequenceFlow id="SequenceFlow1" sourceRef="StartEvent" targetRef="ServiceTask_Logger" />
16+
<bpmn:sequenceFlow id="SequenceFlow_18o7zqy" sourceRef="ServiceTask_Logger" targetRef="ExclusiveGateway_0vgkf2i" />
17+
<bpmn:serviceTask id="ServiceTask_Logger" name="Log on console" camunda:delegateExpression="#{logger}">
18+
<bpmn:extensionElements>
19+
<camunda:properties>
20+
<camunda:property name="simGeneratePayload" value="mypath=${g.uniformFromArgs3(1,2,3)}" />
21+
</camunda:properties>
22+
</bpmn:extensionElements>
23+
<bpmn:incoming>SequenceFlow1</bpmn:incoming>
24+
<bpmn:outgoing>SequenceFlow_18o7zqy</bpmn:outgoing>
25+
</bpmn:serviceTask>
26+
<bpmn:exclusiveGateway id="ExclusiveGateway_0vgkf2i" name="which is mypath?" default="SequenceFlow_14cynn5">
27+
<bpmn:incoming>SequenceFlow_18o7zqy</bpmn:incoming>
28+
<bpmn:outgoing>SequenceFlow_14cynn5</bpmn:outgoing>
29+
<bpmn:outgoing>SequenceFlow_0ny8yfe</bpmn:outgoing>
30+
<bpmn:outgoing>SequenceFlow_163dgt3</bpmn:outgoing>
31+
</bpmn:exclusiveGateway>
32+
<bpmn:sequenceFlow id="SequenceFlow_14cynn5" name="1" sourceRef="ExclusiveGateway_0vgkf2i" targetRef="IntermediateThrowEvent_03ycj5s" />
33+
<bpmn:sequenceFlow id="SequenceFlow_0ny8yfe" name="2" sourceRef="ExclusiveGateway_0vgkf2i" targetRef="Task_0tmp1dk">
34+
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{mypath==2}</bpmn:conditionExpression>
35+
</bpmn:sequenceFlow>
36+
<bpmn:endEvent id="EndEvent_0tqk6qk">
37+
<bpmn:incoming>SequenceFlow_13t0dak</bpmn:incoming>
38+
</bpmn:endEvent>
39+
<bpmn:sequenceFlow id="SequenceFlow_1qmev44" sourceRef="Task_0tmp1dk" targetRef="Task_12d640m" />
40+
<bpmn:sequenceFlow id="SequenceFlow_163dgt3" name="3" sourceRef="ExclusiveGateway_0vgkf2i" targetRef="Task_1y0su7e">
41+
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{mypath==3}</bpmn:conditionExpression>
42+
</bpmn:sequenceFlow>
43+
<bpmn:endEvent id="EndEvent_102ggsf">
44+
<bpmn:incoming>SequenceFlow_18c5nog</bpmn:incoming>
45+
</bpmn:endEvent>
46+
<bpmn:sequenceFlow id="SequenceFlow_18c5nog" sourceRef="Task_1y0su7e" targetRef="EndEvent_102ggsf" />
47+
<bpmn:intermediateThrowEvent id="IntermediateThrowEvent_03ycj5s" name="do nothing">
48+
<bpmn:incoming>SequenceFlow_14cynn5</bpmn:incoming>
49+
<bpmn:outgoing>SequenceFlow_06uzq6z</bpmn:outgoing>
50+
</bpmn:intermediateThrowEvent>
51+
<bpmn:sequenceFlow id="SequenceFlow_06uzq6z" sourceRef="IntermediateThrowEvent_03ycj5s" targetRef="EndEvent" />
52+
<bpmn:userTask id="Task_0tmp1dk" name="user task 1">
53+
<bpmn:extensionElements>
54+
<camunda:properties>
55+
<camunda:property name="simNextFire" value="${g.nowPlusMinutes(g.uniformInt(1, 3))}" />
56+
</camunda:properties>
57+
</bpmn:extensionElements>
58+
<bpmn:incoming>SequenceFlow_0ny8yfe</bpmn:incoming>
59+
<bpmn:outgoing>SequenceFlow_1qmev44</bpmn:outgoing>
60+
</bpmn:userTask>
61+
<bpmn:userTask id="Task_1y0su7e" name="user task 2">
62+
<bpmn:extensionElements>
63+
<camunda:properties>
64+
<camunda:property name="simNextFire" value="${g.nowPlusMinutes(g.uniformInt(1, 3))}" />
65+
</camunda:properties>
66+
</bpmn:extensionElements>
67+
<bpmn:incoming>SequenceFlow_163dgt3</bpmn:incoming>
68+
<bpmn:outgoing>SequenceFlow_18c5nog</bpmn:outgoing>
69+
</bpmn:userTask>
70+
<bpmn:sequenceFlow id="SequenceFlow_13t0dak" sourceRef="Task_12d640m" targetRef="EndEvent_0tqk6qk" />
71+
<bpmn:userTask id="Task_12d640m" name="user task 0">
72+
<bpmn:incoming>SequenceFlow_1qmev44</bpmn:incoming>
73+
<bpmn:outgoing>SequenceFlow_13t0dak</bpmn:outgoing>
74+
</bpmn:userTask>
75+
</bpmn:process>
76+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
77+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="use-case-1">
78+
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent">
79+
<dc:Bounds x="173" y="102" width="36" height="36" />
80+
<bpmndi:BPMNLabel>
81+
<dc:Bounds x="171" y="138" width="41" height="24" />
82+
</bpmndi:BPMNLabel>
83+
</bpmndi:BPMNShape>
84+
<bpmndi:BPMNShape id="EndEvent_0fkea3f_di" bpmnElement="EndEvent">
85+
<dc:Bounds x="942" y="102" width="36" height="36" />
86+
<bpmndi:BPMNLabel>
87+
<dc:Bounds x="940" y="138" width="41" height="27" />
88+
</bpmndi:BPMNLabel>
89+
</bpmndi:BPMNShape>
90+
<bpmndi:BPMNEdge id="SequenceFlow_08va5r8_di" bpmnElement="SequenceFlow1">
91+
<di:waypoint x="209" y="120" />
92+
<di:waypoint x="337" y="120" />
93+
<bpmndi:BPMNLabel>
94+
<dc:Bounds x="228" y="95" width="90" height="20" />
95+
</bpmndi:BPMNLabel>
96+
</bpmndi:BPMNEdge>
97+
<bpmndi:BPMNEdge id="SequenceFlow_18o7zqy_di" bpmnElement="SequenceFlow_18o7zqy">
98+
<di:waypoint x="437" y="120" />
99+
<di:waypoint x="545" y="120" />
100+
<bpmndi:BPMNLabel>
101+
<dc:Bounds x="496.5" y="99" width="0" height="12" />
102+
</bpmndi:BPMNLabel>
103+
</bpmndi:BPMNEdge>
104+
<bpmndi:BPMNShape id="ServiceTask_16vok30_di" bpmnElement="ServiceTask_Logger">
105+
<dc:Bounds x="337" y="80" width="100" height="80" />
106+
</bpmndi:BPMNShape>
107+
<bpmndi:BPMNShape id="ExclusiveGateway_0vgkf2i_di" bpmnElement="ExclusiveGateway_0vgkf2i" isMarkerVisible="true">
108+
<dc:Bounds x="545" y="95" width="50" height="50" />
109+
<bpmndi:BPMNLabel>
110+
<dc:Bounds x="528" y="65" width="84" height="14" />
111+
</bpmndi:BPMNLabel>
112+
</bpmndi:BPMNShape>
113+
<bpmndi:BPMNEdge id="SequenceFlow_14cynn5_di" bpmnElement="SequenceFlow_14cynn5">
114+
<di:waypoint x="595" y="120" />
115+
<di:waypoint x="702" y="120" />
116+
<bpmndi:BPMNLabel>
117+
<dc:Bounds x="607" y="102" width="6" height="14" />
118+
</bpmndi:BPMNLabel>
119+
</bpmndi:BPMNEdge>
120+
<bpmndi:BPMNEdge id="SequenceFlow_0ny8yfe_di" bpmnElement="SequenceFlow_0ny8yfe">
121+
<di:waypoint x="570" y="145" />
122+
<di:waypoint x="570" y="250" />
123+
<di:waypoint x="650" y="250" />
124+
<bpmndi:BPMNLabel>
125+
<dc:Bounds x="607" y="223" width="6" height="14" />
126+
</bpmndi:BPMNLabel>
127+
</bpmndi:BPMNEdge>
128+
<bpmndi:BPMNShape id="EndEvent_0tqk6qk_di" bpmnElement="EndEvent_0tqk6qk">
129+
<dc:Bounds x="942" y="232" width="36" height="36" />
130+
</bpmndi:BPMNShape>
131+
<bpmndi:BPMNEdge id="SequenceFlow_1qmev44_di" bpmnElement="SequenceFlow_1qmev44">
132+
<di:waypoint x="750" y="250" />
133+
<di:waypoint x="790" y="250" />
134+
</bpmndi:BPMNEdge>
135+
<bpmndi:BPMNEdge id="SequenceFlow_163dgt3_di" bpmnElement="SequenceFlow_163dgt3">
136+
<di:waypoint x="570" y="145" />
137+
<di:waypoint x="570" y="390" />
138+
<di:waypoint x="650" y="390" />
139+
<bpmndi:BPMNLabel>
140+
<dc:Bounds x="607" y="363" width="6" height="14" />
141+
</bpmndi:BPMNLabel>
142+
</bpmndi:BPMNEdge>
143+
<bpmndi:BPMNShape id="EndEvent_102ggsf_di" bpmnElement="EndEvent_102ggsf">
144+
<dc:Bounds x="942" y="372" width="36" height="36" />
145+
</bpmndi:BPMNShape>
146+
<bpmndi:BPMNEdge id="SequenceFlow_18c5nog_di" bpmnElement="SequenceFlow_18c5nog">
147+
<di:waypoint x="750" y="390" />
148+
<di:waypoint x="942" y="390" />
149+
</bpmndi:BPMNEdge>
150+
<bpmndi:BPMNShape id="IntermediateThrowEvent_03ycj5s_di" bpmnElement="IntermediateThrowEvent_03ycj5s">
151+
<dc:Bounds x="702" y="102" width="36" height="36" />
152+
<bpmndi:BPMNLabel>
153+
<dc:Bounds x="694" y="145" width="52" height="14" />
154+
</bpmndi:BPMNLabel>
155+
</bpmndi:BPMNShape>
156+
<bpmndi:BPMNEdge id="SequenceFlow_06uzq6z_di" bpmnElement="SequenceFlow_06uzq6z">
157+
<di:waypoint x="738" y="120" />
158+
<di:waypoint x="942" y="120" />
159+
</bpmndi:BPMNEdge>
160+
<bpmndi:BPMNShape id="UserTask_1b9nosk_di" bpmnElement="Task_0tmp1dk">
161+
<dc:Bounds x="650" y="210" width="100" height="80" />
162+
</bpmndi:BPMNShape>
163+
<bpmndi:BPMNShape id="UserTask_1yelxq1_di" bpmnElement="Task_1y0su7e">
164+
<dc:Bounds x="650" y="350" width="100" height="80" />
165+
</bpmndi:BPMNShape>
166+
<bpmndi:BPMNEdge id="SequenceFlow_13t0dak_di" bpmnElement="SequenceFlow_13t0dak">
167+
<di:waypoint x="890" y="250" />
168+
<di:waypoint x="942" y="250" />
169+
</bpmndi:BPMNEdge>
170+
<bpmndi:BPMNShape id="UserTask_0ooe9qj_di" bpmnElement="Task_12d640m">
171+
<dc:Bounds x="790" y="210" width="100" height="80" />
172+
</bpmndi:BPMNShape>
173+
</bpmndi:BPMNPlane>
174+
</bpmndi:BPMNDiagram>
175+
</bpmn:definitions>

0 commit comments

Comments
 (0)