External Tasks Priority Not Working


#1

Hi everyone,

I am working with external tasks using the Java org.camunda.bpm.engine.ExternalTaskService::fetchAndLock(int maxTasks, String workerId, boolean usePriority) method to fetchAndLock tasks.

I set the usePriority parameter to true to fetch based on priority but it seems to ignore it.

Here is a screen shot from Sequel Pro showing the ACT_RU_EXT_TASK table with the priorities set. It should be picking up the one with 100 first right? Why is it not being locked? Am I missing something? My Camunda version is 7.10 and my database is in MariaDB 10.2.

Thanks,

Jim


#2

Just as a double check, can you try with postman/manual URL fetch/directly with api and see if it works. Fetch 1 task at a time and double check it working with the rest API directly


#3

I’m trying to do it in curl but I get an error. I get the same error in Postman.

Here’s my curl:

curl -b cookies.txt https://myhostname/engine-rest/external-task/fetchAndLock -H ‘Accept: application/json’ -H ‘Content-Type: application/json’ -d ‘{“workerId”:“curl”,“maxTasks”:1,“usePriority”:true}’

And the output is this:

Failed processing arguments of org.jboss.resteasy.spi.metadata.ResourceMethod@71ae1a28

Do you see an error in my curl command?

Thanks!


#4

I would prefer not to specify a topicName. But is that required?


#5

Can you try it in postman using a topic and without a topic.


#6

I had to fix another issue to get it working in postman and curl. Anyway, so in postman if I call with no topic I get back an empty [] array–meaning it didn’t lock anything. So it appears that topic is mandatory. This should be put in the documentation. I put in the possible topicNames and it does lock the higher priorty task first that I would expect.

So priority does work in the REST API but not in the Java ExternalTaskService::fetchAndLock method with usePriority. Should I report this as a bug or can someone else verify this?

Thanks,

Jim


#7

I added a JIRA bug for this:

https://app.camunda.com/jira/browse/CAM-10195


#8

Hi @jamesfwood,

thanks for using the JIRA tracker and opening the issue there.

Specifying a topic is indeed mandatory for fetch and lock, I created another JIRA issue CAM-10200 to document this more explicitly.
Would you be interested in providing a pull request for the documentation to fix this?
The repository can be found here: https://github.com/camunda/camunda-docs-manual
Feel free to ask if you have any questions on this.

Regarding the Java API:
After you fixed your issue and made the example work with the REST API call, did you try it again with the Java API with a topic as well?
You didn’t state that, so I just want to make sure we’re not hunting ghosts here.

Besides, as far as I tried with a basic example myself, this works with both APIs just fine as the REST API uses the Java API itself to execute this request.

Best,
Tobias


#9

Hi Tobias,

Yeah I can do a PR to update the documentation. No problem.

As for the Java API, yes I do use it with a topic already–I always have.

Here is what my call looks like:

List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(1, workerId, true).topic(topicName, lockDuration).execute();

See an issue with it?

Remember, this isn’t the newer ExternalTaskClient, this is the ExternalTaskService API.

Details here:
https://docs.camunda.org/javadoc/camunda-bpm-platform/7.10/org/camunda/bpm/engine/ExternalTaskService.html#fetchAndLock-int-java.lang.String-boolean-

So technically there are 3 types of APIs, the RES API, the camunda-external-task-client-java, and this ExternalTaskService API.

Thanks,

Jim


#10

Hi Jim,

Sounds great, looking forward to your PR!

Concerning the issue, I still want to make sure we’re not going into the wrong direction here, so just as a double check:

  1. What is the topic you are trying to fetchAndLock with? I am asking because the tasks with priority 0 and 100 have different topics than the ones with priority 25.
  2. I may have missed it, but what actually happens when you do the fetchAndLock with usePriority set to true? Is no task locked? Is one of the tasks with priority=25 locked? And what happens when usePriority is set to false? You just said that

Best,
Tobias


#11

Hi Tobias,

I think I might know what is going on. I think it’s in my implementation of deciding “potential” external tasks to run. I get the full list of unlocked tasks and start to try to fetch them one at a time. I am not taking into account to try to run the ones with the highest priority first. So I think I need to sort the unlocked list by priority first. Would you know how to sort a List by priority? I’m researching this now… Will keep you posted.

Thanks,

Jim


#12

Hi Jim,

I see, thanks for the update.

Well, as for the sorting, you could provide a custom Comparator that is based on the priority like:

List<LockedExternalTask> tasks = externalTaskService
    .fetchAndLock(5, "aWorkerId")
    .topic("aTopic", 10000L)
    .execute();
Collections.sort(tasks, new Comparator<LockedExternalTask>() {
  @Override
  public int compare(LockedExternalTask o1, LockedExternalTask o2) {
    return Long.compare(o1.getPriority(), o2.getPriority());
  }
});

Hope that helps.

Best,
Tobias


#13

Hi Jim,

I just read that you are looking for unlocked tasks first, my example is showing how to sort the locked tasks. But nonetheless, you could use it analogously for unlocked tasks as well.

But maybe you don’t event need to do that, since the ExternalTaskQuery allows for ordering by priority already:

externalTaskService.createExternalTaskQuery().orderByPriority().desc().list();

This will result in an ordered list with highest priority tasks first.

Hope that helps.

Best,
Tobias


#14

Yes, that’s perfect! I will give it a try and let you know how it’s working.

Thanks!

Jim


#15

I have a question regarding the externalTaskService fetchAndLock. I am using the topic() method to narrow it to one topic. What if I have a list of topics that I want to try to fetch any of them with the highest priority? How could I write the code when the list is a variable size of topics? Seems the REST API has this capability but not the Java API.

Thanks!

Jim


#16

It needs a method for topics(ArrayList topics)…


#17

Hi Jim,

did you have a look at examples in the external task documentation? You can do something like:

List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(10, "externalWorkerId")
  .topic("AddressValidation", 60L * 1000L)
  .topic("ShipmentScheduling", 120L * 1000L)
  .execute();

With that you can work with multiple topics.
In the priority documentation you can see an example that does exactly what you are trying to achieve, I guess.

Best,
Tobias


#18

Yeah I understand, but that’s if you know the names of the topics. The names of the topics in our system are an array of Strings determined by what models are loaded in the system. So we can’t write static code like since we don’t know the names and how many there are.


#19

A good feature request would be to extend the external task system to support topic name query with a “like” support. So you can query for topic name patterns. Then you can prefix your topics with namespaces.

As a workaround depending on how many tasks you are generating/what scale, you could do a get all tasks and do a parallel stream to filter based on topic names that start with/contain your namespace.


#20

Hey Jim,

do you have access to the list of topics that are of interest at this point?
I guess so, because otherwise a feature like

List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(10, "externalWorkerId", true)
  .topics(topicList, 60L * 1000L)
  .execute();

wouldn’t help you, right?

So, if you have the list of topics at hand, why not do something like

ExternalTaskQueryBuilder fetchAndLock = externalTaskService.fetchAndLock(10, "externalWorkerId", true);
for (String topic : topicList) {
  fetchAndLock.topic(topic, 60L * 1000L);
}
List<LockedExternalTask> tasks = fetchAndLock.execute();

Does that help you?

Best,
Tobias