Task claim - spring - two users get the same task

I wonder if this is a potential bug:

we have a rest controller that searches for unassigned tasks, gets the first one, claims it and returns the form url to the browser. So users work in a batch mode, after task completion, they get the next task automatically.

Now we get bug reports that a task is shown to two users at the same time.
I inspected the code and saw that in the ClaimTaskCmd#execute() the following is done:

 TaskEntity task = taskManager.findTaskById(taskId);
    ensureNotNull("Cannot find task with id " + taskId, "task", task);

    checkClaimTask(task, commandContext);

    if (userId != null) { 
      if (task.getAssignee() != null) {
        if (!task.getAssignee().equals(userId)) {
          // When the task is already claimed by another user, throw exception. Otherwise, ignore
          // this, post-conditions of method already met.
          throw new TaskAlreadyClaimedException(task.getId(), task.getAssignee());
        }
      } else {
        task.setAssignee(userId);
      }
    } else {
      // Task should be assigned to no one
      task.setAssignee(null);
    }

If I do two claims simultaniously the condition check will allow the operation for both users since they both read the entity before it was claimed by the other user. I do not find any other checks later in the code.

Question: did you encounter the problem already? is this a bug/support issue? Is there something strange going on between mybatis and spring transactional behaviour? What would be a possible workaround?

Thanks a lot
Jan

Hi Jan,

There may be a problem, but I don’t think what you found is the reason. In this case, two engine commands try to update the same entry in ACT_RU_TASK in parallel. One of them is expected to fail with an OptimisticLockingException when it flushes its changes to the database.

Things you could check:

  • Make sure the OptimisticLockingException is not swallowed
  • Tune up the logging. Useful loggers in this case could be: org.camunda.bpm.engine.cmd to see when an engine command begins and ends. org.camunda.bpm.engine.impl.persistence.entity to see all executed SQL statements, their parameters and results. Set both of them to DEBUG for useful output.

Cheers,
Thorben