pyworkflow-engine 0.2.2__tar.gz → 0.2.3__tar.gz

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 (229) hide show
  1. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/PKG-INFO +1 -1
  2. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyproject.toml +1 -1
  3. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/__init__.py +1 -1
  4. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/celery/app.py +7 -23
  5. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/celery/tasks.py +22 -80
  6. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/core/step.py +3 -2
  7. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/CLAUDE.md +0 -0
  8. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/DISTRIBUTED.md +0 -0
  9. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/LICENSE +0 -0
  10. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/MANIFEST.in +0 -0
  11. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/README.md +0 -0
  12. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/RELEASING.md +0 -0
  13. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/architecture.md +0 -0
  14. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/cancellation.mdx +0 -0
  15. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/continue-as-new.mdx +0 -0
  16. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/events.mdx +0 -0
  17. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/fault-tolerance.mdx +0 -0
  18. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/hooks.mdx +0 -0
  19. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/limitations.mdx +0 -0
  20. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/schedules.mdx +0 -0
  21. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/sleep.mdx +0 -0
  22. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/step-context.mdx +0 -0
  23. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/steps.mdx +0 -0
  24. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/concepts/workflows.mdx +0 -0
  25. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/conventions.md +0 -0
  26. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/guides/brokers.mdx +0 -0
  27. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/guides/cli.mdx +0 -0
  28. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/guides/configuration.mdx +0 -0
  29. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/harness-gaps.md +0 -0
  30. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/introduction.mdx +0 -0
  31. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/layers.md +0 -0
  32. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/docs/quickstart.mdx +0 -0
  33. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/__init__.py +0 -0
  34. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/__init__.py +0 -0
  35. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/docker-compose.yml +0 -0
  36. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/pyworkflow.config.yaml +0 -0
  37. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/__init__.py +0 -0
  38. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/basic.py +0 -0
  39. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/batch_processing.py +0 -0
  40. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/cancellation.py +0 -0
  41. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/child_workflow_from_step.py +0 -0
  42. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/child_workflow_patterns.py +0 -0
  43. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/child_workflows.py +0 -0
  44. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/continue_as_new.py +0 -0
  45. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/fault_tolerance.py +0 -0
  46. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/hooks.py +0 -0
  47. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/idempotency.py +0 -0
  48. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/long_running.py +0 -0
  49. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/retries.py +0 -0
  50. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/schedules.py +0 -0
  51. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/sleep_in_step.py +0 -0
  52. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/durable/workflows/step_context.py +0 -0
  53. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/transient/01_basic_workflow.py +0 -0
  54. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/transient/02_fault_tolerance.py +0 -0
  55. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/transient/__init__.py +0 -0
  56. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/celery/transient/pyworkflow.config.yaml +0 -0
  57. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/__init__.py +0 -0
  58. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/01_basic_workflow.py +0 -0
  59. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/02_file_storage.py +0 -0
  60. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/03_retries.py +0 -0
  61. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/04_long_running.py +0 -0
  62. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/05_event_log.py +0 -0
  63. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/06_idempotency.py +0 -0
  64. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/07_hooks.py +0 -0
  65. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/08_cancellation.py +0 -0
  66. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/09_child_workflows.py +0 -0
  67. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/10_child_workflow_patterns.py +0 -0
  68. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/11_continue_as_new.py +0 -0
  69. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/12_schedules.py +0 -0
  70. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/13_step_context.py +0 -0
  71. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/14_child_workflow_from_step.py +0 -0
  72. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/durable/__init__.py +0 -0
  73. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/transient/01_quick_tasks.py +0 -0
  74. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/transient/02_retries.py +0 -0
  75. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/transient/03_sleep.py +0 -0
  76. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/examples/local/transient/__init__.py +0 -0
  77. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/aws/__init__.py +0 -0
  78. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/aws/context.py +0 -0
  79. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/aws/handler.py +0 -0
  80. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/aws/testing.py +0 -0
  81. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/celery/__init__.py +0 -0
  82. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/celery/loop.py +0 -0
  83. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/celery/scheduler.py +0 -0
  84. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/celery/singleton.py +0 -0
  85. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/__init__.py +0 -0
  86. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/__main__.py +0 -0
  87. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/__init__.py +0 -0
  88. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/hooks.py +0 -0
  89. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/quickstart.py +0 -0
  90. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/runs.py +0 -0
  91. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/scheduler.py +0 -0
  92. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/schedules.py +0 -0
  93. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/setup.py +0 -0
  94. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/worker.py +0 -0
  95. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/commands/workflows.py +0 -0
  96. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/output/__init__.py +0 -0
  97. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/output/formatters.py +0 -0
  98. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/output/styles.py +0 -0
  99. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/__init__.py +0 -0
  100. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/async_helpers.py +0 -0
  101. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/config.py +0 -0
  102. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/config_generator.py +0 -0
  103. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/discovery.py +0 -0
  104. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/docker_manager.py +0 -0
  105. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/interactive.py +0 -0
  106. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/cli/utils/storage.py +0 -0
  107. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/config.py +0 -0
  108. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/context/__init__.py +0 -0
  109. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/context/aws.py +0 -0
  110. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/context/base.py +0 -0
  111. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/context/local.py +0 -0
  112. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/context/mock.py +0 -0
  113. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/context/step_context.py +0 -0
  114. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/core/__init__.py +0 -0
  115. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/core/exceptions.py +0 -0
  116. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/core/registry.py +0 -0
  117. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/core/scheduled.py +0 -0
  118. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/core/validation.py +0 -0
  119. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/core/workflow.py +0 -0
  120. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/discovery.py +0 -0
  121. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/engine/__init__.py +0 -0
  122. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/engine/events.py +0 -0
  123. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/engine/executor.py +0 -0
  124. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/engine/replay.py +0 -0
  125. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/observability/__init__.py +0 -0
  126. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/observability/logging.py +0 -0
  127. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/__init__.py +0 -0
  128. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/child_handle.py +0 -0
  129. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/child_workflow.py +0 -0
  130. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/continue_as_new.py +0 -0
  131. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/define_hook.py +0 -0
  132. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/hooks.py +0 -0
  133. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/resume_hook.py +0 -0
  134. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/schedule.py +0 -0
  135. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/shield.py +0 -0
  136. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/sleep.py +0 -0
  137. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/step_checkpoint.py +0 -0
  138. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/primitives/step_hook.py +0 -0
  139. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/runtime/__init__.py +0 -0
  140. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/runtime/base.py +0 -0
  141. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/runtime/celery.py +0 -0
  142. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/runtime/factory.py +0 -0
  143. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/runtime/local.py +0 -0
  144. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/scheduler/__init__.py +0 -0
  145. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/scheduler/local.py +0 -0
  146. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/serialization/__init__.py +0 -0
  147. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/serialization/decoder.py +0 -0
  148. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/serialization/encoder.py +0 -0
  149. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/__init__.py +0 -0
  150. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/base.py +0 -0
  151. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/cassandra.py +0 -0
  152. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/citus.py +0 -0
  153. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/config.py +0 -0
  154. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/dynamodb.py +0 -0
  155. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/file.py +0 -0
  156. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/memory.py +0 -0
  157. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/migrations/__init__.py +0 -0
  158. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/migrations/base.py +0 -0
  159. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/mysql.py +0 -0
  160. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/postgres.py +0 -0
  161. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/schemas.py +0 -0
  162. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/storage/sqlite.py +0 -0
  163. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/__init__.py +0 -0
  164. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/checkpoint.py +0 -0
  165. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/consumer.py +0 -0
  166. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/context.py +0 -0
  167. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/decorator.py +0 -0
  168. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/dispatcher.py +0 -0
  169. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/emit.py +0 -0
  170. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/registry.py +0 -0
  171. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/signal.py +0 -0
  172. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/streams/step_context.py +0 -0
  173. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/utils/__init__.py +0 -0
  174. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/utils/duration.py +0 -0
  175. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/utils/helpers.py +0 -0
  176. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow/utils/schedule.py +0 -0
  177. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/pyworkflow_engine.egg-info/SOURCES.txt +0 -0
  178. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/setup.cfg +0 -0
  179. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/__init__.py +0 -0
  180. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_cancellation.py +0 -0
  181. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_cassandra_storage.py +0 -0
  182. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_child_workflows.py +0 -0
  183. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_continue_as_new.py +0 -0
  184. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_dynamodb_storage.py +0 -0
  185. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_fault_tolerance.py +0 -0
  186. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_schedule_storage.py +0 -0
  187. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_schema_migrations.py +0 -0
  188. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_singleton.py +0 -0
  189. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_stream_e2e.py +0 -0
  190. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/integration/test_workflow_suspended.py +0 -0
  191. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/__init__.py +0 -0
  192. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/backends/__init__.py +0 -0
  193. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/backends/test_cassandra_storage.py +0 -0
  194. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/backends/test_citus_storage.py +0 -0
  195. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/backends/test_dynamodb_storage.py +0 -0
  196. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/backends/test_postgres_storage.py +0 -0
  197. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/backends/test_sqlite_storage.py +0 -0
  198. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/conftest.py +0 -0
  199. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/storage/__init__.py +0 -0
  200. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/storage/test_migrations.py +0 -0
  201. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_cancellation.py +0 -0
  202. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_child_workflows.py +0 -0
  203. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_cli_worker.py +0 -0
  204. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_continue_as_new.py +0 -0
  205. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_emit.py +0 -0
  206. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_event_limits.py +0 -0
  207. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_executor.py +0 -0
  208. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_fault_tolerance.py +0 -0
  209. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_force_local.py +0 -0
  210. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_hooks.py +0 -0
  211. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_parent_run_id.py +0 -0
  212. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_primitives_from_steps.py +0 -0
  213. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_registry.py +0 -0
  214. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_replay.py +0 -0
  215. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_retention.py +0 -0
  216. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_schedule_schemas.py +0 -0
  217. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_schedule_utils.py +0 -0
  218. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_scheduled_workflow.py +0 -0
  219. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_signal.py +0 -0
  220. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_singleton.py +0 -0
  221. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_step.py +0 -0
  222. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_step_checkpoint.py +0 -0
  223. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_step_context.py +0 -0
  224. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_step_hook.py +0 -0
  225. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_stream_storage.py +0 -0
  226. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_stream_workflow.py +0 -0
  227. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_validation.py +0 -0
  228. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_workflow.py +0 -0
  229. {pyworkflow_engine-0.2.2 → pyworkflow_engine-0.2.3}/tests/unit/test_workflow_suspended.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyworkflow-engine
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: A Python implementation of durable, event-sourced workflows inspired by Vercel Workflow
5
5
  Author: PyWorkflow Contributors
6
6
  License: MIT
@@ -7,7 +7,7 @@ packages = [{include = "pyworkflow"}]
7
7
 
8
8
  [project]
9
9
  name = "pyworkflow-engine"
10
- version = "0.2.2"
10
+ version = "0.2.3"
11
11
  description = "A Python implementation of durable, event-sourced workflows inspired by Vercel Workflow"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.11"
@@ -29,7 +29,7 @@ Quick Start:
29
29
  >>> run_id = await start(my_workflow, "Alice")
30
30
  """
31
31
 
32
- __version__ = "0.2.2"
32
+ __version__ = "0.2.3"
33
33
 
34
34
  # Configuration
35
35
  from pyworkflow.config import (
@@ -304,33 +304,17 @@ def create_celery_app(
304
304
  # Broker transport options - prevent task redelivery
305
305
  # See: https://github.com/celery/celery/issues/5935
306
306
  "broker_transport_options": final_broker_opts,
307
- # Task routing
307
+ # Task routing — use direct exchange (each task specifies queue= explicitly)
308
308
  "task_default_queue": "pyworkflow.default",
309
309
  "task_default_exchange": "pyworkflow",
310
- "task_default_exchange_type": "topic",
311
- "task_default_routing_key": "workflow.default",
310
+ "task_default_exchange_type": "direct",
311
+ "task_default_routing_key": "pyworkflow.default",
312
312
  # Task queues
313
313
  "task_queues": (
314
- Queue(
315
- "pyworkflow.default",
316
- Exchange("pyworkflow", type="topic"),
317
- routing_key="workflow.#",
318
- ),
319
- Queue(
320
- "pyworkflow.steps",
321
- Exchange("pyworkflow", type="topic"),
322
- routing_key="workflow.step.#",
323
- ),
324
- Queue(
325
- "pyworkflow.workflows",
326
- Exchange("pyworkflow", type="topic"),
327
- routing_key="workflow.workflow.#",
328
- ),
329
- Queue(
330
- "pyworkflow.schedules",
331
- Exchange("pyworkflow", type="topic"),
332
- routing_key="workflow.schedule.#",
333
- ),
314
+ Queue("pyworkflow.default", Exchange("pyworkflow", type="direct")),
315
+ Queue("pyworkflow.steps", Exchange("pyworkflow", type="direct")),
316
+ Queue("pyworkflow.workflows", Exchange("pyworkflow", type="direct")),
317
+ Queue("pyworkflow.schedules", Exchange("pyworkflow", type="direct")),
334
318
  ),
335
319
  # Task execution
336
320
  "task_acks_late": True,
@@ -10,7 +10,6 @@ These tasks enable:
10
10
  """
11
11
 
12
12
  import asyncio
13
- import contextlib
14
13
  import random
15
14
  import uuid
16
15
  from collections.abc import Callable
@@ -186,29 +185,6 @@ def execute_step_task(
186
185
  )
187
186
  return None
188
187
 
189
- # Execution-time guard: prevent duplicate step execution on concurrent workers.
190
- # The singleton lock (unique_on=["run_id", "step_id"]) prevents duplicate queueing,
191
- # but broker-level re-delivery or race conditions can still result in two workers
192
- # executing the same step. This Redis lock ensures only one proceeds.
193
- _exec_lock_key = f"pyworkflow:step_exec:{run_id}:{step_id}"
194
- _exec_lock_backend = self.singleton_backend
195
- _exec_lock_acquired = False
196
- if _exec_lock_backend is not None:
197
- _exec_lock_acquired = _exec_lock_backend.lock(
198
- _exec_lock_key, self.request.id or "unknown", expiry=self._lock_expiry
199
- )
200
- if not _exec_lock_acquired:
201
- logger.warning(
202
- "Step already being executed by another worker, skipping duplicate",
203
- run_id=run_id,
204
- step_id=step_id,
205
- step_name=step_name,
206
- existing_worker_task=_exec_lock_backend.get(_exec_lock_key),
207
- )
208
- return None
209
- else:
210
- _exec_lock_acquired = True # No Redis = no locking
211
-
212
188
  # Deserialize arguments
213
189
  args = deserialize_args(args_json)
214
190
  kwargs = deserialize_kwargs(kwargs_json)
@@ -475,11 +451,6 @@ def execute_step_task(
475
451
  raise FatalError(f"Step '{step_name}' failed after retries: {str(e)}") from e
476
452
 
477
453
  finally:
478
- # Release execution lock so retries or other tasks can proceed.
479
- if _exec_lock_acquired and _exec_lock_backend is not None:
480
- with contextlib.suppress(Exception):
481
- _exec_lock_backend.unlock(_exec_lock_key)
482
-
483
454
  # Clean up step execution context (checkpoint/hook primitives)
484
455
  if step_exec_tokens is not None:
485
456
  from pyworkflow.primitives.step_checkpoint import reset_step_execution_context
@@ -864,62 +835,33 @@ def start_workflow_task(
864
835
  celery_task_id=self.request.id,
865
836
  )
866
837
 
867
- # Execution-time guard: prevent duplicate workflow start on concurrent workers.
868
- # The singleton lock (unique_on=["run_id"]) prevents duplicate queueing, but
869
- # broker-level re-delivery or race conditions can still result in two workers
870
- # executing the same start task. This Redis lock ensures only one proceeds.
871
- _exec_lock_key = f"pyworkflow:wf_start:{run_id}"
872
- _exec_lock_backend = self.singleton_backend
873
- _exec_lock_acquired = False
874
- if _exec_lock_backend is not None:
875
- _exec_lock_acquired = _exec_lock_backend.lock(
876
- _exec_lock_key, self.request.id or "unknown", expiry=self._lock_expiry
877
- )
878
- if not _exec_lock_acquired:
879
- logger.warning(
880
- "Workflow start already being executed by another worker, skipping duplicate",
881
- run_id=run_id,
882
- workflow_name=workflow_name,
883
- existing_worker_task=_exec_lock_backend.get(_exec_lock_key),
884
- )
885
- return run_id
886
- else:
887
- _exec_lock_acquired = True # No Redis = no locking
888
-
889
- try:
890
- # Get workflow metadata
891
- workflow_meta = get_workflow(workflow_name)
892
- if not workflow_meta:
893
- raise ValueError(f"Workflow '{workflow_name}' not found in registry")
838
+ # Get workflow metadata
839
+ workflow_meta = get_workflow(workflow_name)
840
+ if not workflow_meta:
841
+ raise ValueError(f"Workflow '{workflow_name}' not found in registry")
894
842
 
895
- # Deserialize arguments
896
- args = deserialize_args(args_json)
897
- kwargs = deserialize_kwargs(kwargs_json)
843
+ # Deserialize arguments
844
+ args = deserialize_args(args_json)
845
+ kwargs = deserialize_kwargs(kwargs_json)
898
846
 
899
- # Get storage backend
900
- storage = _get_storage_backend(storage_config)
847
+ # Get storage backend
848
+ storage = _get_storage_backend(storage_config)
901
849
 
902
- # Execute workflow directly on worker
903
- result_run_id = run_async(
904
- _start_workflow_on_worker(
905
- workflow_meta=workflow_meta,
906
- args=args,
907
- kwargs=kwargs,
908
- storage=storage,
909
- storage_config=storage_config,
910
- idempotency_key=idempotency_key,
911
- run_id=run_id,
912
- )
850
+ # Execute workflow directly on worker
851
+ result_run_id = run_async(
852
+ _start_workflow_on_worker(
853
+ workflow_meta=workflow_meta,
854
+ args=args,
855
+ kwargs=kwargs,
856
+ storage=storage,
857
+ storage_config=storage_config,
858
+ idempotency_key=idempotency_key,
859
+ run_id=run_id,
913
860
  )
861
+ )
914
862
 
915
- logger.info(f"Workflow execution initiated: {workflow_name}", run_id=result_run_id)
916
- return result_run_id
917
-
918
- finally:
919
- # Release execution lock so retries or re-dispatches can proceed.
920
- if _exec_lock_acquired and _exec_lock_backend is not None:
921
- with contextlib.suppress(Exception):
922
- _exec_lock_backend.unlock(_exec_lock_key)
863
+ logger.info(f"Workflow execution initiated: {workflow_name}", run_id=result_run_id)
864
+ return result_run_id
923
865
 
924
866
 
925
867
  @celery_app.task(
@@ -669,7 +669,8 @@ async def _dispatch_step_to_celery(
669
669
 
670
670
  # Defense-in-depth: check if STEP_STARTED was already recorded for this step.
671
671
  # This guards against duplicate dispatch when two resume tasks race and both
672
- # replay past the same step. If already started, re-suspend to wait.
672
+ # replay past the same step. If already started, re-suspend to wait for
673
+ # the running task to complete via task_reject_on_worker_lost re-delivery.
673
674
  # Exception: if STEP_SUSPENDED was recorded (step_hook suspension), the step
674
675
  # needs re-dispatch so it can re-execute and find the HOOK_RECEIVED event.
675
676
  events = await ctx.storage.get_events(ctx.run_id)
@@ -682,7 +683,7 @@ async def _dispatch_step_to_celery(
682
683
  )
683
684
  if already_started and not was_suspended:
684
685
  logger.info(
685
- f"Step {step_name} already has STEP_STARTED event, re-suspending",
686
+ f"Step {step_name} already has STEP_STARTED event, re-suspending (task running)",
686
687
  run_id=ctx.run_id,
687
688
  step_id=step_id,
688
689
  )