Fast-Forward to Parquet
This example generates a week of a shop's orders at factor=0.0 and writes them to Parquet files, on the local disk or in S3-compatible storage. Egress shows Google Cloud Storage and Azure Blob Storage. Each tab shows the example written one way: as a YAML blueprint, with the builder API, or with the low-level API. Ways to write a simulation compares the three.
desflow is built for real-time digital twins, but the same model can also run faster than real time. With factor set to 0 the clock does not wait for the wall clock, and logical_start_time puts the week before now, so the records are stamped as history. Look for the Parquet files the run writes, one per batch, with one row for each lifecycle event.
Before You Start
The example needs only desflow, which each Quick Start below installs, and no other service. With PARQUET_FILESYSTEM=s3 it writes to an object store instead, which needs Docker and the odctl profile storage. Services for the Examples lists the services the other examples need.
Steps
Run It
This example builds the simulation of the builder example in the Builder tab from a YAML blueprint, with no Python. With factor: 0.0 the clock is detached from the wall clock, so a week of shop orders is written to Parquet as fast as the machine allows.
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
What It Does
The run writes each batch as a Parquet file of its own, such as data/events_1a2b3c4d.parquet, and ends on its own. default_path is a file name prefix, not a folder. Egress explains the file names and how to read the files back as one table. A second run adds its files beside the first run's, so delete data/ before running again, or set DEST_PATH to a new folder. On a laptop, one run of a week of simulated time takes about 20 seconds. It writes 725 files with 3.6 million rows in all, one row per lifecycle event. Without a router, the egress drops telemetry and writes each event as one flat row, so the columns are stream_type, sim_ts, timestamp, key, task, instance, path_id and status. logical_start_time: -7d stamps the week as history that ends now.
To write to S3 instead, install odctl (uv tool install "odctl>=1.0,<2" or pip install "odctl>=1.0,<2"), start the object store, and set these variables before the run command. All three versions read the same ones. The files are written under the odctl-dev/history/ prefix, which you can browse at http://localhost:8889.
Stop it with odctl down storage --volumes when you are finished.
This version builds the simulation with the builder API (SimulationContext) and writes with ParquetStorageEgress.
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
To write to S3 instead, install odctl (uv tool install "odctl>=1.0,<2" or pip install "odctl>=1.0,<2"), start the object store, and set these variables before the run command. All three versions read the same ones. The files are written under the odctl-dev/history/ prefix, which you can browse at http://localhost:8889.
Stop it with odctl down storage --volumes when you are finished.
This version wires the simulation by hand on DynamicRealtimeEnvironment, the low-level API, and writes with ParquetStorageEgress.
Quick Start
desflow examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:
To write to S3 instead, install odctl (uv tool install "odctl>=1.0,<2" or pip install "odctl>=1.0,<2"), start the object store, and set these variables before the run command. All three versions read the same ones. The files are written under the odctl-dev/history/ prefix, which you can browse at http://localhost:8889.
Stop it with odctl down storage --volumes when you are finished.
Check the Result
The three tabs write the same records, which a test checks by running each version unpaced. A real run writes them as rows of Parquet files under data/. desflow run parquet.yaml --sample 4 --stdout prints the first four events as JSON lines instead, and writes no file:
Each event becomes one row of a file, and the two fields of value, path_id and status, become columns of their own.
Full Files
Full files
filesystem is a mapping. type picks the local disk or S3, and the other keys are passed to PyArrow's S3FileSystem. A key whose value is empty is left out, so with no variables set the mapping is the local disk.
Files live in the examples/yaml/ folder of the repository, and the label on each block below is its path there.
This script simulates 7 days of the shop. It flattens the lifecycle events into rows, routes them to one Parquet dataset and writes them as fast as the machine allows.
Scripts live in the examples/ folder of the repository, and the label on the block below is this one's path there.
| examples/builder/parquet_example.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
This script simulates 7 days of the shop. It flattens the lifecycle events into rows, routes them to one Parquet dataset and writes them as fast as the machine allows.
Scripts live in the examples/ folder of the repository, and the label on the block below is this one's path there.
| examples/low-level/parquet_example.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |