Skip to content

Commit 7239c16

Browse files
committed
Unacquiring external worker job should unlock the exclusive scope if the external worker job is exclusive
1 parent aafd130 commit 7239c16

File tree

5 files changed

+211
-0
lines changed

5 files changed

+211
-0
lines changed

modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/externalworker/ExternalWorkerServiceTaskTest.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,62 @@ public void testCaseInstanceIsNotLockedByNotExclusiveJob() {
10271027
assertThat(caseInstance.getLockTime()).isNull();
10281028
}
10291029

1030+
@Test
1031+
@CmmnDeployment(resources = "org/flowable/cmmn/test/externalworker/ExternalWorkerServiceTaskTest.testSimpleExclusive.cmmn")
1032+
public void testCaseInstanceIsUnlockedWhenUnacquiringExclusiveJob() {
1033+
cmmnRuntimeService.createCaseInstanceBuilder()
1034+
.caseDefinitionKey("simpleExternalWorker")
1035+
.variable("name", "kermit")
1036+
.start();
1037+
1038+
List<AcquiredExternalWorkerJob> acquiredJobs = cmmnManagementService.createExternalWorkerJobAcquireBuilder()
1039+
.topic("simple", Duration.ofHours(1))
1040+
.acquireAndLock(1, "worker1");
1041+
1042+
AcquiredExternalWorkerJob acquiredJob = acquiredJobs.get(0);
1043+
1044+
assertThat(acquiredJob.getLockOwner()).isEqualTo("worker1");
1045+
assertThat(acquiredJob.getLockExpirationTime()).isNotNull();
1046+
1047+
CaseInstanceEntity caseInstance = (CaseInstanceEntity) cmmnRuntimeService.createCaseInstanceQuery()
1048+
.caseInstanceId(acquiredJob.getScopeId())
1049+
.singleResult();
1050+
1051+
assertThat(caseInstance.getLockOwner()).isEqualTo("worker1");
1052+
assertThat(caseInstance.getLockTime()).isNotNull();
1053+
1054+
acquiredJobs = cmmnManagementService.createExternalWorkerJobAcquireBuilder()
1055+
.topic("simple", Duration.ofHours(1))
1056+
.acquireAndLock(1, "worker1");
1057+
1058+
assertThat(acquiredJobs).isEmpty();
1059+
1060+
cmmnManagementService.unacquireExternalWorkerJob(acquiredJob.getId(), "worker1");
1061+
1062+
caseInstance = (CaseInstanceEntity) cmmnRuntimeService.createCaseInstanceQuery()
1063+
.caseInstanceId(acquiredJob.getScopeId())
1064+
.singleResult();
1065+
1066+
assertThat(caseInstance.getLockOwner()).isNull();
1067+
assertThat(caseInstance.getLockTime()).isNull();
1068+
1069+
acquiredJobs = cmmnManagementService.createExternalWorkerJobAcquireBuilder()
1070+
.topic("simple", Duration.ofHours(1))
1071+
.acquireAndLock(1, "worker1");
1072+
1073+
acquiredJob = acquiredJobs.get(0);
1074+
1075+
assertThat(acquiredJob.getLockOwner()).isEqualTo("worker1");
1076+
assertThat(acquiredJob.getLockExpirationTime()).isNotNull();
1077+
1078+
caseInstance = (CaseInstanceEntity) cmmnRuntimeService.createCaseInstanceQuery()
1079+
.caseInstanceId(acquiredJob.getScopeId())
1080+
.singleResult();
1081+
1082+
assertThat(caseInstance.getLockOwner()).isEqualTo("worker1");
1083+
assertThat(caseInstance.getLockTime()).isNotNull();
1084+
}
1085+
10301086
@Test
10311087
@CmmnDeployment(resources = "org/flowable/cmmn/test/externalworker/ExternalWorkerServiceTaskTest.testSimple.cmmn")
10321088
public void testCreateCmmnExternalWorkerJobInterceptor() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL" xmlns:flowable="http://flowable.org/cmmn"
3+
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI" xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
4+
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI" targetNamespace="http://flowable.org/cmmn">
5+
<case id="simpleExternalWorker" name="Simple External Worker">
6+
<casePlanModel id="onecaseplanmodel1" name="Case plan model">
7+
<planItem id="planItem1" name="External Worker" definitionRef="externalWorkerTask"/>
8+
<planItem id="planItem2" name="After External Worker Complete" definitionRef="afterExternalWorkerCompleteTask">
9+
<entryCriterion id="entryCriterion1" sentryRef="sentry1"/>
10+
</planItem>
11+
<planItem id="planItem3" name="After External Worker Terminate" definitionRef="afterExternalWorkerTerminateTask">
12+
<entryCriterion id="entryCriterion2" sentryRef="sentry2"/>
13+
</planItem>
14+
<sentry id="sentry1">
15+
<planItemOnPart id="sentryOnPart1" sourceRef="planItem1">
16+
<standardEvent>complete</standardEvent>
17+
</planItemOnPart>
18+
</sentry>
19+
<sentry id="sentry2">
20+
<planItemOnPart id="sentryOnPart2" sourceRef="planItem1">
21+
<standardEvent>terminate</standardEvent>
22+
</planItemOnPart>
23+
</sentry>
24+
<task id="externalWorkerTask" name="External Worker" flowable:type="external-worker" flowable:exclusive="true" flowable:topic="simple"/>
25+
<humanTask id="afterExternalWorkerCompleteTask" name="After External Worker Complete"/>
26+
<humanTask id="afterExternalWorkerTerminateTask" name="After External Worker Terminate"/>
27+
</casePlanModel>
28+
</case>
29+
<cmmndi:CMMNDI>
30+
<cmmndi:CMMNDiagram id="CMMNDiagram_simpleExternalWorker">
31+
<cmmndi:CMMNShape id="CMMNShape_onecaseplanmodel1" cmmnElementRef="onecaseplanmodel1">
32+
<dc:Bounds height="754.0" width="758.0" x="30.0" y="45.0"/>
33+
<cmmndi:CMMNLabel/>
34+
</cmmndi:CMMNShape>
35+
<cmmndi:CMMNShape id="CMMNShape_planItem1" cmmnElementRef="planItem1">
36+
<dc:Bounds height="80.0" width="100.0" x="136.0" y="256.0"/>
37+
<cmmndi:CMMNLabel/>
38+
</cmmndi:CMMNShape>
39+
<cmmndi:CMMNShape id="CMMNShape_planItem2" cmmnElementRef="planItem2">
40+
<dc:Bounds height="80.0" width="100.0" x="391.0" y="136.0"/>
41+
<cmmndi:CMMNLabel/>
42+
</cmmndi:CMMNShape>
43+
<cmmndi:CMMNShape id="CMMNShape_entryCriterion1" cmmnElementRef="entryCriterion1">
44+
<dc:Bounds height="28.0" width="18.0" x="382.0" y="162.0"/>
45+
<cmmndi:CMMNLabel/>
46+
</cmmndi:CMMNShape>
47+
<cmmndi:CMMNShape id="CMMNShape_planItem3" cmmnElementRef="planItem3">
48+
<dc:Bounds height="80.0" width="100.0" x="391.0" y="406.0"/>
49+
<cmmndi:CMMNLabel/>
50+
</cmmndi:CMMNShape>
51+
<cmmndi:CMMNShape id="CMMNShape_entryCriterion2" cmmnElementRef="entryCriterion2">
52+
<dc:Bounds height="28.0" width="18.0" x="382.0" y="450.0"/>
53+
<cmmndi:CMMNLabel/>
54+
</cmmndi:CMMNShape>
55+
<cmmndi:CMMNEdge id="CMMNEdge_connector1" cmmnElementRef="planItem1" targetCMMNElementRef="entryCriterion1">
56+
<di:waypoint x="186.0" y="256.0"/>
57+
<di:waypoint x="186.0" y="176.0"/>
58+
<di:waypoint x="382.0" y="176.0"/>
59+
<cmmndi:CMMNLabel/>
60+
</cmmndi:CMMNEdge>
61+
<cmmndi:CMMNEdge id="CMMNEdge_connector2" cmmnElementRef="planItem1" targetCMMNElementRef="entryCriterion2">
62+
<di:waypoint x="186.0" y="335.95000000000005"/>
63+
<di:waypoint x="186.0" y="464.0"/>
64+
<di:waypoint x="382.0" y="464.0"/>
65+
<cmmndi:CMMNLabel/>
66+
</cmmndi:CMMNEdge>
67+
</cmmndi:CMMNDiagram>
68+
</cmmndi:CMMNDI>
69+
</definitions>

modules/flowable-engine/src/test/java/org/flowable/engine/test/externalworker/ExternalWorkerServiceTaskTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,63 @@ void testProcessInstanceIsNotLockedByNotExclusiveJob() {
10431043
assertThat(processInstance.getLockTime()).isNull();
10441044
}
10451045

1046+
@Test
1047+
@Deployment(resources = "org/flowable/engine/test/externalworker/ExternalWorkerServiceTaskTest.testSimpleExclusive.bpmn20.xml")
1048+
void testProcessInstanceIsUnlockedWhenUnacquiringExclusiveJob() {
1049+
runtimeService.createProcessInstanceBuilder()
1050+
.processDefinitionKey("simpleExternalWorker")
1051+
.variable("name", "kermit")
1052+
.start();
1053+
1054+
List<AcquiredExternalWorkerJob> acquiredJobs = managementService.createExternalWorkerJobAcquireBuilder()
1055+
.topic("simple", Duration.ofHours(1))
1056+
.acquireAndLock(1, "worker1");
1057+
1058+
AcquiredExternalWorkerJob acquiredJob = acquiredJobs.get(0);
1059+
1060+
assertThat(acquiredJob.getLockOwner()).isEqualTo("worker1");
1061+
assertThat(acquiredJob.getLockExpirationTime()).isNotNull();
1062+
1063+
ExecutionEntity processInstance = (ExecutionEntity) runtimeService.createProcessInstanceQuery()
1064+
.processInstanceId(acquiredJob.getProcessInstanceId())
1065+
.singleResult();
1066+
1067+
assertThat(processInstance.getLockOwner()).isEqualTo("worker1");
1068+
assertThat(processInstance.getLockTime()).isNotNull();
1069+
1070+
acquiredJobs = managementService.createExternalWorkerJobAcquireBuilder()
1071+
.topic("simple", Duration.ofHours(1))
1072+
.acquireAndLock(1, "worker1");
1073+
1074+
assertThat(acquiredJobs).isEmpty();
1075+
1076+
managementService.unacquireExternalWorkerJob(acquiredJob.getId(), "worker1");
1077+
1078+
processInstance = (ExecutionEntity) runtimeService.createProcessInstanceQuery()
1079+
.processInstanceId(acquiredJob.getProcessInstanceId())
1080+
.singleResult();
1081+
1082+
assertThat(processInstance.getLockOwner()).isNull();
1083+
assertThat(processInstance.getLockTime()).isNull();
1084+
1085+
acquiredJobs = managementService.createExternalWorkerJobAcquireBuilder()
1086+
.topic("simple", Duration.ofHours(1))
1087+
.acquireAndLock(1, "worker1");
1088+
1089+
acquiredJob = acquiredJobs.get(0);
1090+
1091+
assertThat(acquiredJob.getLockOwner()).isEqualTo("worker1");
1092+
assertThat(acquiredJob.getLockExpirationTime()).isNotNull();
1093+
1094+
processInstance = (ExecutionEntity) runtimeService.createProcessInstanceQuery()
1095+
.processInstanceId(acquiredJob.getProcessInstanceId())
1096+
.singleResult();
1097+
1098+
assertThat(processInstance.getLockOwner()).isEqualTo("worker1");
1099+
assertThat(processInstance.getLockTime()).isNotNull();
1100+
1101+
}
1102+
10461103
@Test
10471104
@Deployment(resources = "org/flowable/engine/test/externalworker/ExternalWorkerServiceTaskTest.testSimple.bpmn20.xml")
10481105
void testCreateExternalWorkerJobInterceptor() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions id="definitions"
3+
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
4+
xmlns:flowable="http://flowable.org/bpmn"
5+
targetNamespace="Examples"
6+
>
7+
8+
<process id="simpleExternalWorker">
9+
10+
<startEvent id="theStart"/>
11+
12+
<sequenceFlow sourceRef="theStart" targetRef="externalWorkerTask"/>
13+
14+
<serviceTask id="externalWorkerTask" flowable:type="external-worker" flowable:exclusive="true" flowable:topic="simple"/>
15+
16+
<sequenceFlow sourceRef="externalWorkerTask" targetRef="taskAfter"/>
17+
18+
<userTask id="taskAfter"/>
19+
20+
<sequenceFlow sourceRef="taskAfter" targetRef="theEnd"/>
21+
22+
<endEvent id="theEnd"/>
23+
24+
</process>
25+
26+
</definitions>

modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/UnacquireExternalWorkerJobCmd.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public Void execute(CommandContext commandContext) {
5757
jobEntity.setLockExpirationTime(null);
5858
jobEntity.setLockOwner(null);
5959
externalWorkerJobEntityManager.update(jobEntity);
60+
if (jobEntity.isExclusive()) {
61+
new UnlockExclusiveJobCmd(jobEntity, jobServiceConfiguration).execute(commandContext);
62+
}
6063

6164
return null;
6265
}

0 commit comments

Comments
 (0)