pyworkflow-engine 0.1.7__py3-none-any.whl → 0.1.9__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.
Files changed (145) hide show
  1. pyworkflow/__init__.py +10 -1
  2. pyworkflow/celery/tasks.py +272 -24
  3. pyworkflow/cli/__init__.py +4 -1
  4. pyworkflow/cli/commands/runs.py +4 -4
  5. pyworkflow/cli/commands/setup.py +203 -4
  6. pyworkflow/cli/utils/config_generator.py +76 -3
  7. pyworkflow/cli/utils/docker_manager.py +232 -0
  8. pyworkflow/context/__init__.py +13 -0
  9. pyworkflow/context/base.py +26 -0
  10. pyworkflow/context/local.py +80 -0
  11. pyworkflow/context/step_context.py +295 -0
  12. pyworkflow/core/registry.py +6 -1
  13. pyworkflow/core/step.py +141 -0
  14. pyworkflow/core/workflow.py +56 -0
  15. pyworkflow/engine/events.py +30 -0
  16. pyworkflow/engine/replay.py +39 -0
  17. pyworkflow/primitives/child_workflow.py +1 -1
  18. pyworkflow/runtime/local.py +1 -1
  19. pyworkflow/storage/__init__.py +14 -0
  20. pyworkflow/storage/base.py +35 -0
  21. pyworkflow/storage/cassandra.py +1747 -0
  22. pyworkflow/storage/config.py +69 -0
  23. pyworkflow/storage/dynamodb.py +31 -2
  24. pyworkflow/storage/file.py +28 -0
  25. pyworkflow/storage/memory.py +18 -0
  26. pyworkflow/storage/mysql.py +1159 -0
  27. pyworkflow/storage/postgres.py +27 -2
  28. pyworkflow/storage/schemas.py +4 -3
  29. pyworkflow/storage/sqlite.py +25 -2
  30. {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.9.dist-info}/METADATA +7 -4
  31. pyworkflow_engine-0.1.9.dist-info/RECORD +91 -0
  32. pyworkflow_engine-0.1.9.dist-info/top_level.txt +1 -0
  33. dashboard/backend/app/__init__.py +0 -1
  34. dashboard/backend/app/config.py +0 -32
  35. dashboard/backend/app/controllers/__init__.py +0 -6
  36. dashboard/backend/app/controllers/run_controller.py +0 -86
  37. dashboard/backend/app/controllers/workflow_controller.py +0 -33
  38. dashboard/backend/app/dependencies/__init__.py +0 -5
  39. dashboard/backend/app/dependencies/storage.py +0 -50
  40. dashboard/backend/app/repositories/__init__.py +0 -6
  41. dashboard/backend/app/repositories/run_repository.py +0 -80
  42. dashboard/backend/app/repositories/workflow_repository.py +0 -27
  43. dashboard/backend/app/rest/__init__.py +0 -8
  44. dashboard/backend/app/rest/v1/__init__.py +0 -12
  45. dashboard/backend/app/rest/v1/health.py +0 -33
  46. dashboard/backend/app/rest/v1/runs.py +0 -133
  47. dashboard/backend/app/rest/v1/workflows.py +0 -41
  48. dashboard/backend/app/schemas/__init__.py +0 -23
  49. dashboard/backend/app/schemas/common.py +0 -16
  50. dashboard/backend/app/schemas/event.py +0 -24
  51. dashboard/backend/app/schemas/hook.py +0 -25
  52. dashboard/backend/app/schemas/run.py +0 -54
  53. dashboard/backend/app/schemas/step.py +0 -28
  54. dashboard/backend/app/schemas/workflow.py +0 -31
  55. dashboard/backend/app/server.py +0 -87
  56. dashboard/backend/app/services/__init__.py +0 -6
  57. dashboard/backend/app/services/run_service.py +0 -240
  58. dashboard/backend/app/services/workflow_service.py +0 -155
  59. dashboard/backend/main.py +0 -18
  60. docs/concepts/cancellation.mdx +0 -362
  61. docs/concepts/continue-as-new.mdx +0 -434
  62. docs/concepts/events.mdx +0 -266
  63. docs/concepts/fault-tolerance.mdx +0 -370
  64. docs/concepts/hooks.mdx +0 -552
  65. docs/concepts/limitations.mdx +0 -167
  66. docs/concepts/schedules.mdx +0 -775
  67. docs/concepts/sleep.mdx +0 -312
  68. docs/concepts/steps.mdx +0 -301
  69. docs/concepts/workflows.mdx +0 -255
  70. docs/guides/cli.mdx +0 -942
  71. docs/guides/configuration.mdx +0 -560
  72. docs/introduction.mdx +0 -155
  73. docs/quickstart.mdx +0 -279
  74. examples/__init__.py +0 -1
  75. examples/celery/__init__.py +0 -1
  76. examples/celery/durable/docker-compose.yml +0 -55
  77. examples/celery/durable/pyworkflow.config.yaml +0 -12
  78. examples/celery/durable/workflows/__init__.py +0 -122
  79. examples/celery/durable/workflows/basic.py +0 -87
  80. examples/celery/durable/workflows/batch_processing.py +0 -102
  81. examples/celery/durable/workflows/cancellation.py +0 -273
  82. examples/celery/durable/workflows/child_workflow_patterns.py +0 -240
  83. examples/celery/durable/workflows/child_workflows.py +0 -202
  84. examples/celery/durable/workflows/continue_as_new.py +0 -260
  85. examples/celery/durable/workflows/fault_tolerance.py +0 -210
  86. examples/celery/durable/workflows/hooks.py +0 -211
  87. examples/celery/durable/workflows/idempotency.py +0 -112
  88. examples/celery/durable/workflows/long_running.py +0 -99
  89. examples/celery/durable/workflows/retries.py +0 -101
  90. examples/celery/durable/workflows/schedules.py +0 -209
  91. examples/celery/transient/01_basic_workflow.py +0 -91
  92. examples/celery/transient/02_fault_tolerance.py +0 -257
  93. examples/celery/transient/__init__.py +0 -20
  94. examples/celery/transient/pyworkflow.config.yaml +0 -25
  95. examples/local/__init__.py +0 -1
  96. examples/local/durable/01_basic_workflow.py +0 -94
  97. examples/local/durable/02_file_storage.py +0 -132
  98. examples/local/durable/03_retries.py +0 -169
  99. examples/local/durable/04_long_running.py +0 -119
  100. examples/local/durable/05_event_log.py +0 -145
  101. examples/local/durable/06_idempotency.py +0 -148
  102. examples/local/durable/07_hooks.py +0 -334
  103. examples/local/durable/08_cancellation.py +0 -233
  104. examples/local/durable/09_child_workflows.py +0 -198
  105. examples/local/durable/10_child_workflow_patterns.py +0 -265
  106. examples/local/durable/11_continue_as_new.py +0 -249
  107. examples/local/durable/12_schedules.py +0 -198
  108. examples/local/durable/__init__.py +0 -1
  109. examples/local/transient/01_quick_tasks.py +0 -87
  110. examples/local/transient/02_retries.py +0 -130
  111. examples/local/transient/03_sleep.py +0 -141
  112. examples/local/transient/__init__.py +0 -1
  113. pyworkflow_engine-0.1.7.dist-info/RECORD +0 -196
  114. pyworkflow_engine-0.1.7.dist-info/top_level.txt +0 -5
  115. tests/examples/__init__.py +0 -0
  116. tests/integration/__init__.py +0 -0
  117. tests/integration/test_cancellation.py +0 -330
  118. tests/integration/test_child_workflows.py +0 -439
  119. tests/integration/test_continue_as_new.py +0 -428
  120. tests/integration/test_dynamodb_storage.py +0 -1146
  121. tests/integration/test_fault_tolerance.py +0 -369
  122. tests/integration/test_schedule_storage.py +0 -484
  123. tests/unit/__init__.py +0 -0
  124. tests/unit/backends/__init__.py +0 -1
  125. tests/unit/backends/test_dynamodb_storage.py +0 -1554
  126. tests/unit/backends/test_postgres_storage.py +0 -1281
  127. tests/unit/backends/test_sqlite_storage.py +0 -1460
  128. tests/unit/conftest.py +0 -41
  129. tests/unit/test_cancellation.py +0 -364
  130. tests/unit/test_child_workflows.py +0 -680
  131. tests/unit/test_continue_as_new.py +0 -441
  132. tests/unit/test_event_limits.py +0 -316
  133. tests/unit/test_executor.py +0 -320
  134. tests/unit/test_fault_tolerance.py +0 -334
  135. tests/unit/test_hooks.py +0 -495
  136. tests/unit/test_registry.py +0 -261
  137. tests/unit/test_replay.py +0 -420
  138. tests/unit/test_schedule_schemas.py +0 -285
  139. tests/unit/test_schedule_utils.py +0 -286
  140. tests/unit/test_scheduled_workflow.py +0 -274
  141. tests/unit/test_step.py +0 -353
  142. tests/unit/test_workflow.py +0 -243
  143. {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.9.dist-info}/WHEEL +0 -0
  144. {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.9.dist-info}/entry_points.txt +0 -0
  145. {pyworkflow_engine-0.1.7.dist-info → pyworkflow_engine-0.1.9.dist-info}/licenses/LICENSE +0 -0
@@ -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>