Skip to content

Commit

Permalink
fix(engine): unlock job with custom retries when fails
Browse files Browse the repository at this point in the history
* set lock owner to null
* set lock expiration time to null
* set due date to for the next retry

Related to CAM-9571
  • Loading branch information
yanavasileva authored and koevskinikola committed Dec 10, 2019
1 parent 15ab643 commit cd09d47
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ protected void executeCustomStrategy(CommandContext commandContext, JobEntity jo
int intervalsCount = intervals.size();
int indexOfInterval = Math.max(0, Math.min(intervalsCount - 1, intervalsCount - (job.getRetries() - 1)));
DurationHelper durationHelper = getDurationHelper(intervals.get(indexOfInterval));
job.setLockExpirationTime(durationHelper.getDateAfter());

job.setDuedate(durationHelper.getDateAfter());
job.unlock();

logException(job);
decrementRetries(job);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.camunda.bpm.engine.runtime.Job;
import org.camunda.bpm.engine.runtime.JobQuery;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.test.Deployment;
import org.camunda.bpm.engine.variable.Variables;
import org.camunda.bpm.model.bpmn.Bpmn;
Expand All @@ -44,6 +45,8 @@

public class FoxJobRetryCmdTest extends PluggableProcessEngineTestCase {

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

@Deployment(resources = { "org/camunda/bpm/engine/test/bpmn/async/FoxJobRetryCmdTest.testFailedServiceTask.bpmn20.xml" })
public void testFailedServiceTask() {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("failedServiceTask");
Expand Down Expand Up @@ -379,7 +382,6 @@ public void testFailedJobRetryTimeCycleWithChangingExpression() throws ParseExce
.endEvent()
.done();

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2017-01-01T09:55:00");
ClockUtil.setCurrentTime(startDate);

Expand Down Expand Up @@ -415,8 +417,8 @@ public void testFailedJobRetryTimeCycleWithChangingExpression() throws ParseExce

//then
Date expectedDate = simpleDateFormat.parse("2017-01-01T10:15:00");
Date lockExpirationTime = ((JobEntity) managementService.createJobQuery().singleResult()).getLockExpirationTime();
assertEquals(expectedDate, lockExpirationTime);
Date duedateTime = (managementService.createJobQuery().singleResult()).getDuedate();
assertEquals(expectedDate, duedateTime);
}

public void testRetryOnTimerStartEventWithExpression() {
Expand Down Expand Up @@ -457,7 +459,6 @@ public void testRetryOnAsyncStartEvent() throws Exception {

deployment(bpmnModelInstance);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2018-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

Expand All @@ -479,7 +480,7 @@ public void testRetryOnAsyncStartEvent() throws Exception {
Assert.assertEquals(4, job.getRetries());

Date expectedDate = simpleDateFormat.parse("2018-01-01T10:05:00");
assertEquals(expectedDate, ((JobEntity) job).getLockExpirationTime());
assertEquals(expectedDate, job.getDuedate());
}

public void testIntermediateCatchEvent() throws Exception {
Expand All @@ -495,7 +496,6 @@ public void testIntermediateCatchEvent() throws Exception {

deployment(bpmnModelInstance);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2018-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

Expand All @@ -517,7 +517,7 @@ public void testIntermediateCatchEvent() throws Exception {
Assert.assertEquals(4, job.getRetries());

Date expectedDate = simpleDateFormat.parse("2018-01-01T10:05:00");
assertEquals(expectedDate, ((JobEntity) job).getLockExpirationTime());
assertEquals(expectedDate, job.getDuedate());
}

public void testEndEvent() throws Exception {
Expand All @@ -531,7 +531,6 @@ public void testEndEvent() throws Exception {

deployment(bpmnModelInstance);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2018-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

Expand All @@ -553,7 +552,7 @@ public void testEndEvent() throws Exception {
Assert.assertEquals(4, job.getRetries());

Date expectedDate = simpleDateFormat.parse("2018-01-01T10:05:00");
assertEquals(expectedDate, ((JobEntity) job).getLockExpirationTime());
assertEquals(expectedDate, job.getDuedate());
}

public void testExclusiveGateway() throws Exception {
Expand All @@ -568,7 +567,6 @@ public void testExclusiveGateway() throws Exception {

deployment(bpmnModelInstance);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2018-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

Expand All @@ -590,7 +588,7 @@ public void testExclusiveGateway() throws Exception {
Assert.assertEquals(4, job.getRetries());

Date expectedDate = simpleDateFormat.parse("2018-01-01T10:05:00");
assertEquals(expectedDate, ((JobEntity) job).getLockExpirationTime());
assertEquals(expectedDate, job.getDuedate());
}

public void testInclusiveGateway() throws Exception {
Expand All @@ -605,7 +603,6 @@ public void testInclusiveGateway() throws Exception {

deployment(bpmnModelInstance);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2018-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

Expand All @@ -627,7 +624,7 @@ public void testInclusiveGateway() throws Exception {
Assert.assertEquals(4, job.getRetries());

Date expectedDate = simpleDateFormat.parse("2018-01-01T10:05:00");
assertEquals(expectedDate, ((JobEntity) job).getLockExpirationTime());
assertEquals(expectedDate, job.getDuedate());
}

public void testEventBasedGateway() throws Exception {
Expand All @@ -644,7 +641,6 @@ public void testEventBasedGateway() throws Exception {

deployment(bpmnModelInstance);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2018-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

Expand All @@ -666,7 +662,7 @@ public void testEventBasedGateway() throws Exception {
Assert.assertEquals(4, job.getRetries());

Date expectedDate = simpleDateFormat.parse("2018-01-01T10:05:00");
assertEquals(expectedDate, ((JobEntity) job).getLockExpirationTime());
assertEquals(expectedDate, job.getDuedate());
}

public void testParallelGateway() throws Exception {
Expand All @@ -681,7 +677,6 @@ public void testParallelGateway() throws Exception {

deployment(bpmnModelInstance);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date startDate = simpleDateFormat.parse("2018-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

Expand All @@ -703,7 +698,104 @@ public void testParallelGateway() throws Exception {
Assert.assertEquals(4, job.getRetries());

Date expectedDate = simpleDateFormat.parse("2018-01-01T10:05:00");
assertEquals(expectedDate, ((JobEntity) job).getLockExpirationTime());
assertEquals(expectedDate, job.getDuedate());
}

public void testFailingIntermidiateBoundaryTimerJobWithCustomRetries() throws ParseException {
try {
// given
BpmnModelInstance bpmnModelInstance = Bpmn.createExecutableProcess("process")
.startEvent()
.userTask("wait")
.boundaryEvent("timer")
.cancelActivity(false)
.timerWithCycle("R4/PT1M")
.camundaFailedJobRetryTimeCycle("R2/PT10M")
.serviceTask("failing")
.camundaClass("foo")
.endEvent()
.done();

deployment(bpmnModelInstance);

Date startDate = simpleDateFormat.parse("2019-01-01T10:00:00");
ClockUtil.setCurrentTime(startDate);

runtimeService.startProcessInstanceByKey("process");

ClockUtil.setCurrentTime(simpleDateFormat.parse("2019-01-01T10:01:01"));

// when the first timer is triggered
Job firstJob = managementService.createJobQuery().singleResult();
try {
managementService.executeJob(firstJob.getId());
} catch (Exception e) {
// ignore
}

// then a second job will be created for the second timer
List<Job> jobs = managementService.createJobQuery().list();
assertEquals(2, jobs.size());
for (Job job : jobs) {
if (job.getRetries() == 1) { // the first job already failed once
Date expectedDate = simpleDateFormat.parse("2019-01-01T10:11:01");
assertEquals(expectedDate, job.getDuedate());
assertNull(((JobEntity) job).getLockExpirationTime());
} else if (job.getRetries() == 3) { // the second job is not triggered yet
Date expectedDate = simpleDateFormat.parse("2019-01-01T10:02:00");
assertEquals(expectedDate, job.getDuedate());
assertNull(((JobEntity) job).getLockExpirationTime());
} else {
fail("Unexpected job");
}
}
} finally {
ClockUtil.reset();
}
}

public void testExecuteSecondJobWhenJobFailedWithCustomJobRetriesInSameProcess() {
// given
BpmnModelInstance bpmnModelInstance = Bpmn.createExecutableProcess("process")
.startEvent()
.parallelGateway("gwt")
.serviceTask("failing")
.camundaClass("foo")
.camundaAsyncBefore()
.camundaFailedJobRetryTimeCycle("R2/PT5M")
.moveToNode("gwt")
.userTask("beforePassing")
.serviceTask("passing")
.camundaExpression("${true}")
.camundaAsyncBefore()
.userTask("afterPassing")
.done();

deployment(bpmnModelInstance);

runtimeService.startProcessInstanceByKey("process");

Job job = managementService.createJobQuery().singleResult();
try {
managementService.executeJob(job.getId());
} catch (Exception e) {
// ignore
}

Task task = taskService.createTaskQuery().taskDefinitionKey("beforePassing").singleResult();
taskService.complete(task.getId());

// when one failed job and one passing are present
// only the passing should be executed
waitForJobExecutorToProcessAllJobs(5000);

// then the passing service task has been executed
task = taskService.createTaskQuery().taskDefinitionKey("afterPassing").singleResult();
assertNotNull(task);
// and the failing job still have one retry left
Job failedJob = managementService.createJobQuery().singleResult();
assertEquals(1, failedJob.getRetries());
assertNull(((JobEntity) failedJob).getLockExpirationTime());
}

protected void assertJobRetriesForActivity(ProcessInstance pi, String activityId) {
Expand Down
Loading

0 comments on commit cd09d47

Please sign in to comment.