I am working on a document management app. Every document can be updated which produces a new version of the document. The document update and approval process is done with an camunda workflow. In the last part of the workflow there is a user task for specific users to acknowledge the new document version. For this task i am using the multi-instance feature.
so far so god …
The request is now that this acknowledge task should only be created for specific user when this user does not already have a open task for that document.
Of course i simply can adjust the list of multi-instance users on every run.
But now the tricky thing…
Expected is some indication at history that the task for the specific user has been canceled/not created because there is a pending open task for version x of that document.
I tried different approaches already:
- Create the tasks for all selected users and delete/complete the once which have already open once in a TaskListener → did not work because task deletion or completion is not possible within a TaskListener
- Adjust (reduce) the multi-instance user list and manually insert history events with the usage of a custom HistoryEventHandler → seems to work but feels very hacky and is a nightmare to maintain.
Any ideas? I would prefer option 1, but I could not find any way to automatically complete/delete specific tasks of a multi-instance user task.
What about making the MI a sub-process?
(User-Document) → meaning combination of User and Document # (not including version #)
Service Task - Check for Open Acknowledge Tasks for User-Document
Service Task / Message - Close Prior Acknowledge Tasks for User-Document
User Task - Acknowledge User-Document (for this version) … with an interrupting boundary Message Receive for (User-Document has been updated)
This way, the users are only ever being asked to acknowledge the latest version of the document (if you’re away for 3 weeks, you want to read and acknowledge the one that came out last week, not a month ago…)
The implementation of the acknowledgement task works in that way, that the user sees a compare view of that document (the version that the user already acknowledged/knows against the lastest effective version). That is why keeping the oldest acknowledgement task makes sense.
I think what I was meaning was that you could keep track of something like:
| User | Document | Version | Outcome |
| 1 | 1 | 1 | Read |
| 2 | 1 | 1 | Read |
| 1 | 1 | 2 | Read |
| 2 | 1 | 2 | Read |
| 1 | 1 | 3 | Pending |
| 2 | 1 | 3 | Read |
So now when Document 1 Version 4 comes in, you want to:
For each user:
. Find all Pending requests
. Cancel Pending request (Message interrupting will do this!)
. Add new Pending
In the new Pending (per user), you can the compare the Current document to the last Read version (since the outcomes are different)
| User | Document | Version | Outcome |
| 1 | 1 | 1 | Read |
| 2 | 1 | 1 | Read |
| 1 | 1 | 2 | Read |
| 2 | 1 | 2 | Read |
| 1 | 1 | 3 | Canceled |
| 2 | 1 | 3 | Read |
| 1 | 1 | 3 | Pending |
| 2 | 1 | 3 | Pending |
You could even do cleanup after a User-Document-Version is read… Removing the prior “Read” versions
I agree that your approach would work, but i would need to change the implementation of the Acknowledgement task, which is located in another client system. Of course it is possible, but for now i am trying to avoid it. Camunda is a replacement for another old workflow system and i am trying to recreate the same behavior of the old system.
I already found one new approach: “Conditional Boundary Event”
For the condition i use the checking of an existing pending task.
This cancels the task right at creation time, which is what i wanted, but it looks like the task instance is even not flushed to the database and no historical task data is created. In some cases this would make sense, but in my usecase i need the historical data.
Is it somehow possible to decuple the “Conditional Boundary Event” from the task creation transaction, that the task gets persisted in database before it is canceled? I played around with the asynchronous continuations already, but i did not see any difference.
As a user task, it should be persisted to the DB immediately.
This is basically the approach that I was suggesting, but I would have thought that you would want to keep the newest version, rather than remove the newest version…
As a user task, it should be persisted to the DB immediately.
For my use case, it looks like that this is not the case when the task completed immediately by the Conditional Boundary Event. Even when i query for historic activities, these tasks are returned as ActivityType = “UserTask”, but does not have TaskId or TaskAssignee.