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