Skip to content

Commit

Permalink
Fix deployment issue with getting a definition from the cache
Browse files Browse the repository at this point in the history
  • Loading branch information
tijsrademakers committed Apr 2, 2024
1 parent d3fabfd commit dbc8247
Show file tree
Hide file tree
Showing 34 changed files with 946 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,6 @@ protected void updateCachingAndArtifacts(AppDefinitionEntity appDefinition, AppM
appDefinitionCache.add(appDefinition.getId(), cacheEntry);

deployment.addDeployedArtifact(appDefinition);
deployment.addAppDefinitionCacheEntry(appDefinition.getId(), cacheEntry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public AppDefinitionCacheEntry resolveAppDefinition(AppDefinition appDefinition)
AppDeploymentEntity deployment = deploymentEntityManager.findById(deploymentId);
deployment.setNew(false);
deploy(deployment, null);
cachedAppDefinition = appDefinitionCache.get(appDefinitionId);
cachedAppDefinition = deployment.getAppDefinitionCacheEntry(appDefinitionId);

if (cachedAppDefinition == null) {
throw new FlowableException("deployment '" + deploymentId + "' didn't put app definition '" + appDefinitionId + "' in the cache");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Map;

import org.flowable.app.api.repository.AppDeployment;
import org.flowable.app.engine.impl.persistence.entity.deploy.AppDefinitionCacheEntry;
import org.flowable.common.engine.api.repository.EngineResource;
import org.flowable.common.engine.impl.persistence.entity.Entity;

Expand All @@ -32,6 +33,10 @@ public interface AppDeploymentEntity extends AppDeployment, Entity {
void addDeployedArtifact(Object deployedArtifact);

<T> List<T> getDeployedArtifacts(Class<T> clazz);

void addAppDefinitionCacheEntry(String appDefinitionId, AppDefinitionCacheEntry appDefinitionCacheEntry);

AppDefinitionCacheEntry getAppDefinitionCacheEntry(String appDefinitionId);

void setName(String name);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Map;

import org.flowable.app.engine.AppEngineConfiguration;
import org.flowable.app.engine.impl.persistence.entity.deploy.AppDefinitionCacheEntry;
import org.flowable.app.engine.impl.util.CommandContextUtil;
import org.flowable.common.engine.api.repository.EngineResource;

Expand All @@ -45,6 +46,7 @@ public class AppDeploymentEntityImpl extends AbstractAppEngineNoRevisionEntity i
* Will only be used during actual deployment to pass deployed artifacts (eg process definitions). Will be null otherwise.
*/
protected Map<Class<?>, List<Object>> deployedArtifacts;
protected Map<String, AppDefinitionCacheEntry> appDefinitionCache = new HashMap<>();

public AppDeploymentEntityImpl() {

Expand Down Expand Up @@ -106,6 +108,16 @@ public <T> List<T> getDeployedArtifacts(Class<T> clazz) {
}
return null;
}

@Override
public void addAppDefinitionCacheEntry(String appDefinitionId, AppDefinitionCacheEntry appDefinitionCacheEntry) {
appDefinitionCache.put(appDefinitionId, appDefinitionCacheEntry);
}

@Override
public AppDefinitionCacheEntry getAppDefinitionCacheEntry(String appDefinitionId) {
return appDefinitionCache.get(appDefinitionId);
}

// getters and setters ////////////////////////////////////////////////////////

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ protected void updateCachingAndArtifacts(CmmnParseResult parseResult) {
caseDefinitionCache.add(caseDefinitionEntity.getId(), cacheEntry);

deployment.addDeployedArtifact(caseDefinitionEntity);
deployment.addCaseDefinitionCacheEntry(caseDefinitionEntity.getId(), cacheEntry);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public CaseDefinitionCacheEntry resolveCaseDefinition(CaseDefinition caseDefinit
CmmnDeploymentEntity deployment = deploymentEntityManager.findById(deploymentId);
deployment.setNew(false);
deploy(deployment, null);
cachedCaseDefinition = caseDefinitionCache.get(caseDefinitionId);
cachedCaseDefinition = deployment.getCaseDefinitionCacheEntry(caseDefinitionId);

if (cachedCaseDefinition == null) {
throw new FlowableException("deployment '" + deploymentId + "' didn't put case definition '" + caseDefinitionId + "' in the cache");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Map;

import org.flowable.cmmn.api.repository.CmmnDeployment;
import org.flowable.cmmn.engine.impl.persistence.entity.deploy.CaseDefinitionCacheEntry;
import org.flowable.common.engine.api.repository.EngineResource;
import org.flowable.common.engine.impl.persistence.entity.Entity;

Expand All @@ -32,6 +33,10 @@ public interface CmmnDeploymentEntity extends CmmnDeployment, Entity {
void addDeployedArtifact(Object deployedArtifact);

<T> List<T> getDeployedArtifacts(Class<T> clazz);

void addCaseDefinitionCacheEntry(String caseDefinitionId, CaseDefinitionCacheEntry caseDefinitionCacheEntry);

CaseDefinitionCacheEntry getCaseDefinitionCacheEntry(String caseDefinitionId);

void setName(String name);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Map;

import org.flowable.cmmn.engine.CmmnEngineConfiguration;
import org.flowable.cmmn.engine.impl.persistence.entity.deploy.CaseDefinitionCacheEntry;
import org.flowable.cmmn.engine.impl.util.CommandContextUtil;
import org.flowable.common.engine.api.repository.EngineResource;

Expand All @@ -45,6 +46,7 @@ public class CmmnDeploymentEntityImpl extends AbstractCmmnEngineNoRevisionEntity
* Will only be used during actual deployment to pass deployed artifacts (eg process definitions). Will be null otherwise.
*/
protected Map<Class<?>, List<Object>> deployedArtifacts;
protected Map<String, CaseDefinitionCacheEntry> caseDefinitionCache = new HashMap<>();

public CmmnDeploymentEntityImpl() {

Expand Down Expand Up @@ -107,6 +109,16 @@ public <T> List<T> getDeployedArtifacts(Class<T> clazz) {
}
return null;
}

@Override
public void addCaseDefinitionCacheEntry(String caseDefinitionId, CaseDefinitionCacheEntry caseDefinitionCacheEntry) {
caseDefinitionCache.put(caseDefinitionId, caseDefinitionCacheEntry);
}

@Override
public CaseDefinitionCacheEntry getCaseDefinitionCacheEntry(String caseDefinitionId) {
return caseDefinitionCache.get(caseDefinitionId);
}

// getters and setters ////////////////////////////////////////////////////////

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.cmmn.test.cache;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.flowable.cmmn.api.CmmnHistoryService;
import org.flowable.cmmn.api.CmmnManagementService;
import org.flowable.cmmn.api.CmmnRepositoryService;
import org.flowable.cmmn.api.CmmnRuntimeService;
import org.flowable.cmmn.api.repository.CmmnDeployment;
import org.flowable.cmmn.api.repository.CmmnDeploymentBuilder;
import org.flowable.cmmn.engine.CmmnEngine;
import org.flowable.cmmn.engine.CmmnEngineConfiguration;
import org.flowable.cmmn.engine.test.FlowableCmmnTestCase;
import org.flowable.cmmn.engine.test.impl.CmmnHistoryTestHelper;
import org.flowable.cmmn.engine.test.impl.CmmnJobTestHelper;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.history.HistoryLevel;
import org.junit.Test;

/**
* @author Joram Barrez
*/
public class CaseDefinitionCacheTest {

@Test
public void testCaseDefinitionCache() {
CmmnEngine cmmnEngine = null;
String flowableCmmnCfgXml = "flowable.cache.cfg.xml";
try (InputStream inputStream = FlowableCmmnTestCase.class.getClassLoader().getResourceAsStream(flowableCmmnCfgXml)) {
cmmnEngine = CmmnEngineConfiguration.createCmmnEngineConfigurationFromInputStream(inputStream).buildCmmnEngine();
CmmnEngineConfiguration cmmnEngineConfiguration = cmmnEngine.getCmmnEngineConfiguration();
CmmnManagementService cmmnManagementService = cmmnEngine.getCmmnManagementService();
CmmnRepositoryService cmmnRepositoryService = cmmnEngine.getCmmnRepositoryService();
CmmnRuntimeService cmmnRuntimeService = cmmnEngine.getCmmnRuntimeService();
CmmnHistoryService cmmnHistoryService = cmmnEngine.getCmmnHistoryService();

List<String> deploymentIds = new ArrayList<>();
int nrOfModels = 9;
for (int nrOfIterations = 0; nrOfIterations < 10; nrOfIterations++) {
CmmnDeploymentBuilder deploymentBuilder = cmmnRepositoryService.createDeployment();
for (int i = 1; i <= nrOfModels; i++) {
deploymentBuilder.addClasspathResource("org/flowable/cmmn/test/cache/case" + i + ".cmmn");
}
CmmnDeployment deployment = deploymentBuilder.deploy();
deploymentIds.add(0, deployment.getId());

assertThat(cmmnRepositoryService.createCaseDefinitionQuery().count()).isEqualTo((nrOfIterations + 1) * nrOfModels);

for (int i = 1; i <= nrOfModels; i++) {
cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("case" + i).start();
}

assertThat(cmmnManagementService.createJobQuery().count()).isEqualTo((nrOfIterations + 1) * nrOfModels);
}

CmmnJobTestHelper.waitForJobExecutorToProcessAllJobs(cmmnEngine, 30000, 200, true);

assertThat(cmmnManagementService.createJobQuery().count()).isEqualTo(0);

if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
for (int i = 1; i <= nrOfModels; i++) {
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseDefinitionKey("case" + i).count()).isEqualTo(10);
}
}

for (String deploymentId : deploymentIds) {
cmmnRepositoryService.deleteDeployment(deploymentId, true);
}

} catch (IOException e) {
throw new FlowableException("Could not create CMMN engine", e);

} finally {
if (cmmnEngine != null) {
cmmnEngine.close();
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="dataSource" class="org.flowable.common.engine.impl.test.ClosingDataSource">
<constructor-arg>
<bean class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg>
<bean class="com.zaxxer.hikari.HikariConfig">
<property name="minimumIdle" value="0" />
<property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}"/>
<property name="driverClassName" value="${jdbc.driver:org.h2.Driver}"/>
<property name="username" value="${jdbc.username:sa}"/>
<property name="password" value="${jdbc.password:}"/>
</bean>
</constructor-arg>
</bean>
</constructor-arg>
</bean>

<bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.engine.impl.cfg.StandaloneInMemCmmnEngineConfiguration">
<property name="dataSource" ref="dataSource"/>

<property name="engineLifecycleListeners">
<list>
<ref bean="dataSource"/>
</list>
</property>

<property name="databaseSchemaUpdate" value="true" />

<property name="asyncExecutorActivate" value="false" />
<property name="asyncExecutorDefaultAsyncJobAcquireWaitTime" value="1000" />
<property name="asyncExecutorDefaultTimerJobAcquireWaitTime" value="1000" />

<property name="asyncFailedJobWaitTime" value="1" />

<property name="enableEntityLinks" value="true" />
<property name="enableCaseDefinitionHistoryLevel" value="true" />

<property name="caseDefinitionCacheLimit" value="9" />
</bean>

</beans>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:flowable="http://flowable.org/cmmn"
targetNamespace="http://flowable.org/cmmn">

<case id="case1">
<casePlanModel id="myPlanModel" name="My CasePlanModel">
<planItem id="planItem1" name="The Task" definitionRef="theTask" />
<task id="theTask" name="The Task" isBlocking="false" flowable:async="true" flowable:type="java" flowable:class="org.flowable.cmmn.test.delegate.TestJavaDelegate" />
</casePlanModel>
</case>

</definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:flowable="http://flowable.org/cmmn"
targetNamespace="http://flowable.org/cmmn">

<case id="case2">
<casePlanModel id="myPlanModel" name="My CasePlanModel">
<planItem id="planItem1" name="The Task" definitionRef="theTask" />
<task id="theTask" name="The Task" isBlocking="false" flowable:async="true" flowable:type="java" flowable:class="org.flowable.cmmn.test.delegate.TestJavaDelegate" />
</casePlanModel>
</case>

</definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:flowable="http://flowable.org/cmmn"
targetNamespace="http://flowable.org/cmmn">

<case id="case3">
<casePlanModel id="myPlanModel" name="My CasePlanModel">
<planItem id="planItem1" name="The Task" definitionRef="theTask" />
<task id="theTask" name="The Task" isBlocking="false" flowable:async="true" flowable:type="java" flowable:class="org.flowable.cmmn.test.delegate.TestJavaDelegate" />
</casePlanModel>
</case>

</definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:flowable="http://flowable.org/cmmn"
targetNamespace="http://flowable.org/cmmn">

<case id="case4">
<casePlanModel id="myPlanModel" name="My CasePlanModel">
<planItem id="planItem1" name="The Task" definitionRef="theTask" />
<task id="theTask" name="The Task" isBlocking="false" flowable:async="true" flowable:type="java" flowable:class="org.flowable.cmmn.test.delegate.TestJavaDelegate" />
</casePlanModel>
</case>

</definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:flowable="http://flowable.org/cmmn"
targetNamespace="http://flowable.org/cmmn">

<case id="case5">
<casePlanModel id="myPlanModel" name="My CasePlanModel">
<planItem id="planItem1" name="The Task" definitionRef="theTask" />
<task id="theTask" name="The Task" isBlocking="false" flowable:async="true" flowable:type="java" flowable:class="org.flowable.cmmn.test.delegate.TestJavaDelegate" />
</casePlanModel>
</case>

</definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:flowable="http://flowable.org/cmmn"
targetNamespace="http://flowable.org/cmmn">

<case id="case6">
<casePlanModel id="myPlanModel" name="My CasePlanModel">
<planItem id="planItem1" name="The Task" definitionRef="theTask" />
<task id="theTask" name="The Task" isBlocking="false" flowable:async="true" flowable:type="java" flowable:class="org.flowable.cmmn.test.delegate.TestJavaDelegate" />
</casePlanModel>
</case>

</definitions>
Loading

0 comments on commit dbc8247

Please sign in to comment.