Viewflow Process won't exit cleanly with split-n-join tasks?

239 Views Asked by At

Say I have a Process which has two optional View tasks to the finish:

--> Split --> optional_view_1 ---> Join ----> finish
       |                            ^
       |                            |
       -----> optional_view_2 -------

Let's say both tasks are assigned, but a human logs in and completes optional_view_1. The Join itself and indeed the End node both end up with status DONE. However, the Process will get stuck and NOT exit cleanly due to optional_view_2.

The questions are:

  • how to finish the process cleanly (i.e. not cancel it) and without races
  • from where (e.g. from inside the Join or a Handler after each View to cancel the other one?)

I originally posted this as an issue, along with a possible coded solution. In summary the code:

  1. Overrides the Activation "done" associated with the Join
  2. The override checks if the Join has wait_all=False
  3. And if so, tries to find any other tasks the Join is waiting for
  4. And cancels them

The code for step 3 is the bit I am most worried about. It is a modified version of the Viewflow code handling the wait_all=True case and looks like this in summary:

previous = self.task.previous.exclude(status=STATUS.CANCELED).all()
join_prefixes = set(prev.token.get_common_split_prefix(self.task.token, prev.pk)
                    for prev in previous)
#
# Don't forget to exclude the previous tasks.
#
join_token_prefix = next(iter(join_prefixes))
active = self.flow_class.task_class._default_manager \
    .filter(process=self.process, token__startswith=join_token_prefix) \
    .exclude(status__in=[STATUS.DONE, STATUS.CANCELED], pk__in=[prev.pk for prev in previous])
 for task in active:
     cancel_task(task)

Any comments on whether this is the right approach or not would be welcome.

1

There are 1 best solutions below

1
On BEST ANSWER

That BPMN process would not be complete, it's the right behavior. The join outgoing path would be executed twice.

To have an optional branch, you need to implement event-based gateway. That would subscribe to flow task end signal (override ready method) and cancel nonfinished tasks.

https://www.youtube.com/watch?v=pyJM_V8Ji2w