Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.67.x] [kie-issues-509] Handle SLA timers during process instance migration #2328

Merged
merged 1 commit into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -401,9 +401,9 @@ public void removeEventListeners() {
}

@Override
protected void triggerCompleted(String type, boolean remove) {
if (this.slaCompliance == org.kie.api.runtime.process.ProcessInstance.SLA_PENDING) {
if (System.currentTimeMillis() > slaDueDate.getTime()) {
protected void triggerCompleted(String type, boolean remove) {
if (this.slaCompliance == org.kie.api.runtime.process.ProcessInstance.SLA_PENDING) {
if (System.currentTimeMillis() > slaDueDate.getTime()) {
// completion of the node instance is after expected SLA due date, mark it accordingly
this.slaCompliance = org.kie.api.runtime.process.ProcessInstance.SLA_VIOLATED;
} else {
Expand Down

Large diffs are not rendered by default.

Expand Up @@ -41,6 +41,7 @@
import org.jbpm.services.task.identity.JBossUserGroupCallbackImpl;
import org.jbpm.services.task.impl.TaskDeadlinesServiceImpl;
import org.jbpm.test.listener.process.NodeLeftCountDownProcessEventListener;
import org.jbpm.test.listener.process.SLAViolationCountDownProcessEventListener;
import org.jbpm.test.util.AbstractBaseTest;
import org.junit.After;
import org.junit.Before;
Expand Down Expand Up @@ -114,6 +115,13 @@ public TimerMigrationManagerTest(String strategy) {

private static final String USERTASK_BOUNDARY_TIMER_ID_V1 = "UserTaskBoundary-v1";
private static final String USERTASK_BOUNDARY_TIMER_ID_V2 = "UserTaskBoundary-v2";

private static final String USERTASK_SLA_ID_V1 = "BPMN2-UserTaskSLA-v1";
private static final String USERTASK_SLA_ID_V2 = "BPMN2-UserTaskSLA-v2";

private static final String PROCESS_SLA_ID_V1 = "BPMN2-ProcessSLA-v1";
private static final String PROCESS_SLA_ID_V2 = "BPMN2-ProcessSLA-v2";

private JPAAuditLogService auditService;
private RuntimeEngine runtime;
private long pid;
Expand Down Expand Up @@ -298,7 +306,7 @@ public void testMigrateEventSubprocessTimerProcessInstance() throws Exception {
}

@SuppressWarnings({"unchecked", "rawtypes"})
@Test(timeout=10000)
@Test//(timeout=10000)
public void testMigrateTimerProcessInstanceRollback() throws Exception {
NodeLeftCountDownProcessEventListener countdownListener = new NodeLeftCountDownProcessEventListener("Event", 1);
createRuntimeManagers("migration/v1/BPMN2-Timer-v1.bpmn2", "migration/v2/BPMN2-Timer-v2.bpmn2", countdownListener);
Expand Down Expand Up @@ -590,6 +598,104 @@ public void testMigrateUserTaskNotCompletedBoundaryTimerProcessInstance() throws
checkProcessCompleted(countdownListener);
}

@Test(timeout=10000)
public void testUserTaskSLA() throws Exception {
SLAViolationCountDownProcessEventListener countdownListener = new SLAViolationCountDownProcessEventListener(1);
createRuntimeManagers("migration/v1/BPMN2-UserTaskSLA-v1.bpmn2", "migration/v2/BPMN2-UserTaskSLA-v2.bpmn2", countdownListener);
assertNotNull(managerV1);
assertNotNull(managerV2);

RuntimeEngine runtime = managerV1.getRuntimeEngine(EmptyContext.get());
KieSession ksession = runtime.getKieSession();
assertNotNull(ksession);

ProcessInstance pi1 = ksession.startProcess(USERTASK_SLA_ID_V1);
assertNotNull(pi1);
assertEquals(ProcessInstance.STATE_ACTIVE, pi1.getState());
JPAAuditLogService auditService = new JPAAuditLogService(emf);
ProcessInstanceLog log = auditService.findProcessInstance(pi1.getId());
assertNotNull(log);
assertEquals(USERTASK_SLA_ID_V1, log.getProcessId());
assertEquals(DEPLOYMENT_ID_V1, log.getExternalId());

managerV1.disposeRuntimeEngine(runtime);

MigrationSpec migrationSpec = new MigrationSpec(DEPLOYMENT_ID_V1, pi1.getId(), DEPLOYMENT_ID_V2, USERTASK_SLA_ID_V2);

MigrationManager migrationManager = new MigrationManager(migrationSpec);
MigrationReport report = migrationManager.migrate();

assertNotNull(report);
assertTrue(report.isSuccessful());

log = auditService.findProcessInstance(pi1.getId());
assertNotNull(log);
assertEquals(USERTASK_SLA_ID_V2, log.getProcessId());
assertEquals(DEPLOYMENT_ID_V2, log.getExternalId());
assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue());


// wait till timer fires
countdownListener.waitTillCompleted();

log = auditService.findProcessInstance(pi1.getId());
auditService.dispose();
assertNotNull(log);
assertEquals(USERTASK_SLA_ID_V2, log.getProcessId());
assertEquals(DEPLOYMENT_ID_V2, log.getExternalId());
assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue());

}

@Test(timeout=10000)
public void testProcessSLA() throws Exception {
SLAViolationCountDownProcessEventListener countdownListener = new SLAViolationCountDownProcessEventListener(1);
createRuntimeManagers("migration/v1/BPMN2-ProcessSLA-v1.bpmn2", "migration/v2/BPMN2-ProcessSLA-v2.bpmn2", countdownListener);
assertNotNull(managerV1);
assertNotNull(managerV2);

RuntimeEngine runtime = managerV1.getRuntimeEngine(EmptyContext.get());
KieSession ksession = runtime.getKieSession();
assertNotNull(ksession);

ProcessInstance pi1 = ksession.startProcess(PROCESS_SLA_ID_V1);
assertNotNull(pi1);
assertEquals(ProcessInstance.STATE_ACTIVE, pi1.getState());
JPAAuditLogService auditService = new JPAAuditLogService(emf);
ProcessInstanceLog log = auditService.findProcessInstance(pi1.getId());
assertNotNull(log);
assertEquals(PROCESS_SLA_ID_V1, log.getProcessId());
assertEquals(DEPLOYMENT_ID_V1, log.getExternalId());

managerV1.disposeRuntimeEngine(runtime);

MigrationSpec migrationSpec = new MigrationSpec(DEPLOYMENT_ID_V1, pi1.getId(), DEPLOYMENT_ID_V2, PROCESS_SLA_ID_V2);

MigrationManager migrationManager = new MigrationManager(migrationSpec);
MigrationReport report = migrationManager.migrate();

assertNotNull(report);
assertTrue(report.isSuccessful());

log = auditService.findProcessInstance(pi1.getId());
assertNotNull(log);
assertEquals(PROCESS_SLA_ID_V2, log.getProcessId());
assertEquals(DEPLOYMENT_ID_V2, log.getExternalId());
assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue());


// wait till timer fires
countdownListener.waitTillCompleted();

log = auditService.findProcessInstance(pi1.getId());
auditService.dispose();
assertNotNull(log);
assertEquals(PROCESS_SLA_ID_V2, log.getProcessId());
assertEquals(DEPLOYMENT_ID_V2, log.getExternalId());
assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue());

}

protected void createRuntimeManagers(String processV1, String processV2, ProcessEventListener...eventListeners) {
RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultBuilder()
Expand Down
@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:bpsim="http://www.bpsim.org/schemas/1.0" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:drools="http://www.jboss.org/drools" id="_xI_0QCs8EDy3G-EZm5NgUw" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd http://www.jboss.org/drools drools.xsd http://www.bpsim.org/schemas/1.0 bpsim.xsd http://www.omg.org/spec/DD/20100524/DC DC.xsd http://www.omg.org/spec/DD/20100524/DI DI.xsd " exporter="jBPM Process Modeler" exporterVersion="2.0" targetNamespace="http://www.omg.org/bpmn20">
<bpmn2:itemDefinition id="__2_SkippableInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_PriorityInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_CommentInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_DescriptionInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_CreatedByInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_TaskNameInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_GroupIdInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_ContentInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_NotStartedReassignInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_NotCompletedReassignInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_NotStartedNotifyInputXItem" structureRef="Object"/>
<bpmn2:itemDefinition id="__2_NotCompletedNotifyInputXItem" structureRef="Object"/>
<bpmn2:collaboration id="_5D1B7000-A31C-473F-A542-0A70E294AD83" name="Default Collaboration">
<bpmn2:participant id="_12CADCE6-BF64-4B86-BD88-8CEE522EDFC2" name="Pool Participant" processRef="BPMN2_ProcessSLA_v1"/>
</bpmn2:collaboration>
<bpmn2:process id="BPMN2-ProcessSLA-v1" drools:packageName="com.example" drools:version="1.0" drools:adHoc="false" name="BPMN2-ProcessSLA-v1" isExecutable="true" processType="Private">
<bpmn2:extensionElements>
<drools:metaData name="customSLADueDate">
<drools:metaValue><![CDATA[PT5S]]></drools:metaValue>
</drools:metaData>
</bpmn2:extensionElements>
<bpmn2:sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2"/>
<bpmn2:sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3"/>
<bpmn2:startEvent id="_1" name="StartProcess">
<bpmn2:extensionElements>
<drools:metaData name="elementname">
<drools:metaValue><![CDATA[StartProcess]]></drools:metaValue>
</drools:metaData>
</bpmn2:extensionElements>
<bpmn2:outgoing>_1-_2</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:userTask id="_2" name="Hello v1">
<bpmn2:extensionElements>
<drools:metaData name="elementname">
<drools:metaValue><![CDATA[Hello v1]]></drools:metaValue>
</drools:metaData>
</bpmn2:extensionElements>
<bpmn2:incoming>_1-_2</bpmn2:incoming>
<bpmn2:outgoing>_2-_3</bpmn2:outgoing>
<bpmn2:ioSpecification>
<bpmn2:dataInput id="_2_TaskNameInputX" drools:dtype="Object" itemSubjectRef="__2_TaskNameInputXItem" name="TaskName"/>
<bpmn2:dataInput id="_2_SkippableInputX" drools:dtype="Object" itemSubjectRef="__2_SkippableInputXItem" name="Skippable"/>
<bpmn2:inputSet>
<bpmn2:dataInputRefs>_2_TaskNameInputX</bpmn2:dataInputRefs>
<bpmn2:dataInputRefs>_2_SkippableInputX</bpmn2:dataInputRefs>
</bpmn2:inputSet>
</bpmn2:ioSpecification>
<bpmn2:dataInputAssociation>
<bpmn2:targetRef>_2_TaskNameInputX</bpmn2:targetRef>
<bpmn2:assignment>
<bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[Task]]></bpmn2:from>
<bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_TaskNameInputX]]></bpmn2:to>
</bpmn2:assignment>
</bpmn2:dataInputAssociation>
<bpmn2:dataInputAssociation>
<bpmn2:targetRef>_2_SkippableInputX</bpmn2:targetRef>
<bpmn2:assignment>
<bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[false]]></bpmn2:from>
<bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_SkippableInputX]]></bpmn2:to>
</bpmn2:assignment>
</bpmn2:dataInputAssociation>
<bpmn2:potentialOwner id="_xJEFsCs8EDy3G-EZm5NgUw">
<bpmn2:resourceAssignmentExpression id="_xJEFsSs8EDy3G-EZm5NgUw">
<bpmn2:formalExpression>john</bpmn2:formalExpression>
</bpmn2:resourceAssignmentExpression>
</bpmn2:potentialOwner>
</bpmn2:userTask>
<bpmn2:endEvent id="_3" name="EndProcess">
<bpmn2:extensionElements>
<drools:metaData name="elementname">
<drools:metaValue><![CDATA[EndProcess]]></drools:metaValue>
</drools:metaData>
</bpmn2:extensionElements>
<bpmn2:incoming>_2-_3</bpmn2:incoming>
<bpmn2:terminateEventDefinition/>
</bpmn2:endEvent>
</bpmn2:process>
<bpmndi:BPMNDiagram>
<bpmndi:BPMNPlane bpmnElement="BPMN2_ProcessSLA_v1">
<bpmndi:BPMNShape id="shape__3" bpmnElement="_3">
<dc:Bounds height="56" width="56" x="228" y="16"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape__2" bpmnElement="_2">
<dc:Bounds height="48" width="100" x="96" y="16"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape__1" bpmnElement="_1">
<dc:Bounds height="56" width="56" x="16" y="16"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge_shape__2_to_shape__3" bpmnElement="_2-_3">
<di:waypoint x="146" y="40"/>
<di:waypoint x="252" y="40"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="edge_shape__1_to_shape__2" bpmnElement="_1-_2">
<di:waypoint x="40" y="40"/>
<di:waypoint x="146" y="40"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
<bpmn2:relationship type="BPSimData">
<bpmn2:extensionElements>
<bpsim:BPSimData>
<bpsim:Scenario id="default" name="Simulationscenario">
<bpsim:ScenarioParameters/>
<bpsim:ElementParameters elementRef="_2">
<bpsim:TimeParameters>
<bpsim:ProcessingTime>
<bpsim:NormalDistribution mean="0" standardDeviation="0"/>
</bpsim:ProcessingTime>
</bpsim:TimeParameters>
<bpsim:ResourceParameters>
<bpsim:Availability>
<bpsim:FloatingParameter value="0"/>
</bpsim:Availability>
<bpsim:Quantity>
<bpsim:FloatingParameter value="0"/>
</bpsim:Quantity>
</bpsim:ResourceParameters>
<bpsim:CostParameters>
<bpsim:UnitCost>
<bpsim:FloatingParameter value="0"/>
</bpsim:UnitCost>
</bpsim:CostParameters>
</bpsim:ElementParameters>
<bpsim:ElementParameters elementRef="_1">
<bpsim:TimeParameters>
<bpsim:ProcessingTime>
<bpsim:NormalDistribution mean="0" standardDeviation="0"/>
</bpsim:ProcessingTime>
</bpsim:TimeParameters>
</bpsim:ElementParameters>
</bpsim:Scenario>
</bpsim:BPSimData>
</bpmn2:extensionElements>
<bpmn2:source>_xI_0QCs8EDy3G-EZm5NgUw</bpmn2:source>
<bpmn2:target>_xI_0QCs8EDy3G-EZm5NgUw</bpmn2:target>
</bpmn2:relationship>
</bpmn2:definitions>