pyworkflow-engine 0.1.7__py3-none-any.whl → 0.1.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyworkflow/__init__.py +10 -1
- pyworkflow/celery/tasks.py +272 -24
- pyworkflow/cli/__init__.py +4 -1
- pyworkflow/cli/commands/runs.py +4 -4
- pyworkflow/cli/commands/setup.py +203 -4
- pyworkflow/cli/utils/config_generator.py +76 -3
- pyworkflow/cli/utils/docker_manager.py +232 -0
- pyworkflow/config.py +94 -17
- pyworkflow/context/__init__.py +13 -0
- pyworkflow/context/base.py +26 -0
- pyworkflow/context/local.py +80 -0
- pyworkflow/context/step_context.py +295 -0
- pyworkflow/core/registry.py +6 -1
- pyworkflow/core/step.py +141 -0
- pyworkflow/core/workflow.py +56 -0
- pyworkflow/engine/events.py +30 -0
- pyworkflow/engine/replay.py +39 -0
- pyworkflow/primitives/child_workflow.py +1 -1
- pyworkflow/runtime/local.py +1 -1
- pyworkflow/storage/__init__.py +14 -0
- pyworkflow/storage/base.py +35 -0
- pyworkflow/storage/cassandra.py +1747 -0
- pyworkflow/storage/config.py +69 -0
- pyworkflow/storage/dynamodb.py +31 -2
- pyworkflow/storage/file.py +28 -0
- pyworkflow/storage/memory.py +18 -0
- pyworkflow/storage/mysql.py +1159 -0
- pyworkflow/storage/postgres.py +27 -2
- pyworkflow/storage/schemas.py +4 -3
- pyworkflow/storage/sqlite.py +25 -2
- {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.10.dist-info}/METADATA +7 -4
- pyworkflow_engine-0.1.10.dist-info/RECORD +91 -0
- pyworkflow_engine-0.1.10.dist-info/top_level.txt +1 -0
- dashboard/backend/app/__init__.py +0 -1
- dashboard/backend/app/config.py +0 -32
- dashboard/backend/app/controllers/__init__.py +0 -6
- dashboard/backend/app/controllers/run_controller.py +0 -86
- dashboard/backend/app/controllers/workflow_controller.py +0 -33
- dashboard/backend/app/dependencies/__init__.py +0 -5
- dashboard/backend/app/dependencies/storage.py +0 -50
- dashboard/backend/app/repositories/__init__.py +0 -6
- dashboard/backend/app/repositories/run_repository.py +0 -80
- dashboard/backend/app/repositories/workflow_repository.py +0 -27
- dashboard/backend/app/rest/__init__.py +0 -8
- dashboard/backend/app/rest/v1/__init__.py +0 -12
- dashboard/backend/app/rest/v1/health.py +0 -33
- dashboard/backend/app/rest/v1/runs.py +0 -133
- dashboard/backend/app/rest/v1/workflows.py +0 -41
- dashboard/backend/app/schemas/__init__.py +0 -23
- dashboard/backend/app/schemas/common.py +0 -16
- dashboard/backend/app/schemas/event.py +0 -24
- dashboard/backend/app/schemas/hook.py +0 -25
- dashboard/backend/app/schemas/run.py +0 -54
- dashboard/backend/app/schemas/step.py +0 -28
- dashboard/backend/app/schemas/workflow.py +0 -31
- dashboard/backend/app/server.py +0 -87
- dashboard/backend/app/services/__init__.py +0 -6
- dashboard/backend/app/services/run_service.py +0 -240
- dashboard/backend/app/services/workflow_service.py +0 -155
- dashboard/backend/main.py +0 -18
- docs/concepts/cancellation.mdx +0 -362
- docs/concepts/continue-as-new.mdx +0 -434
- docs/concepts/events.mdx +0 -266
- docs/concepts/fault-tolerance.mdx +0 -370
- docs/concepts/hooks.mdx +0 -552
- docs/concepts/limitations.mdx +0 -167
- docs/concepts/schedules.mdx +0 -775
- docs/concepts/sleep.mdx +0 -312
- docs/concepts/steps.mdx +0 -301
- docs/concepts/workflows.mdx +0 -255
- docs/guides/cli.mdx +0 -942
- docs/guides/configuration.mdx +0 -560
- docs/introduction.mdx +0 -155
- docs/quickstart.mdx +0 -279
- examples/__init__.py +0 -1
- examples/celery/__init__.py +0 -1
- examples/celery/durable/docker-compose.yml +0 -55
- examples/celery/durable/pyworkflow.config.yaml +0 -12
- examples/celery/durable/workflows/__init__.py +0 -122
- examples/celery/durable/workflows/basic.py +0 -87
- examples/celery/durable/workflows/batch_processing.py +0 -102
- examples/celery/durable/workflows/cancellation.py +0 -273
- examples/celery/durable/workflows/child_workflow_patterns.py +0 -240
- examples/celery/durable/workflows/child_workflows.py +0 -202
- examples/celery/durable/workflows/continue_as_new.py +0 -260
- examples/celery/durable/workflows/fault_tolerance.py +0 -210
- examples/celery/durable/workflows/hooks.py +0 -211
- examples/celery/durable/workflows/idempotency.py +0 -112
- examples/celery/durable/workflows/long_running.py +0 -99
- examples/celery/durable/workflows/retries.py +0 -101
- examples/celery/durable/workflows/schedules.py +0 -209
- examples/celery/transient/01_basic_workflow.py +0 -91
- examples/celery/transient/02_fault_tolerance.py +0 -257
- examples/celery/transient/__init__.py +0 -20
- examples/celery/transient/pyworkflow.config.yaml +0 -25
- examples/local/__init__.py +0 -1
- examples/local/durable/01_basic_workflow.py +0 -94
- examples/local/durable/02_file_storage.py +0 -132
- examples/local/durable/03_retries.py +0 -169
- examples/local/durable/04_long_running.py +0 -119
- examples/local/durable/05_event_log.py +0 -145
- examples/local/durable/06_idempotency.py +0 -148
- examples/local/durable/07_hooks.py +0 -334
- examples/local/durable/08_cancellation.py +0 -233
- examples/local/durable/09_child_workflows.py +0 -198
- examples/local/durable/10_child_workflow_patterns.py +0 -265
- examples/local/durable/11_continue_as_new.py +0 -249
- examples/local/durable/12_schedules.py +0 -198
- examples/local/durable/__init__.py +0 -1
- examples/local/transient/01_quick_tasks.py +0 -87
- examples/local/transient/02_retries.py +0 -130
- examples/local/transient/03_sleep.py +0 -141
- examples/local/transient/__init__.py +0 -1
- pyworkflow_engine-0.1.7.dist-info/RECORD +0 -196
- pyworkflow_engine-0.1.7.dist-info/top_level.txt +0 -5
- tests/examples/__init__.py +0 -0
- tests/integration/__init__.py +0 -0
- tests/integration/test_cancellation.py +0 -330
- tests/integration/test_child_workflows.py +0 -439
- tests/integration/test_continue_as_new.py +0 -428
- tests/integration/test_dynamodb_storage.py +0 -1146
- tests/integration/test_fault_tolerance.py +0 -369
- tests/integration/test_schedule_storage.py +0 -484
- tests/unit/__init__.py +0 -0
- tests/unit/backends/__init__.py +0 -1
- tests/unit/backends/test_dynamodb_storage.py +0 -1554
- tests/unit/backends/test_postgres_storage.py +0 -1281
- tests/unit/backends/test_sqlite_storage.py +0 -1460
- tests/unit/conftest.py +0 -41
- tests/unit/test_cancellation.py +0 -364
- tests/unit/test_child_workflows.py +0 -680
- tests/unit/test_continue_as_new.py +0 -441
- tests/unit/test_event_limits.py +0 -316
- tests/unit/test_executor.py +0 -320
- tests/unit/test_fault_tolerance.py +0 -334
- tests/unit/test_hooks.py +0 -495
- tests/unit/test_registry.py +0 -261
- tests/unit/test_replay.py +0 -420
- tests/unit/test_schedule_schemas.py +0 -285
- tests/unit/test_schedule_utils.py +0 -286
- tests/unit/test_scheduled_workflow.py +0 -274
- tests/unit/test_step.py +0 -353
- tests/unit/test_workflow.py +0 -243
- {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.10.dist-info}/WHEEL +0 -0
- {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.10.dist-info}/entry_points.txt +0 -0
- {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.10.dist-info}/licenses/LICENSE +0 -0
docs/concepts/workflows.mdx
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: 'Workflows'
|
|
3
|
-
description: 'Top-level orchestration functions that coordinate steps and handle business logic'
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
## What is a Workflow?
|
|
7
|
-
|
|
8
|
-
A workflow is the top-level orchestration function that coordinates multiple steps, handles business logic, and can pause for extended periods using sleep or webhooks. Workflows are the entry point for your business processes.
|
|
9
|
-
|
|
10
|
-
```python
|
|
11
|
-
from pyworkflow import workflow, step, start, sleep
|
|
12
|
-
|
|
13
|
-
@workflow()
|
|
14
|
-
async def order_processing(order_id: str):
|
|
15
|
-
# Validate and process the order
|
|
16
|
-
order = await validate_order(order_id)
|
|
17
|
-
payment = await process_payment(order)
|
|
18
|
-
|
|
19
|
-
# Wait for fulfillment
|
|
20
|
-
await sleep("2h")
|
|
21
|
-
|
|
22
|
-
# Ship and notify
|
|
23
|
-
await create_shipment(order)
|
|
24
|
-
await send_confirmation(order)
|
|
25
|
-
|
|
26
|
-
return {"status": "completed", "order_id": order_id}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Key Characteristics
|
|
30
|
-
|
|
31
|
-
<CardGroup cols={2}>
|
|
32
|
-
<Card title="Durable" icon="database">
|
|
33
|
-
Workflows survive crashes, restarts, and deployments. State is preserved through event sourcing.
|
|
34
|
-
</Card>
|
|
35
|
-
<Card title="Suspendable" icon="pause">
|
|
36
|
-
Workflows can pause for minutes, hours, or days without consuming resources.
|
|
37
|
-
</Card>
|
|
38
|
-
<Card title="Distributed" icon="server">
|
|
39
|
-
Workflows execute across Celery workers, enabling horizontal scaling.
|
|
40
|
-
</Card>
|
|
41
|
-
<Card title="Deterministic" icon="rotate">
|
|
42
|
-
Workflows can be replayed from any point using the recorded event log.
|
|
43
|
-
</Card>
|
|
44
|
-
</CardGroup>
|
|
45
|
-
|
|
46
|
-
## Creating Workflows
|
|
47
|
-
|
|
48
|
-
<Tabs>
|
|
49
|
-
<Tab title="Decorator">
|
|
50
|
-
```python
|
|
51
|
-
from pyworkflow import workflow
|
|
52
|
-
|
|
53
|
-
@workflow()
|
|
54
|
-
async def my_workflow(user_id: str, amount: float):
|
|
55
|
-
# Your workflow logic here
|
|
56
|
-
result = await some_step(user_id, amount)
|
|
57
|
-
return result
|
|
58
|
-
```
|
|
59
|
-
</Tab>
|
|
60
|
-
<Tab title="Class">
|
|
61
|
-
```python
|
|
62
|
-
from pyworkflow import Workflow
|
|
63
|
-
|
|
64
|
-
class MyWorkflow(Workflow):
|
|
65
|
-
async def run(self, user_id: str, amount: float):
|
|
66
|
-
result = await SomeStep()(user_id, amount)
|
|
67
|
-
return result
|
|
68
|
-
```
|
|
69
|
-
</Tab>
|
|
70
|
-
</Tabs>
|
|
71
|
-
|
|
72
|
-
### Configuration Options
|
|
73
|
-
|
|
74
|
-
<Tabs>
|
|
75
|
-
<Tab title="Decorator">
|
|
76
|
-
```python
|
|
77
|
-
@workflow(
|
|
78
|
-
name="custom_workflow_name", # Override the function name
|
|
79
|
-
max_duration="24h", # Maximum workflow runtime
|
|
80
|
-
max_retries=3 # Retry the entire workflow on failure
|
|
81
|
-
)
|
|
82
|
-
async def my_workflow():
|
|
83
|
-
pass
|
|
84
|
-
```
|
|
85
|
-
</Tab>
|
|
86
|
-
<Tab title="Class">
|
|
87
|
-
```python
|
|
88
|
-
class MyWorkflow(Workflow):
|
|
89
|
-
name = "custom_workflow_name"
|
|
90
|
-
max_duration = "24h"
|
|
91
|
-
max_retries = 3
|
|
92
|
-
|
|
93
|
-
async def run(self):
|
|
94
|
-
pass
|
|
95
|
-
```
|
|
96
|
-
</Tab>
|
|
97
|
-
</Tabs>
|
|
98
|
-
|
|
99
|
-
| Option | Type | Default | Description |
|
|
100
|
-
|--------|------|---------|-------------|
|
|
101
|
-
| `name` | `str` | Function/class name | Unique identifier for the workflow |
|
|
102
|
-
| `max_duration` | `str` | `"7d"` | Maximum time the workflow can run |
|
|
103
|
-
| `max_retries` | `int` | `0` | Number of times to retry the entire workflow |
|
|
104
|
-
|
|
105
|
-
## Starting Workflows
|
|
106
|
-
|
|
107
|
-
### Synchronous Start
|
|
108
|
-
|
|
109
|
-
The `start()` function dispatches a workflow to Celery and returns immediately:
|
|
110
|
-
|
|
111
|
-
```python
|
|
112
|
-
from pyworkflow import start
|
|
113
|
-
|
|
114
|
-
# Start the workflow (non-blocking)
|
|
115
|
-
run_id = start(order_processing, order_id="ORD-123")
|
|
116
|
-
print(f"Workflow started with ID: {run_id}")
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### With Idempotency Key
|
|
120
|
-
|
|
121
|
-
Prevent duplicate workflow executions:
|
|
122
|
-
|
|
123
|
-
```python
|
|
124
|
-
run_id = start(
|
|
125
|
-
order_processing,
|
|
126
|
-
order_id="ORD-123",
|
|
127
|
-
idempotency_key="order-ORD-123"
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
# Calling again with same key returns the same run_id
|
|
131
|
-
run_id_2 = start(
|
|
132
|
-
order_processing,
|
|
133
|
-
order_id="ORD-123",
|
|
134
|
-
idempotency_key="order-ORD-123"
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
assert run_id == run_id_2 # True - same workflow
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Workflow Lifecycle
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
┌─────────────┐
|
|
144
|
-
│ PENDING │ Workflow created, waiting to start
|
|
145
|
-
└──────┬──────┘
|
|
146
|
-
│
|
|
147
|
-
▼
|
|
148
|
-
┌─────────────┐
|
|
149
|
-
│ RUNNING │ Workflow is executing
|
|
150
|
-
└──────┬──────┘
|
|
151
|
-
│
|
|
152
|
-
├────────────────┬────────────────┐
|
|
153
|
-
│ │ │
|
|
154
|
-
▼ ▼ ▼
|
|
155
|
-
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
156
|
-
│ SUSPENDED │ │ INTERRUPTED │ │ FAILED │
|
|
157
|
-
│ │ │(worker crash)│ │ │
|
|
158
|
-
└──────┬──────┘ └──────┬──────┘ └─────────────┘
|
|
159
|
-
│ │
|
|
160
|
-
│ (sleep ends) │ (auto recovery)
|
|
161
|
-
▼ ▼
|
|
162
|
-
┌─────────────┐ ┌─────────────┐
|
|
163
|
-
│ RUNNING │ │ RUNNING │ Recovered
|
|
164
|
-
└──────┬──────┘ └──────┬──────┘
|
|
165
|
-
│ │
|
|
166
|
-
└────────┬───────┘
|
|
167
|
-
│
|
|
168
|
-
▼
|
|
169
|
-
┌─────────────┐
|
|
170
|
-
│ COMPLETED │ Workflow finished successfully
|
|
171
|
-
└─────────────┘
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
<Note>
|
|
175
|
-
When a worker crashes, the workflow enters `INTERRUPTED` status and automatically recovers on another worker. See [Fault Tolerance](/concepts/fault-tolerance) for details.
|
|
176
|
-
</Note>
|
|
177
|
-
|
|
178
|
-
## Workflow Context
|
|
179
|
-
|
|
180
|
-
Inside a workflow, you can access the execution context:
|
|
181
|
-
|
|
182
|
-
```python
|
|
183
|
-
from pyworkflow import workflow, get_context
|
|
184
|
-
|
|
185
|
-
@workflow()
|
|
186
|
-
async def my_workflow():
|
|
187
|
-
ctx = get_context()
|
|
188
|
-
|
|
189
|
-
print(f"Run ID: {ctx.run_id}")
|
|
190
|
-
print(f"Workflow: {ctx.workflow_name}")
|
|
191
|
-
|
|
192
|
-
# Access step results from replay
|
|
193
|
-
previous_result = ctx.step_results.get("step_id")
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
## Error Handling
|
|
197
|
-
|
|
198
|
-
Workflows automatically handle errors based on their type:
|
|
199
|
-
|
|
200
|
-
```python
|
|
201
|
-
from pyworkflow import workflow, FatalError, RetryableError
|
|
202
|
-
|
|
203
|
-
@workflow(max_retries=3)
|
|
204
|
-
async def my_workflow():
|
|
205
|
-
try:
|
|
206
|
-
result = await risky_operation()
|
|
207
|
-
return result
|
|
208
|
-
except ValidationError as e:
|
|
209
|
-
# Fatal errors stop the workflow immediately
|
|
210
|
-
raise FatalError(f"Invalid input: {e}")
|
|
211
|
-
except TemporaryError as e:
|
|
212
|
-
# Retryable errors trigger workflow retry
|
|
213
|
-
raise RetryableError(f"Temporary failure: {e}")
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## Best Practices
|
|
217
|
-
|
|
218
|
-
<AccordionGroup>
|
|
219
|
-
<Accordion title="Keep workflows focused">
|
|
220
|
-
Each workflow should handle a single business process. If a workflow is getting complex, consider breaking it into smaller workflows that call each other.
|
|
221
|
-
</Accordion>
|
|
222
|
-
|
|
223
|
-
<Accordion title="Use meaningful names">
|
|
224
|
-
Workflow names should clearly describe their purpose: `process_order`, `onboard_user`, `send_notification_sequence`.
|
|
225
|
-
</Accordion>
|
|
226
|
-
|
|
227
|
-
<Accordion title="Handle idempotency">
|
|
228
|
-
Use idempotency keys for workflows that shouldn't run twice for the same input. This prevents duplicate processing during retries.
|
|
229
|
-
</Accordion>
|
|
230
|
-
|
|
231
|
-
<Accordion title="Set appropriate timeouts">
|
|
232
|
-
Use `max_duration` to prevent workflows from running indefinitely. Consider the longest possible execution path.
|
|
233
|
-
</Accordion>
|
|
234
|
-
|
|
235
|
-
<Accordion title="Configure fault tolerance">
|
|
236
|
-
Enable `recover_on_worker_loss` for critical workflows to ensure automatic recovery from worker crashes. See [Fault Tolerance](/concepts/fault-tolerance) for configuration options.
|
|
237
|
-
</Accordion>
|
|
238
|
-
</AccordionGroup>
|
|
239
|
-
|
|
240
|
-
## Next Steps
|
|
241
|
-
|
|
242
|
-
<CardGroup cols={2}>
|
|
243
|
-
<Card title="Steps" icon="stairs" href="/concepts/steps">
|
|
244
|
-
Learn about steps - the building blocks of workflows.
|
|
245
|
-
</Card>
|
|
246
|
-
<Card title="Schedules" icon="calendar" href="/concepts/schedules">
|
|
247
|
-
Automatically run workflows on cron, interval, or calendar schedules.
|
|
248
|
-
</Card>
|
|
249
|
-
<Card title="Sleep" icon="clock" href="/concepts/sleep">
|
|
250
|
-
Pause workflows for any duration without consuming resources.
|
|
251
|
-
</Card>
|
|
252
|
-
<Card title="Fault Tolerance" icon="shield-check" href="/concepts/fault-tolerance">
|
|
253
|
-
Configure auto recovery from worker crashes.
|
|
254
|
-
</Card>
|
|
255
|
-
</CardGroup>
|