Commit 95d0df9
authored
Patching (#524)
Patching is a mechanism for safely upgrading workflow code. It is an
alternative to [workflow
versioning](https://docs.dbos.dev/python/tutorials/workflow-tutorial#workflow-versioning-and-recovery)
(though they can be used together).
The problem patching solves is "How do I make a breaking change to a
workflow's code but continue execution of long-running workflows that
started on the old code version?" A breaking change is any change in
what steps run or the order in which they run.
To use patching, first enable it in configuration:
```python
config: DBOSConfig = {
"name": "dbos-starter",
"system_database_url": os.environ.get("DBOS_SYSTEM_DATABASE_URL"),
"enable_patching": True,
}
DBOS(config=config)
```
Next, when making a breaking change, use an `if DBOS.patch():`
conditional. `DBOS.patch()` returns `True` for new workflows (those
started after the breaking change) and `False` for old workflows (those
started before the breaking change). Therefore, if `DBOS.patch()` is
true, call the new code, else call the old code.
So let's say our workflow is:
```python
@DBOS.workflow()
def workflow():
foo()
bar()
```
We want to replace the call to `foo()` with a call to `baz()`, which is
a breaking change. We can do this safely using a patch:
```python
@DBOS.workflow()
def workflow():
if DBOS.patch("use-baz"):
baz()
else:
foo()
bar()
```
Now, new workflows will run `baz()`, while old workflows will safely
recover through `foo()`.
Once all workflows of the pre-patch code version are complete, we can
remove patches from our code. First, we deprecate the patch. This will
safely run workflows containing the patch marker, but will not insert
the patch marker into new workflows:
```python
@DBOS.workflow()
def workflow():
DBOS.deprecate_patch("use-baz")
baz()
bar()
```
Then, when all workflows containing the patch marker are complete, we
can remove the patch entirely and complete the workflow upgrade!
```python
@DBOS.workflow()
def workflow():
baz()
bar()
```
If any mistakes happen during the process (a breaking change is not
patched, or a patch is deprecated or removed prematurely), the workflow
will throw a clean `DBOSUnexpectedStepError` pointing to the step where
the problem occurred.
Also, one advanced feature is that if you need to make consecutive
breaking changes to the same code, you can stack patches:
```python
@DBOS.workflow()
def workflow():
if DBOS.patch("use-qux"):
qux()
elif DBOS.patch("use-baz"):
baz()
else:
foo()
bar()
```1 parent 85b8073 commit 95d0df9
File tree
6 files changed
+414
-5
lines changed- dbos
- tests
6 files changed
+414
-5
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
341 | 341 | | |
342 | 342 | | |
343 | 343 | | |
| 344 | + | |
344 | 345 | | |
345 | 346 | | |
346 | 347 | | |
| |||
350 | 351 | | |
351 | 352 | | |
352 | 353 | | |
| 354 | + | |
| 355 | + | |
353 | 356 | | |
354 | 357 | | |
355 | 358 | | |
| |||
1524 | 1527 | | |
1525 | 1528 | | |
1526 | 1529 | | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
| 1551 | + | |
| 1552 | + | |
| 1553 | + | |
| 1554 | + | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
1527 | 1574 | | |
1528 | 1575 | | |
1529 | 1576 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| 66 | + | |
66 | 67 | | |
67 | 68 | | |
68 | 69 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
143 | 143 | | |
144 | 144 | | |
145 | 145 | | |
146 | | - | |
| 146 | + | |
147 | 147 | | |
148 | 148 | | |
149 | 149 | | |
| |||
162 | 162 | | |
163 | 163 | | |
164 | 164 | | |
165 | | - | |
| 165 | + | |
166 | 166 | | |
167 | 167 | | |
168 | 168 | | |
| |||
182 | 182 | | |
183 | 183 | | |
184 | 184 | | |
| 185 | + | |
185 | 186 | | |
186 | 187 | | |
187 | 188 | | |
188 | 189 | | |
189 | 190 | | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
190 | 198 | | |
191 | 199 | | |
192 | 200 | | |
| |||
203 | 211 | | |
204 | 212 | | |
205 | 213 | | |
206 | | - | |
| 214 | + | |
207 | 215 | | |
208 | 216 | | |
209 | 217 | | |
| |||
219 | 227 | | |
220 | 228 | | |
221 | 229 | | |
222 | | - | |
| 230 | + | |
223 | 231 | | |
224 | 232 | | |
225 | 233 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2361 | 2361 | | |
2362 | 2362 | | |
2363 | 2363 | | |
| 2364 | + | |
| 2365 | + | |
| 2366 | + | |
| 2367 | + | |
| 2368 | + | |
| 2369 | + | |
| 2370 | + | |
| 2371 | + | |
| 2372 | + | |
| 2373 | + | |
| 2374 | + | |
| 2375 | + | |
| 2376 | + | |
| 2377 | + | |
| 2378 | + | |
| 2379 | + | |
| 2380 | + | |
| 2381 | + | |
| 2382 | + | |
| 2383 | + | |
| 2384 | + | |
| 2385 | + | |
| 2386 | + | |
| 2387 | + | |
| 2388 | + | |
| 2389 | + | |
| 2390 | + | |
| 2391 | + | |
| 2392 | + | |
| 2393 | + | |
| 2394 | + | |
| 2395 | + | |
| 2396 | + | |
| 2397 | + | |
| 2398 | + | |
| 2399 | + | |
| 2400 | + | |
| 2401 | + | |
| 2402 | + | |
| 2403 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2078 | 2078 | | |
2079 | 2079 | | |
2080 | 2080 | | |
2081 | | - | |
| 2081 | + | |
2082 | 2082 | | |
2083 | 2083 | | |
2084 | 2084 | | |
| |||
0 commit comments