Several Resources
A task can hold more than one resource at once. This page shows how.
What It Is
Some work needs more than one resource at a time: an order needs a picker and a bench, and a patient needs a doctor and a room. A task can hold several resources at once, or keep a unit and hand it to the next task of its flow.
How to Use It
A task can hold several resources at once: resource: [picker, bench] asks for a picker, then, while it holds the picker, for the bench. The task is served once it holds all of them, and it releases all of them when it finishes. While it waits for the bench, it holds the picker. The units are granted one at a time, never together, so a task can hold some of its resources while it waits for the rest. patience covers the whole acquisition. A plain interrupt keeps the units already held and asks again only for the one it waits for, and on_interrupt: abandon gives every unit back.
A task can also hand a unit to the next task of its flow with keep: the next task holds it from the start and gives it back once it publishes started. An order can therefore keep the picker until it is on the packing bench, as Hand Off to a Resource shows step by step. A task that reneges, whose wait fails with no on_fail, or that has no next task gives it back when it ends. If the unit is preempted while the next task holds it, that task is interrupted and follows its on_interrupt. The unit a task keeps stays with the entity until that next task starts. A child flow started by wait: {task: ...} gives back only the units its own tasks asked for. The competing-resources example does both:
In the low-level API several resources are nested requests, and a handoff is a request released by the next process.
Hold a Unit Between Steps
seize asks for a unit at the start of a task and keeps it until a release, in this task or a later one of the flow, so the unit is held across steps that name no resource. seize is a resource name, or {resource, priority, preempt, patience}. release frees the oldest unit of a resource that the flow holds from a seize or an open, and does nothing when it holds none. A unit still held when the flow ends stays held, as in SimPy, so a flow writes release before it ends. A unit lost to a preemption is asked for again under resume and restart, and is gone under abandon. release also takes {handle: name} for one opened request and {resource, task, where} for the units that other flows of a task hold. A priority on a seize needs the resource to set queue: priority, as picker does here. The clear task below frees the picker from every rush order that holds it.
@app.task(seize="picker") and @app.task(release="picker") take the same values.
The process holds the request itself: picker = shop.picker.request() and yield picker, then shop.picker.release(picker) when the order is on the bench.
How It Works
One order of acquisition. Two tasks that acquire the same two resources in opposite orders can each hold one and wait for ever for the other. desflow loads such a model and logs one WARNING, from the logger desflow.builder.context, that names both tasks. A unit held with seize counts as held. Every task should acquire shared resources in one order. The rule also covers keep handoffs and the request branches of a wait, and a keep for a request branch of a wait is still refused when the model is built (Wait for a Unit, an Item or Room). Competing Resources shows what a partial holding costs.
Example: Competing Resources
In the competing-resources example, orders keep the picker until they are on the bench, and gifts hold the picker and the bench together. It needs no Docker service and ends on its own after 120 simulation seconds.
The tutorial page Competing Resources teaches these features step by step.
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
The whole file is examples/yaml/competing_resources.yaml.
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
The whole file is examples/builder/competing_resources_example.py.
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
The whole file is examples/low-level/competing_resources_example.py.