Skip to content

Make BPMN waiting refresh internal and lazy#460

Merged
essweine merged 1 commit into
mainfrom
rwt2
Apr 27, 2026
Merged

Make BPMN waiting refresh internal and lazy#460
essweine merged 1 commit into
mainfrom
rwt2

Conversation

@jbirddog
Copy link
Copy Markdown
Contributor

refresh_waiting_tasks() forced consumers to understand when BPMN internals needed WAITING tasks refreshed. Because the method scanned waiting tasks and timers, consumers had to call it defensively, making it both a leaky abstraction and a performance trap for hot-path runners.

Keep the public BpmnWorkflow.refresh_waiting_tasks() method as a compatibility no-op and move refresh behavior into engine-owned paths: index WAITING tasks as states change, prune removed tasks, refresh structural waits from task completion notifications, refresh matched event catches directly, schedule timer waits by due time, and rebuild the private index after deserialization.

Add generated BPMN stress fixtures and a Makefile target for repeatable measurement: make RUN='uv run' waiting-task-stress.

Stress results with 100 dormant timers and 100 ready hot-path steps: ready hot path dropped from 10,300 to 100 timer checks (103x fewer), and staggered timers dropped from 1,900 to 10 timer checks (190x fewer). Final stress elapsed times were about 0.092s and 0.0044s respectively.

Verified with: make RUN='uv run' tests; make RUN='uv run' waiting-task-stress.

refresh_waiting_tasks() forced consumers to understand when BPMN internals needed WAITING tasks refreshed. Because the method scanned waiting tasks and timers, consumers had to call it defensively, making it both a leaky abstraction and a performance trap for hot-path runners.

Keep the public BpmnWorkflow.refresh_waiting_tasks() method as a compatibility no-op and move refresh behavior into engine-owned paths: index WAITING tasks as states change, prune removed tasks, refresh structural waits from task completion notifications, refresh matched event catches directly, schedule timer waits by due time, and rebuild the private index after deserialization.

Add generated BPMN stress fixtures and a Makefile target for repeatable measurement: make RUN='uv run' waiting-task-stress.

Stress results with 100 dormant timers and 100 ready hot-path steps: ready hot path dropped from 10,300 to 100 timer checks (103x fewer), and staggered timers dropped from 1,900 to 10 timer checks (190x fewer). Final stress elapsed times were about 0.092s and 0.0044s respectively.

Verified with: make RUN='uv run' tests; make RUN='uv run' waiting-task-stress.
@essweine
Copy link
Copy Markdown
Contributor

Well, I never liked refresh waiting tasks either. This is somewhat more complicated than it needs to be and I don't like the attribute checks in workflow (I've worked hard to separate bpmn functionality from the core functionality) but whatever.

@essweine essweine merged commit 9541baf into main Apr 27, 2026
6 checks passed
@essweine essweine deleted the rwt2 branch April 27, 2026 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants