Stale document model when workflow actions trigger further actions
If a workflow action A triggers an event which triggers a workflow action B, the document models may become out of sync with the database, giving very unexpected results.
Example:
A workflow has an initial state S1 with two actions on entry, A and C. A second state S2 has action B as entry action. There is a transition T from S1 to S2. There is a trigger for transition T which is triggered by an event caused by the execution of action A.
If B modifies the context document (e.g., changes the label) and C does something else (but also saves the document), B's label change will not be reflected. This happens because C's context document model is not refreshed from the database after B has modified the database state.
Cause:
In Workflow.launch_for
, a Document instance is created with self.instances.create(document=document)
.
The same model instance is used for all subsequent initial actions without being refreshed from the database.
Action B in the example will be executed from WorkflowInstanceLogEntry.save()
, which is called by handler_trigger_transition
. In handler_trigger_transition
, a different WorkflowInstance instance (and thus a different Document instance) is created by calling WorkflowInstance.objects.filter
. These two Document instances will be out of sync.
Possible solution:
Not sure about this, but adding context['document'].refresh_from_db()
in WorkflowAction.execute
(directly before calling the subclass execute
) seems to help.
Edit: Nope, the above solution is not enough for this related case: If action A saves to the db after triggering the event, the changes in the triggered action C will also be overwritten (for example as in .DocumentMetadata.save()
)
Edit 2: In Document.save()
, the super(..).save()
call will trigger launching workflows. If state actions trigger transitions which trigger other state actions, this document instance will become out-of-sync with the db and we should call self.refresh_from_db()