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
@@ -93,6 +93,9 @@ class EventReplayer:
93
93
  elif event.type == EventType.CANCELLATION_REQUESTED:
94
94
  await self._apply_cancellation_requested(ctx, event)
95
95
 
96
+ elif event.type == EventType.CONTEXT_UPDATED:
97
+ await self._apply_context_updated(ctx, event)
98
+
96
99
  # Other event types don't affect replay state
97
100
  # (workflow_started, step_started, step_failed, etc. are informational)
98
101
 
@@ -255,6 +258,42 @@ class EventReplayer:
255
258
  requested_by=requested_by,
256
259
  )
257
260
 
261
+ async def _apply_context_updated(self, ctx: LocalContext, event: Event) -> None:
262
+ """
263
+ Apply context_updated event - restore step context.
264
+
265
+ During replay, this restores the step context to its state at the time
266
+ the event was recorded. This ensures deterministic replay.
267
+ """
268
+ from pyworkflow.context.step_context import (
269
+ _set_step_context_internal,
270
+ get_step_context_class,
271
+ )
272
+
273
+ context_data = event.data.get("context", {})
274
+
275
+ if context_data:
276
+ # Get the registered context class
277
+ context_class = get_step_context_class()
278
+ if context_class is not None:
279
+ try:
280
+ step_ctx = context_class.from_dict(context_data)
281
+ _set_step_context_internal(step_ctx)
282
+ logger.debug(
283
+ "Restored step context from replay",
284
+ run_id=ctx.run_id,
285
+ )
286
+ except Exception as e:
287
+ logger.warning(
288
+ f"Failed to restore step context: {e}",
289
+ run_id=ctx.run_id,
290
+ )
291
+ else:
292
+ logger.debug(
293
+ "No context class registered, skipping context restoration",
294
+ run_id=ctx.run_id,
295
+ )
296
+
258
297
 
259
298
  # Singleton instance
260
299
  _replayer = EventReplayer()
@@ -346,7 +346,7 @@ async def _start_child_on_worker(
346
346
  parent_run_id=ctx.run_id,
347
347
  nesting_depth=child_depth,
348
348
  max_duration=workflow_meta.max_duration,
349
- metadata={}, # Run-level metadata
349
+ context={}, # Step context
350
350
  )
351
351
  await storage.create_run(child_run)
352
352
 
@@ -167,7 +167,7 @@ class LocalRuntime(Runtime):
167
167
  input_kwargs=serialize_kwargs(**kwargs),
168
168
  idempotency_key=idempotency_key,
169
169
  max_duration=max_duration,
170
- metadata=metadata or {},
170
+ context=metadata or {},
171
171
  )
172
172
  await storage.create_run(workflow_run)
173
173
 
@@ -35,6 +35,18 @@ try:
35
35
  except ImportError:
36
36
  DynamoDBStorageBackend = None # type: ignore
37
37
 
38
+ # Cassandra backend - optional import (requires cassandra-driver)
39
+ try:
40
+ from pyworkflow.storage.cassandra import CassandraStorageBackend
41
+ except ImportError:
42
+ CassandraStorageBackend = None # type: ignore
43
+
44
+ # MySQL backend - optional import (requires aiomysql)
45
+ try:
46
+ from pyworkflow.storage.mysql import MySQLStorageBackend
47
+ except ImportError:
48
+ MySQLStorageBackend = None # type: ignore
49
+
38
50
  __all__ = [
39
51
  "StorageBackend",
40
52
  "FileStorageBackend",
@@ -42,6 +54,8 @@ __all__ = [
42
54
  "SQLiteStorageBackend",
43
55
  "PostgresStorageBackend",
44
56
  "DynamoDBStorageBackend",
57
+ "CassandraStorageBackend",
58
+ "MySQLStorageBackend",
45
59
  "WorkflowRun",
46
60
  "StepExecution",
47
61
  "Hook",
@@ -109,6 +109,41 @@ class StorageBackend(ABC):
109
109
  """
110
110
  pass
111
111
 
112
+ @abstractmethod
113
+ async def update_run_context(
114
+ self,
115
+ run_id: str,
116
+ context: dict,
117
+ ) -> None:
118
+ """
119
+ Update the step context for a workflow run.
120
+
121
+ Called when set_step_context() is invoked in workflow code.
122
+ The context is stored and can be loaded by steps running on
123
+ remote workers.
124
+
125
+ Args:
126
+ run_id: Workflow run identifier
127
+ context: Context data as a dictionary (serialized StepContext)
128
+ """
129
+ pass
130
+
131
+ @abstractmethod
132
+ async def get_run_context(self, run_id: str) -> dict:
133
+ """
134
+ Get the current step context for a workflow run.
135
+
136
+ Called when a step starts execution on a remote worker to
137
+ load the context that was set by the workflow.
138
+
139
+ Args:
140
+ run_id: Workflow run identifier
141
+
142
+ Returns:
143
+ Context data as a dictionary, or empty dict if not set
144
+ """
145
+ pass
146
+
112
147
  @abstractmethod
113
148
  async def list_runs(
114
149
  self,