Skip to content

Commit d3ba58b

Browse files
feat(engine, engine-rest-core) Add a query criteria to retrieve all executing jobs
related to: camunda#4470
1 parent c829dd5 commit d3ba58b

File tree

9 files changed

+100
-1
lines changed

9 files changed

+100
-1
lines changed

engine-rest/engine-rest-openapi/src/main/templates/lib/commons/job-definition-query-params.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<#elseif requestMethod == "POST">
1616
<#assign listSeparator = "">
1717
</#if>
18-
18+
1919
<#assign params = {
2020
"jobDefinitionId": {
2121
"type": "string",

engine-rest/engine-rest-openapi/src/main/templates/lib/commons/job-query-params.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,11 @@
163163
"type": "boolean",
164164
"desc": "Include jobs which belong to no tenant. Can be used in combination with `tenantIdIn`.
165165
Value may only be `true`, as `false` is the default behavior."
166+
},
167+
"executing": {
168+
"type": "boolean",
169+
"desc": "Only select jobs which are executing, i.e., lock expiration date is not null, lock expiration
170+
date is in future and suspension state is 1. Value may only be `true`, as `false` is the default
171+
behavior."
166172
}
167173
}>

engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/runtime/JobQueryDto.java

+9
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public class JobQueryDto extends AbstractQueryDto<JobQuery> {
9494
protected List<String> tenantIds;
9595
protected Boolean withoutTenantId;
9696
protected Boolean includeJobsWithoutTenantId;
97+
protected Boolean executing;
9798

9899
protected List<ConditionQueryParameterDto> dueDates;
99100
protected List<ConditionQueryParameterDto> createTimes;
@@ -234,6 +235,11 @@ public void setIncludeJobsWithoutTenantId(Boolean includeJobsWithoutTenantId) {
234235
this.includeJobsWithoutTenantId = includeJobsWithoutTenantId;
235236
}
236237

238+
@CamundaQueryParam(value="executing", converter = BooleanConverter.class)
239+
public void setExecuting(Boolean executing) {
240+
this.executing = executing;
241+
}
242+
237243
@Override
238244
protected boolean isValidSortByValue(String value) {
239245
return VALID_SORT_BY_VALUES.contains(value);
@@ -418,6 +424,9 @@ String fieldName() {
418424
if (TRUE.equals(includeJobsWithoutTenantId)) {
419425
query.includeJobsWithoutTenantId();
420426
}
427+
if (TRUE.equals(executing)) {
428+
query.executing();
429+
}
421430
}
422431

423432
@Override

engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/JobRestServiceQueryTest.java

+13
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,17 @@ public void testMessagesParameter() {
359359
verify(mockQuery).list();
360360
}
361361

362+
@Test
363+
public void testExecutingParameter() {
364+
Map<String, Object> parameters = new HashMap<>();
365+
parameters.put("executing", MockProvider.EXAMPLE_EXECUTING);
366+
367+
given().queryParams(parameters).then().expect().statusCode(Status.OK.getStatusCode()).when().get(JOBS_RESOURCE_URL);
368+
369+
verify(mockQuery).executing();
370+
verify(mockQuery).list();
371+
}
372+
362373
@Test
363374
public void testMessagesTimersParameter() {
364375
Map<String, Object> parameters = new HashMap<>();
@@ -421,6 +432,7 @@ private Map<String, Object> getCompleteParameters() {
421432
parameters.put("priorityLowerThanOrEquals", JOB_QUERY_MAX_PRIORITY);
422433
parameters.put("priorityHigherThanOrEquals", JOB_QUERY_MIN_PRIORITY);
423434
parameters.put("jobDefinitionId", MockProvider.EXAMPLE_JOB_DEFINITION_ID);
435+
parameters.put("executing", MockProvider.EXAMPLE_EXECUTING);
424436
return parameters;
425437
}
426438

@@ -458,6 +470,7 @@ private void verifyParameterQueryInvocations() {
458470
verify(mockQuery).priorityLowerThanOrEquals(JOB_QUERY_MAX_PRIORITY);
459471
verify(mockQuery).priorityHigherThanOrEquals(JOB_QUERY_MIN_PRIORITY);
460472
verify(mockQuery).jobDefinitionId(MockProvider.EXAMPLE_JOB_DEFINITION_ID);
473+
verify(mockQuery).executing();
461474
}
462475

463476
private void testDateParameters(DateParameters parameters) {

engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/helper/MockProvider.java

+2
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@ public abstract class MockProvider {
530530
public static final String EXAMPLE_AUTHORIZATION_ID = "someAuthorizationId";
531531
public static final int EXAMPLE_AUTHORIZATION_TYPE = 0;
532532
public static final String EXAMPLE_AUTHORIZATION_TYPE_STRING = "0";
533+
public static final Boolean EXAMPLE_EXECUTING = true;
534+
533535

534536
// process applications
535537
public static final String EXAMPLE_PROCESS_APPLICATION_NAME = "aProcessApplication";

engine/src/main/java/org/camunda/bpm/engine/impl/JobQueryImpl.java

+9
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public class JobQueryImpl extends AbstractQuery<JobQuery, Job> implements JobQue
7171
protected String failedActivityId;
7272
protected boolean noRetriesLeft;
7373
protected SuspensionState suspensionState;
74+
protected boolean executing;
7475

7576
protected boolean isTenantIdSet = false;
7677
protected String[] tenantIds;
@@ -257,6 +258,11 @@ public JobQuery suspended() {
257258
return this;
258259
}
259260

261+
public JobQuery executing() {
262+
executing = true;
263+
return this;
264+
}
265+
260266
@Override
261267
protected boolean hasExcludingConditions() {
262268
return super.hasExcludingConditions()
@@ -402,5 +408,8 @@ public boolean isWithException() {
402408
public String getExceptionMessage() {
403409
return exceptionMessage;
404410
}
411+
public boolean getExecuting() {
412+
return executing;
413+
}
405414

406415
}

engine/src/main/java/org/camunda/bpm/engine/runtime/JobQuery.java

+6
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,10 @@ public interface JobQuery extends Query<JobQuery, Job> {
191191
*/
192192
JobQuery orderByTenantId();
193193

194+
/**
195+
* Only select jobs that are executing,
196+
* ie. lock expiration time is not null, lock expiration is in future and suspension state is 1
197+
*/
198+
JobQuery executing();
199+
194200
}

engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/Job.xml

+8
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,14 @@
420420
<if test="suspensionState != null">
421421
and RES.SUSPENSION_STATE_ = #{suspensionState.stateCode}
422422
</if>
423+
<if test="executing">
424+
AND
425+
RES.SUSPENSION_STATE_ = 1
426+
AND
427+
RES.LOCK_EXP_TIME_ IS NOT NULL
428+
AND
429+
RES.LOCK_EXP_TIME_ > #{now, jdbcType=TIMESTAMP}
430+
</if>
423431
<if test="isTenantIdSet">
424432
<if test="tenantIds != null &amp;&amp; tenantIds.length > 0">
425433
and ( RES.TENANT_ID_ in

engine/src/test/java/org/camunda/bpm/engine/test/api/mgmt/JobQueryTest.java

+46
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,31 @@ public void testQueryInvalidSortingUsage() {
871871
}
872872
}
873873

874+
@Test
875+
public void testQueryByExecuting() {
876+
Calendar lockExpDate = Calendar.getInstance();
877+
//given - lock expiration date in future
878+
lockExpDate.add(Calendar.MILLISECOND, 30000000);
879+
880+
createJobWithLockExpiration(lockExpDate.getTime());
881+
882+
Job job = managementService.createJobQuery().jobId(timerEntity.getId()).singleResult();
883+
assertNotNull(job);
884+
885+
List<Job> list = managementService.createJobQuery().executing().list();
886+
assertEquals(list.size(), 1);
887+
deleteJobInDatabase();
888+
889+
//given - lock expiration date in the past
890+
lockExpDate.add(Calendar.MILLISECOND, -60000000);
891+
createJobWithLockExpiration(lockExpDate.getTime());
892+
893+
list = managementService.createJobQuery().executing().list();
894+
assertEquals(list.size(), 0);
895+
896+
deleteJobInDatabase();
897+
}
898+
874899
//helper ////////////////////////////////////////////////////////////
875900

876901
private void setRetries(final String processInstanceId, final int retries) {
@@ -886,6 +911,27 @@ public Void execute(CommandContext commandContext) {
886911
});
887912
}
888913

914+
private void createJobWithLockExpiration(Date lockDate) {
915+
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutorTxRequired();
916+
commandExecutor.execute(new Command<Void>() {
917+
public Void execute(CommandContext commandContext) {
918+
JobManager jobManager = commandContext.getJobManager();
919+
timerEntity = new TimerEntity();
920+
timerEntity.setLockOwner(UUID.randomUUID().toString());
921+
timerEntity.setDuedate(new Date());
922+
timerEntity.setRetries(0);
923+
timerEntity.setLockExpirationTime(lockDate);
924+
925+
jobManager.insert(timerEntity);
926+
927+
assertNotNull(timerEntity.getId());
928+
929+
return null;
930+
931+
}
932+
});
933+
}
934+
889935
private ProcessInstance startProcessInstanceWithFailingJob() {
890936
// start a process with a failing job
891937
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("exceptionInJobExecution");

0 commit comments

Comments
 (0)