upstream: the finished payload of the task that routed to this one with next, or the part of it at path. A start by an arrival has no upstream, and a task that on_fail or on_interrupt_next reaches is handed a failure or an interrupted record, so a blueprint refuses upstream there.
Use it for a value from the record of the task that routed to this one.
Keys
Key
Type
Default
gen
upstream
required
path
text
none
Every kind also accepts null_rate, unique, omit_rate and omit_when, which Generators describes.
Example
The task order routes to the task invoice, which publishes the amount of the order. An order starts every 60 seconds for 200 seconds, with the seed 42, so three orders start.
# Upstream: a value from the record of the task that routed here.# An order starts every 60 seconds and routes to an invoice. The run lasts 200 seconds,# so three orders start.## Run it with: desflow run examples/generators/upstream.yamlsimulation:sim_id:Genfactor:0random_seed:42logical_start_time:2026-01-01T00:00:00egress:-{type:Console}arrivals:orders:{dist:constant, value:60, spawn:order}tasks:order:payload:amount:{gen:integer, bounds:[10,20]}next:invoiceinvoice:payload:amount:{gen:upstream, path:amount}run:{until:200}
"""Upstream: a value from the record of the task that routed here, builder API.The builder version of `upstream.yaml`. The order routes to the invoice with `next`.Run it with: python examples/generators/upstream_builder.py"""importloggingfromdatetimeimportdatetime,timezonefromdesflowimportConsoleEgress,SimulationContextfromdesflow.valuesimportTemplateUNTIL=200defbuild()->SimulationContext:"""Builds the model."""app=SimulationContext(sim_id="Gen",factor=0,random_seed=42,logical_start_time=datetime(2026,1,1,tzinfo=timezone.utc),)app.add_egress(ConsoleEgress())app.add_arrival("orders","constant",value=60,spawn="order")order_payload=Template({"amount":{"gen":"integer","bounds":[10,20]}},name="tasks.order")invoice_payload=Template({"amount":{"gen":"upstream","path":"amount"}},name="tasks.invoice")@app.task(name="order",next="invoice")deforder(task_id):"""Gives one order."""returnorder_payload@app.task(name="invoice")definvoice(task_id):"""Gives the invoice of one order."""returninvoice_payloadreturnappif__name__=="__main__":logging.basicConfig(level=logging.INFO,format="%(levelname)s%(message)s")build().run(until=UNTIL)
"""Upstream: a value from the record of the task that routed here, low-level API.The low-level version of `upstream.yaml`: plain SimPy on a `DynamicRealtimeEnvironment`,which publishes each record with `publish_event`. Each draw is made with`Sampler.generator(<place>)`, the random sequence of the blueprint's generator at thatplace, so the draws are the blueprint's. The order publishes its record, then theinvoice takes the amount from it, as `upstream` reads the record of the task that routedto it.Needs: nothing.Run it with: python examples/generators/upstream_low_level.py"""importitertoolsimportloggingfromdatetimeimportdatetime,timezonefromdesflowimportConsoleEgress,DynamicRealtimeEnvironment,SamplerUNTIL=200START=datetime(2026,1,1,tzinfo=timezone.utc)ENVIRONMENT={"logical_start_time":START,"timezone":"UTC"}defbuild(env:DynamicRealtimeEnvironment)->None:"""Starts the processes on `env`."""sampler=Sampler(seed=42)amount=sampler.generator("tasks.order.payload.amount")deforders():fornumberinitertools.count(1):yieldenv.timeout(60)key,instance=f"orders-{number}",number-1order={"amount":int(amount.integers(10,20+1))}env.publish_event(key,order,task="order",instance=instance)env.publish_event(key,{"amount":order["amount"]},task="invoice",instance=instance)env.process(orders())defrun()->None:"""Runs the model unpaced into the console."""env=DynamicRealtimeEnvironment(factor=0,**ENVIRONMENT)env.setup_egress([ConsoleEgress()])build(env)try:env.run(until=UNTIL)finally:env.teardown()if__name__=="__main__":logging.basicConfig(level=logging.INFO,format="%(levelname)s%(message)s")run()
{"additionalProperties":false,"description":"`upstream`: the finished payload of the task that routed to this one with\n`next`, or the part of it at `path`. A start by an arrival has no upstream, and a\ntask that `on_fail` or `on_interrupt_next` reaches is handed a failure or an\ninterrupted record, so a blueprint refuses `upstream` there.","properties":{"null_rate":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"},{"$ref":"#/$defs/Placeholder"}],"default":null},"unique":{"default":false,"anyOf":[{"type":"boolean"},{"$ref":"#/$defs/Placeholder"}]},"omit_rate":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"},{"$ref":"#/$defs/Placeholder"}],"default":null},"omit_when":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null},"gen":{"anyOf":[{"const":"upstream","type":"string"},{"$ref":"#/$defs/Placeholder"}]},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null}},"required":["gen"],"title":"Upstream","type":"object"}