OrchardCore icon indicating copy to clipboard operation
OrchardCore copied to clipboard

Workflows queuing

Open Piedone opened this issue 9 months ago • 5 comments

Is your feature request related to a problem?

Workflows can potentially be expensive to run (just as any logic), e.g. doing a bunch of content updates, sending e-mails... When workflows are triggered by user interactions, like form submissions, this expense can be incurred unevenly during the day, making resource usage spike, causing the app to become unstable. A typical example is business process-related form submissions that spike at the start of the workday or after lunch break.

Describe the solution you'd like

If it's not necessary that the workflow runs immediately, spikes can be smoothed out by using a queue for workflow executions behind the scenes, executing them in a steady pace instead of on-demand.

The queue can be something simple and Workflows-specific, storing entries in the DB, so I'm not talking about implementing some kind of generic queue. It should also build on the already existing workflow instance management: with an option per workflow, we could make the workflow execution be suspended right when it start, and have a background task that takes batches of these instances and executes them (with a configurable batch size) every minute.

Describe alternatives you've considered

Lower-level ways of handling the load can work too, like temporarily scaling the app. However, that involves complexity and cost, where having such a queue can be a turn-key solution that works in any hosting environment for workflows that allow it.

Piedone avatar Apr 15 '25 17:04 Piedone

Should it be the responsibility of a workflow activity to schedule/delegate a job and wait for its completion? Reusing your examples: "doing a bunch of content updates, sending e-mails" maybe these activities should have the option to execute these tasks asynchronously, in the jobs queue, which would pause the workflow (optionally)?

The issue I am seeing is that some activities don't make sense for delayed/remote execution, for instance the notifications, or redirects, or http response.

But this could be both, like some activities may support "async" operations, but we could also support it at the workflow level to run from a separate thread. They can be complementary.

sebastienros avatar Apr 17 '25 17:04 sebastienros

We triaged this issue and set the milestone according to the priority we think is appropriate (see the docs on how we triage and prioritize issues).

This indicates when the core team may start working on it. However, if you'd like to contribute, we'd warmly welcome you to do that anytime. See our guide on contributions here.

github-actions[bot] avatar Apr 17 '25 17:04 github-actions[bot]

Yeah, this wouldn't work for all workflows, hence I'd make it opt-in per workflow type.

But the per-activity idea is an interesting one too. I think that's ultimately better if you really know what you're doing, However, it would be harder to use (to determine what you want to queue) and possibly only useful if single Tasks are really impactful (and thus the benefits of queuing them separately outweighs the overhead of using a queue).

Piedone avatar Apr 17 '25 22:04 Piedone

Just as a thought experiment, can't this be already achieved with the current activities? E.g. you can effectively split the workflow into two workflows:

  • The first workflow may fill a "queue" by creating special content items during the desired events.
  • Have a second workflow that uses the timer as a starting point and processes the created content items. This can do all the related tasks one-by-one and evenly distributed.

This solution is not quite as sophisticated as a full queue implementation, but may be workaround.

gvkries avatar Apr 22 '25 11:04 gvkries

I suppose you could create such a kind of queue implementation with Workflows itself, though keep in mind that you have to store and retrieve the workflow instance's state; I don't know how that would work with a content item for this (you can store and retrieve simple context, but I don't think you'd be able to restore a whole HttpContext, necessary for form submissions, for example).

Piedone avatar Apr 22 '25 14:04 Piedone