Search code examples
django-viewflow

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


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.


Solution

  • 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