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

chore(engine, engine-rest): Add CreateTime Flag to Fetch and Lock API #3912

Merged
merged 22 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
73953bd
chore(engine): Adjust Persistence Layer for CreationDate
psavidis Oct 26, 2023
a0d3ac6
test(model-api): Add Tests for Multi-Level Sorting
psavidis Nov 2, 2023
6a8919c
refactor(engine): Rename CREATION_DATE to CreateTime
psavidis Nov 7, 2023
056b746
chore(engine): Adjust Fetch And Lock API
psavidis Nov 3, 2023
8987e7f
tests(engine): Adjust Tests
psavidis Nov 3, 2023
246423f
chore(engine-rest): Adjust Fetch & Lock API
psavidis Nov 3, 2023
f552e14
chore(engine): Add Multi-Level Sorting Tests
psavidis Nov 6, 2023
ab748fc
test(engine): Add Tests for Null Or Empty Configs
psavidis Nov 6, 2023
a10d35d
Rename CreationDate to CreateTime
psavidis Nov 6, 2023
05e9de6
refactor(engine): Fix Tests for null & Empty createTimeConfig
psavidis Nov 8, 2023
c28bf9c
refactor(engine-rest): Simplify ExternalTaskQueryDto
psavidis Oct 26, 2023
3035233
refactor(engine-rest, engine): Add Creation-Date to API and Impl
psavidis Oct 26, 2023
8e7d083
refactor(engine): Change Column Name to CREATE_TIME_
psavidis Nov 6, 2023
5033882
chore(engine, engine-rest): Replace CreateTimeConfig with Builder
psavidis Nov 13, 2023
c4832e2
chore(engine, engine-rest): Adjust ExternalTaskServiceTest tests
psavidis Nov 16, 2023
382800e
chore(engine, engine-rest): Refactor builder
psavidis Nov 16, 2023
417c251
chore(engine, engine-rest): Fix Tests
psavidis Nov 17, 2023
8f1555e
chore(engine, engine-rest): Add CreateTime Tests to REST API
psavidis Nov 17, 2023
c50657a
refactor(engine): Code Review points
psavidis Dec 1, 2023
21a47c1
Fix Code Review Points
psavidis Dec 12, 2023
b69bfde
Move when blocks for ExternalTaskQueryByCreateTimeTest
psavidis Dec 12, 2023
93143b3
chore(engine): Cover Code Review Points
psavidis Dec 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,51 +16,39 @@
*/
package org.camunda.bpm.engine.rest.dto.externaltask;

import java.util.ArrayList;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java.util.function.Consumer;
import javax.ws.rs.core.MultivaluedMap;

import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.externaltask.ExternalTaskQuery;
import org.camunda.bpm.engine.rest.dto.AbstractQueryDto;
import org.camunda.bpm.engine.rest.dto.CamundaQueryParam;
import org.camunda.bpm.engine.rest.dto.converter.BooleanConverter;
import org.camunda.bpm.engine.rest.dto.converter.DateConverter;
import org.camunda.bpm.engine.rest.dto.converter.LongConverter;
import org.camunda.bpm.engine.rest.dto.converter.StringListConverter;
import org.camunda.bpm.engine.rest.dto.converter.StringSetConverter;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.camunda.bpm.engine.rest.dto.converter.LongConverter;

/**
* @author Thorben Lindhauer
*
*/
public class ExternalTaskQueryDto extends AbstractQueryDto<ExternalTaskQuery> {

public static final String SORT_BY_ID_VALUE = "id";
public static final String SORT_BY_LOCK_EXPIRATION_TIME = "lockExpirationTime";
public static final String SORT_BY_PROCESS_INSTANCE_ID = "processInstanceId";
public static final String SORT_BY_PROCESS_DEFINITION_ID = "processDefinitionId";
public static final String SORT_BY_PROCESS_DEFINITION_KEY = "processDefinitionKey";
public static final String SORT_BY_TENANT_ID = "tenantId";
public static final String SORT_BY_PRIORITY = "taskPriority";

public static final List<String> VALID_SORT_BY_VALUES;
static {
VALID_SORT_BY_VALUES = new ArrayList<>();
VALID_SORT_BY_VALUES.add(SORT_BY_ID_VALUE);
VALID_SORT_BY_VALUES.add(SORT_BY_LOCK_EXPIRATION_TIME);
VALID_SORT_BY_VALUES.add(SORT_BY_PROCESS_INSTANCE_ID);
VALID_SORT_BY_VALUES.add(SORT_BY_PROCESS_DEFINITION_ID);
VALID_SORT_BY_VALUES.add(SORT_BY_PROCESS_DEFINITION_KEY);
VALID_SORT_BY_VALUES.add(SORT_BY_TENANT_ID);
VALID_SORT_BY_VALUES.add(SORT_BY_PRIORITY);
}
public static final Map<String, Consumer<ExternalTaskQuery>> SORT_METHODS_BY_FIELD = Map.of(
"id", ExternalTaskQuery::orderById,
"lockExpirationTime", ExternalTaskQuery::orderByLockExpirationTime,
"processInstanceId", ExternalTaskQuery::orderByProcessInstanceId,
"processDefinitionId", ExternalTaskQuery::orderByProcessDefinitionId,
"processDefinitionKey", ExternalTaskQuery::orderByProcessDefinitionKey,
"tenantId", ExternalTaskQuery::orderByTenantId,
"taskPriority", ExternalTaskQuery::orderByPriority,
"createTime", ExternalTaskQuery::orderByCreateTime
);

protected String externalTaskId;
protected Set<String> externalTaskIds;
Expand Down Expand Up @@ -201,7 +189,7 @@ public void setPriorityLowerThanOrEquals(Long priorityLowerThanOrEquals) {

@Override
protected boolean isValidSortByValue(String value) {
return VALID_SORT_BY_VALUES.contains(value);
return SORT_METHODS_BY_FIELD.containsKey(value);
}

@Override
Expand Down Expand Up @@ -278,24 +266,10 @@ protected void applyFilters(ExternalTaskQuery query) {

@Override
protected void applySortBy(ExternalTaskQuery query, String sortBy, Map<String, Object> parameters, ProcessEngine engine) {
if (SORT_BY_ID_VALUE.equals(sortBy)) {
query.orderById();
}
else if (SORT_BY_LOCK_EXPIRATION_TIME.equals(sortBy)) {
query.orderByLockExpirationTime();
}
else if (SORT_BY_PROCESS_DEFINITION_ID.equals(sortBy)) {
query.orderByProcessDefinitionId();
}
else if (SORT_BY_PROCESS_DEFINITION_KEY.equals(sortBy)) {
query.orderByProcessDefinitionKey();
}
else if (SORT_BY_PROCESS_INSTANCE_ID.equals(sortBy)) {
query.orderByProcessInstanceId();
} else if (sortBy.equals(SORT_BY_TENANT_ID)) {
query.orderByTenantId();
} else if (sortBy.equals(SORT_BY_PRIORITY)) {
query.orderByPriority();
var sortByMethod = SORT_METHODS_BY_FIELD.get(sortBy);

if (sortByMethod != null) {
sortByMethod.accept(query);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@
*/
package org.camunda.bpm.engine.rest.dto.externaltask;

import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.externaltask.ExternalTaskQueryBuilder;
import org.camunda.bpm.engine.externaltask.ExternalTaskQueryTopicBuilder;

import static java.lang.Boolean.TRUE;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import org.camunda.bpm.engine.ExternalTaskService;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.externaltask.ExternalTaskQueryTopicBuilder;
import org.camunda.bpm.engine.externaltask.FetchAndLockBuilder;
import org.camunda.bpm.engine.impl.util.CollectionUtil;
import org.camunda.bpm.engine.rest.dto.SortingDto;

/**
* @author Thorben Lindhauer
Expand All @@ -37,21 +43,28 @@ public class FetchExternalTasksDto {
protected List<FetchExternalTaskTopicDto> topics;
protected boolean includeExtensionProperties = false;

protected List<SortingDto> sortings;

public int getMaxTasks() {
return maxTasks;
}

public void setMaxTasks(int maxTasks) {
this.maxTasks = maxTasks;
}

public String getWorkerId() {
return workerId;
}

public void setWorkerId(String workerId) {
this.workerId = workerId;
}

public List<FetchExternalTaskTopicDto> getTopics() {
return topics;
}

public void setTopics(List<FetchExternalTaskTopicDto> topics) {
this.topics = topics;
}
Expand All @@ -64,6 +77,14 @@ public void setUsePriority(boolean usePriority) {
this.usePriority = usePriority;
}

public void setSortings(List<SortingDto> sortings) {
this.sortings = sortings;
}

public List<SortingDto> getSortings() {
return this.sortings;
}

public boolean isIncludeExtensionProperties() {
return includeExtensionProperties;
}
Expand Down Expand Up @@ -182,73 +203,137 @@ public void setIncludeExtensionProperties(boolean includeExtensionProperties) {
}
}

public ExternalTaskQueryBuilder buildQuery(ProcessEngine processEngine) {
ExternalTaskQueryBuilder fetchBuilder = processEngine
.getExternalTaskService()
.fetchAndLock(getMaxTasks(), getWorkerId(), isUsePriority());
public ExternalTaskQueryTopicBuilder buildQuery(ProcessEngine processEngine) {
FetchAndLockBuilder fetchAndLockBuilder = getBuilder(processEngine);

if (getTopics() != null) {
for (FetchExternalTaskTopicDto topicDto : getTopics()) {
ExternalTaskQueryTopicBuilder topicFetchBuilder =
fetchBuilder.topic(topicDto.getTopicName(), topicDto.getLockDuration());
return configureTopics(fetchAndLockBuilder);
}

if (topicDto.getBusinessKey() != null) {
topicFetchBuilder = topicFetchBuilder.businessKey(topicDto.getBusinessKey());
}
protected ExternalTaskQueryTopicBuilder configureTopics(FetchAndLockBuilder builder) {
ExternalTaskQueryTopicBuilder topicBuilder = builder.subscribe();

if (topicDto.getProcessDefinitionId() != null) {
topicFetchBuilder.processDefinitionId(topicDto.getProcessDefinitionId());
}
if (CollectionUtil.isEmpty(topics)) {
return topicBuilder;
}

if (topicDto.getProcessDefinitionIdIn() != null) {
topicFetchBuilder.processDefinitionIdIn(topicDto.getProcessDefinitionIdIn());
}
topics.forEach(topic -> {
topicBuilder.topic(topic.getTopicName(), topic.getLockDuration());

if (topicDto.getProcessDefinitionKey() != null) {
topicFetchBuilder.processDefinitionKey(topicDto.getProcessDefinitionKey());
}
if (topic.getBusinessKey() != null) {
topicBuilder.businessKey(topic.getBusinessKey());
}

if (topicDto.getProcessDefinitionKeyIn() != null) {
topicFetchBuilder.processDefinitionKeyIn(topicDto.getProcessDefinitionKeyIn());
}
if (topic.getProcessDefinitionId() != null) {
topicBuilder.processDefinitionId(topic.getProcessDefinitionId());
}

if (topicDto.getVariables() != null) {
topicFetchBuilder = topicFetchBuilder.variables(topicDto.getVariables());
}
if (topic.getProcessDefinitionIdIn() != null) {
topicBuilder.processDefinitionIdIn(topic.getProcessDefinitionIdIn());
}

if (topicDto.getProcessVariables() != null) {
topicFetchBuilder = topicFetchBuilder.processInstanceVariableEquals(topicDto.getProcessVariables());
}
if (topic.getProcessDefinitionKey() != null) {
topicBuilder.processDefinitionKey(topic.getProcessDefinitionKey());
}

if (topicDto.isDeserializeValues()) {
topicFetchBuilder = topicFetchBuilder.enableCustomObjectDeserialization();
}
if (topic.getProcessDefinitionKeyIn() != null) {
topicBuilder.processDefinitionKeyIn(topic.getProcessDefinitionKeyIn());
}

if (topicDto.isLocalVariables()) {
topicFetchBuilder = topicFetchBuilder.localVariables();
}
if (topic.getVariables() != null) {
topicBuilder.variables(topic.getVariables());
}

if (TRUE.equals(topicDto.isWithoutTenantId())) {
topicFetchBuilder = topicFetchBuilder.withoutTenantId();
}
if (topic.getProcessVariables() != null) {
topicBuilder.processInstanceVariableEquals(topic.getProcessVariables());
}

if (topicDto.getTenantIdIn() != null) {
topicFetchBuilder = topicFetchBuilder.tenantIdIn(topicDto.getTenantIdIn());
}
if (topic.isDeserializeValues()) {
topicBuilder.enableCustomObjectDeserialization();
}

if(topicDto.getProcessDefinitionVersionTag() != null) {
topicFetchBuilder = topicFetchBuilder.processDefinitionVersionTag(topicDto.getProcessDefinitionVersionTag());
}
if (topic.isLocalVariables()) {
topicBuilder.localVariables();
}

if (TRUE.equals(topic.isWithoutTenantId())) {
topicBuilder.withoutTenantId();
}

if(topicDto.isIncludeExtensionProperties()) {
topicFetchBuilder = topicFetchBuilder.includeExtensionProperties();
}
if (topic.getTenantIdIn() != null) {
topicBuilder.tenantIdIn(topic.getTenantIdIn());
}

if(topic.getProcessDefinitionVersionTag() != null) {
topicBuilder.processDefinitionVersionTag(topic.getProcessDefinitionVersionTag());
}

fetchBuilder = topicFetchBuilder;
if(topic.isIncludeExtensionProperties()) {
topicBuilder.includeExtensionProperties();
}
});

return topicBuilder;
}

protected FetchAndLockBuilder getBuilder(ProcessEngine engine) {
ExternalTaskService service = engine.getExternalTaskService();

FetchAndLockBuilder builder = service.fetchAndLock()
.workerId(workerId)
.maxTasks(maxTasks)
.usePriority(usePriority);

SortMapper mapper = new SortMapper(sortings, builder);

return mapper.getBuilderWithSortConfigs();
}

/**
* Encapsulates the mapping of sorting configurations (field, order) to the respective methods builder config methods
* and applies them.
* <p>
* To achieve that, maps are used internally to map fields and orders to the corresponding builder method.
* It works with case-insensitive orders (e.g will work with "asc", "ASC").
* Fields need are case-sensitive.
mboskamp marked this conversation as resolved.
Show resolved Hide resolved
*/
static class SortMapper {

protected static Map<String, Consumer<FetchAndLockBuilder>> FIELD_MAPPINGS = Map.of(
"createTime", FetchAndLockBuilder::orderByCreateTime
);

protected static Map<String, Consumer<FetchAndLockBuilder>> ORDER_MAPPINGS = Map.of(
"asc", FetchAndLockBuilder::asc,
"desc", FetchAndLockBuilder::desc
);

protected final List<SortingDto> sortings;
protected final FetchAndLockBuilder builder;

protected SortMapper(List<SortingDto> sortings, FetchAndLockBuilder builder) {
this.sortings = (sortings == null) ? Collections.emptyList() : sortings;
this.builder = builder;
}

return fetchBuilder;
/**
* Applies the sorting field mappings to the builder and returns it.
*/
protected FetchAndLockBuilder getBuilderWithSortConfigs() {
sortings.forEach(dto -> {
fieldMappingKey(dto).ifPresent(key -> FIELD_MAPPINGS.get(key).accept(builder));
orderMappingKey(dto).ifPresent(key -> ORDER_MAPPINGS.get(key).accept(builder));
});

return builder;
}

protected Optional<String> fieldMappingKey(SortingDto dto) {
return Optional.ofNullable(dto.getSortBy());
}

protected Optional<String> orderMappingKey(SortingDto dto) {
return Optional.ofNullable(dto.getSortOrder());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.core.Response.Status;

import org.camunda.bpm.engine.IdentityService;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.externaltask.ExternalTaskQueryBuilder;
import org.camunda.bpm.engine.externaltask.ExternalTaskQueryTopicBuilder;
import org.camunda.bpm.engine.externaltask.LockedExternalTask;
import org.camunda.bpm.engine.impl.ProcessEngineImpl;
import org.camunda.bpm.engine.impl.identity.Authentication;
Expand Down Expand Up @@ -264,8 +262,9 @@ protected FetchAndLockResult tryFetchAndLock(FetchAndLockRequest request) {
}

protected List<LockedExternalTaskDto> executeFetchAndLock(FetchExternalTasksExtendedDto fetchingDto, ProcessEngine processEngine) {
ExternalTaskQueryBuilder fetchBuilder = fetchingDto.buildQuery(processEngine);
ExternalTaskQueryTopicBuilder fetchBuilder = fetchingDto.buildQuery(processEngine);
List<LockedExternalTask> externalTasks = fetchBuilder.execute();

return LockedExternalTaskDto.fromLockedExternalTasks(externalTasks);
}

Expand Down
Loading