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
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
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!
I would prefer not to specify a topicName. But is that required?
Can you try it in postman using a topic and without a topic.
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
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
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
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:
- 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
.
- 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
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
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
1 Like
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
Yes, thatâs perfect! I will give it a try and let you know how itâs working.
Thanks!
Jim
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
It needs a method for topics(ArrayList topics)âŚ
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
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.
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.
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