Workflow Engine Auto-Extraction
Developer guide for the Enezaframework workflow engine. Part of the Workflow series.
Table of Contents
- Overview
WorkflowInstanceHolds the Target- Web Path —
_evaluate_and_route() - Celery Path —
evaluate_condition_step() - Service Function —
evaluate_condition_for_document() - Related Guides
Overview
Callers never pass object_id to condition queries. A WorkflowInstance already stores the target document, so the engine extracts the primary key and passes it to SavedQuery.get_queryset(). The extraction happens in two code paths, both ending in the same scoped filtering.
flowchart TD
WI["WorkflowInstance<br/>content_type + object_id + document"] --> W["Web path:<br/>ConditionStepHandler._evaluate_and_route()"]
WI --> C["Celery path:<br/>evaluate_condition_step()"]
W --> WQ["get_queryset(object_id=wf_instance.object_id)"]
C --> S["evaluate_condition_for_document(document, query)"]
S --> SQ["object_id = str(document.pk)"]
SQ --> CQ["get_queryset(object_id=object_id)"]WorkflowInstance Holds the Target
Defined in enezaworkflowengine/models/workflowtemplate.py:104, WorkflowInstance stores:
object_id = models.TextField(null=True, blank=True)
document = GenericForeignKey('content_type', 'object_id')
(models/workflowtemplate.py:124-125). So workflow_instance.object_id and workflow_instance.document.pk are two routes to the same primary key.
Web Path — _evaluate_and_route()
File: enezaworkflowengine/services/step_handlers.py:233
The condition step handler has direct access to workflow_instance.object_id and passes it without an extra query:
# services/step_handlers.py:233-243
def _evaluate_and_route(self, step_instance, workflow_instance, step_template):
condition_query = step_template.condition_expression
# ...
queryset = condition_query.get_queryset(object_id=workflow_instance.object_id)
result = queryset.count() > 0
Celery Path — evaluate_condition_step()
File: enezaworkflowengine/tasks/workflow_tasks.py:216
The background task delegates to the service function, which extracts the PK from the resolved document:
# tasks/workflow_tasks.py:253-254
from enezaworkflowengine.services.condition_step import evaluate_condition_for_document
result = evaluate_condition_for_document(workflow_instance.document, condition_query)
The task itself needed no change: the extraction lives in the service function, so both paths share it.
Service Function — evaluate_condition_for_document()
File: enezaworkflowengine/services/condition_step.py:16
def evaluate_condition_for_document(document, condition_query):
if not document or not condition_query:
return False
try:
object_id = str(document.pk)
queryset = condition_query.get_queryset(object_id=object_id)
result_count = queryset.count()
return result_count > 0
except Exception as e:
raise ConditionStepError(f"Failed to evaluate condition: {str(e)}")
This function is also usable outside the engine — for previewing or testing a condition against a specific document.
sequenceDiagram
participant T as evaluate_condition_step (Celery)
participant S as evaluate_condition_for_document
participant Q as SavedQuery
T->>S: (workflow_instance.document, condition_query)
S->>S: object_id = str(document.pk)
S->>Q: get_queryset(object_id=object_id)
Q-->>S: queryset
S->>S: return count > 0
S-->>T: bool