lookup: a row of the finished payloads of the task task, or the part of it at path (dotted; an integer part indexes a list).
A row is readable from the instant the task's finished record is published. The task keeps its last history rows (default 1,000,000).
strategy is random (the default), first (the oldest row kept) or last (the newest). histogram splits the rows kept, in the order they were written, into bins of the stated shares; a draw picks a bin by its frequency and then a row of the bin at random, so it is for random only. A bin that holds no row yet is left out of the draw, and while no bin with a frequency above 0 holds a row (a few rows and a last bin of frequency 0), the draw is over all the rows. latest_by keeps only the newest row for each value of that field of the row, so a lookup sees a customer's latest address; strategy and histogram then choose among those rows, oldest first by the time each was written. distinct draws without replacement within one repeat, so the items of one order differ.
Use it for a value from a record that another task already published, such as an existing customer.
Every kind also accepts null_rate, unique, omit_rate and omit_when, which Generators describes.
HistogramBin
One bin of a lookup histogram: bin is the share of the rows it covers, in the order they were written, and frequency is the chance that a draw falls in it. Both are scaled to add up to 1, so {bin: 2, frequency: 8}, {bin: 8, frequency: 2} means the same as 0.2 with 0.8, and 0.8 with 0.2.
Key
Type
Default
bin
number
required
frequency
number
required
Example
Three customers start at time 0. Each order picks one of them at random and publishes its customer_id. An order starts every 60 seconds for 200 seconds, with the seed 42, so three orders start.
# Lookup: a value from a finished record of another task.# Three customers start at time 0, and an order starts every 60 seconds. The run lasts# 200 seconds, so three orders start.## Run it with: desflow run examples/generators/lookup.yamlsimulation:sim_id:Genfactor:0random_seed:42logical_start_time:2026-01-01T00:00:00egress:-{type:Console}arrivals:customers:{initial:3, dist:constant, value:3600, spawn:customer}orders:{dist:constant, value:60, spawn:order}tasks:customer:payload:customer_id:{gen:sequence, start:100}order:payload:customer_id:{gen:lookup, task:customer, path:customer_id}run:{until:200}
"""Lookup: a value from a finished record of another task, builder API.The builder version of `lookup.yaml`. A task that something looks up keeps its finishedrows, so the customer task sets `history`.Run it with: python examples/generators/lookup_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("customers","constant",value=3600,spawn="customer",initial=3)app.add_arrival("orders","constant",value=60,spawn="order")customer_payload=Template({"customer_id":{"gen":"sequence","start":100}},name="tasks.customer")order_payload=Template({"customer_id":{"gen":"lookup","task":"customer","path":"customer_id"}},name="tasks.order",)@app.task(name="customer",history=1_000_000)defcustomer(task_id):"""Gives one customer."""returncustomer_payload@app.task(name="order")deforder(task_id):"""Gives one order."""returnorder_payloadreturnappif__name__=="__main__":logging.basicConfig(level=logging.INFO,format="%(levelname)s%(message)s")build().run(until=UNTIL)
"""Lookup: a value from a finished record of another task, low-level API.The low-level version of `lookup.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 script keeps the `customer_id` of eachcustomer it has published, and an order takes one at an index drawn with`integers(len(rows))`, as `lookup` does with `strategy: random`.Needs: nothing.Run it with: python examples/generators/lookup_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)seller=sampler.generator("tasks.order.payload.customer_id")customers:list=[]# the customer_id of each customer so far, oldest firstdefcustomer_arrivals():yieldenv.timeout(0)fornumberinrange(1,4):customers.append(100+number-1)env.publish_event(f"customers-{number}",{"customer_id":customers[-1]},task="customer",instance=number-1,)deforders():fornumberinitertools.count(1):yieldenv.timeout(60)payload={"customer_id":customers[int(seller.integers(len(customers)))]}env.publish_event(f"orders-{number}",payload,task="order",instance=number-1)env.process(customer_arrivals())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":"`lookup`: a row of the finished payloads of the task `task`, or the part of it\nat `path` (dotted; an integer part indexes a list).\n\nA row is readable from the instant the task's finished record is published. The\ntask keeps its last `history` rows (default 1,000,000).\n\n`strategy` is `random` (the default), `first` (the oldest row kept) or `last` (the\nnewest). `histogram` splits the rows kept, in the order they were written, into\nbins of the stated shares; a draw picks a bin by its frequency and then a row of the\nbin at random, so it is for `random` only. A bin that holds no row yet is left out\nof the draw, and while no bin with a frequency above 0 holds a row (a few rows and\na last bin of frequency 0), the draw is over all the rows. `latest_by` keeps only\nthe newest row for each value of that field of the row, so a lookup sees a\ncustomer's latest address; `strategy` and `histogram` then choose among those rows,\noldest first by the time each was written. `distinct` draws without replacement\nwithin one `repeat`, so the items of one order differ.","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":"lookup","type":"string"},{"$ref":"#/$defs/Placeholder"}]},"task":{"type":"string"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null},"strategy":{"default":"random","anyOf":[{"enum":["random","first","last"],"type":"string"},{"$ref":"#/$defs/Placeholder"}]},"histogram":{"anyOf":[{"items":{"$ref":"#/$defs/HistogramBin"},"type":"array"},{"type":"null"}],"default":null},"latest_by":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null},"distinct":{"default":false,"anyOf":[{"type":"boolean"},{"$ref":"#/$defs/Placeholder"}]}},"required":["gen","task"],"title":"Lookup","type":"object"}