pyworkflow-engine 0.2.13__tar.gz → 0.2.15__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 (232) hide show
  1. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/PKG-INFO +1 -1
  2. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyproject.toml +1 -1
  3. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/__init__.py +1 -1
  4. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/celery/tasks.py +53 -4
  5. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/dispatcher.py +1 -3
  6. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/CLAUDE.md +0 -0
  7. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/DISTRIBUTED.md +0 -0
  8. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/LICENSE +0 -0
  9. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/MANIFEST.in +0 -0
  10. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/README.md +0 -0
  11. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/RELEASING.md +0 -0
  12. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/architecture.md +0 -0
  13. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/cancellation.mdx +0 -0
  14. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/continue-as-new.mdx +0 -0
  15. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/events.mdx +0 -0
  16. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/fault-tolerance.mdx +0 -0
  17. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/hooks.mdx +0 -0
  18. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/limitations.mdx +0 -0
  19. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/schedules.mdx +0 -0
  20. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/sleep.mdx +0 -0
  21. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/step-context.mdx +0 -0
  22. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/steps.mdx +0 -0
  23. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/stream-steps.mdx +0 -0
  24. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/stream-workflows.mdx +0 -0
  25. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/concepts/workflows.mdx +0 -0
  26. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/conventions.md +0 -0
  27. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/guides/brokers.mdx +0 -0
  28. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/guides/cli.mdx +0 -0
  29. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/guides/configuration.mdx +0 -0
  30. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/harness-gaps.md +0 -0
  31. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/introduction.mdx +0 -0
  32. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/layers.md +0 -0
  33. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/docs/quickstart.mdx +0 -0
  34. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/__init__.py +0 -0
  35. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/__init__.py +0 -0
  36. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/docker-compose.yml +0 -0
  37. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/pyworkflow.config.yaml +0 -0
  38. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/__init__.py +0 -0
  39. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/basic.py +0 -0
  40. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/batch_processing.py +0 -0
  41. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/cancellation.py +0 -0
  42. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/child_workflow_from_step.py +0 -0
  43. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/child_workflow_patterns.py +0 -0
  44. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/child_workflows.py +0 -0
  45. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/continue_as_new.py +0 -0
  46. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/fault_tolerance.py +0 -0
  47. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/hooks.py +0 -0
  48. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/idempotency.py +0 -0
  49. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/long_running.py +0 -0
  50. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/retries.py +0 -0
  51. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/schedules.py +0 -0
  52. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/sleep_in_step.py +0 -0
  53. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/durable/workflows/step_context.py +0 -0
  54. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/transient/01_basic_workflow.py +0 -0
  55. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/transient/02_fault_tolerance.py +0 -0
  56. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/transient/__init__.py +0 -0
  57. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/celery/transient/pyworkflow.config.yaml +0 -0
  58. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/__init__.py +0 -0
  59. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/01_basic_workflow.py +0 -0
  60. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/02_file_storage.py +0 -0
  61. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/03_retries.py +0 -0
  62. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/04_long_running.py +0 -0
  63. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/05_event_log.py +0 -0
  64. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/06_idempotency.py +0 -0
  65. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/07_hooks.py +0 -0
  66. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/08_cancellation.py +0 -0
  67. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/09_child_workflows.py +0 -0
  68. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/10_child_workflow_patterns.py +0 -0
  69. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/11_continue_as_new.py +0 -0
  70. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/12_schedules.py +0 -0
  71. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/13_step_context.py +0 -0
  72. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/14_child_workflow_from_step.py +0 -0
  73. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/durable/__init__.py +0 -0
  74. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/transient/01_quick_tasks.py +0 -0
  75. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/transient/02_retries.py +0 -0
  76. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/transient/03_sleep.py +0 -0
  77. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/examples/local/transient/__init__.py +0 -0
  78. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/aws/__init__.py +0 -0
  79. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/aws/context.py +0 -0
  80. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/aws/handler.py +0 -0
  81. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/aws/testing.py +0 -0
  82. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/celery/__init__.py +0 -0
  83. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/celery/app.py +0 -0
  84. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/celery/loop.py +0 -0
  85. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/celery/scheduler.py +0 -0
  86. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/celery/singleton.py +0 -0
  87. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/__init__.py +0 -0
  88. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/__main__.py +0 -0
  89. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/__init__.py +0 -0
  90. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/hooks.py +0 -0
  91. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/quickstart.py +0 -0
  92. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/runs.py +0 -0
  93. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/scheduler.py +0 -0
  94. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/schedules.py +0 -0
  95. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/setup.py +0 -0
  96. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/worker.py +0 -0
  97. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/commands/workflows.py +0 -0
  98. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/output/__init__.py +0 -0
  99. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/output/formatters.py +0 -0
  100. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/output/styles.py +0 -0
  101. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/__init__.py +0 -0
  102. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/async_helpers.py +0 -0
  103. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/config.py +0 -0
  104. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/config_generator.py +0 -0
  105. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/discovery.py +0 -0
  106. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/docker_manager.py +0 -0
  107. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/interactive.py +0 -0
  108. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/cli/utils/storage.py +0 -0
  109. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/config.py +0 -0
  110. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/context/__init__.py +0 -0
  111. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/context/aws.py +0 -0
  112. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/context/base.py +0 -0
  113. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/context/local.py +0 -0
  114. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/context/mock.py +0 -0
  115. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/context/step_context.py +0 -0
  116. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/core/__init__.py +0 -0
  117. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/core/exceptions.py +0 -0
  118. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/core/registry.py +0 -0
  119. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/core/scheduled.py +0 -0
  120. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/core/step.py +0 -0
  121. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/core/validation.py +0 -0
  122. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/core/workflow.py +0 -0
  123. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/discovery.py +0 -0
  124. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/engine/__init__.py +0 -0
  125. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/engine/events.py +0 -0
  126. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/engine/executor.py +0 -0
  127. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/engine/replay.py +0 -0
  128. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/observability/__init__.py +0 -0
  129. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/observability/logging.py +0 -0
  130. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/__init__.py +0 -0
  131. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/child_handle.py +0 -0
  132. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/child_workflow.py +0 -0
  133. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/continue_as_new.py +0 -0
  134. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/define_hook.py +0 -0
  135. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/hooks.py +0 -0
  136. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/resume_hook.py +0 -0
  137. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/schedule.py +0 -0
  138. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/shield.py +0 -0
  139. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/sleep.py +0 -0
  140. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/step_checkpoint.py +0 -0
  141. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/primitives/step_hook.py +0 -0
  142. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/runtime/__init__.py +0 -0
  143. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/runtime/base.py +0 -0
  144. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/runtime/celery.py +0 -0
  145. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/runtime/factory.py +0 -0
  146. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/runtime/local.py +0 -0
  147. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/scheduler/__init__.py +0 -0
  148. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/scheduler/local.py +0 -0
  149. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/serialization/__init__.py +0 -0
  150. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/serialization/decoder.py +0 -0
  151. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/serialization/encoder.py +0 -0
  152. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/__init__.py +0 -0
  153. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/base.py +0 -0
  154. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/cassandra.py +0 -0
  155. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/citus.py +0 -0
  156. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/config.py +0 -0
  157. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/dynamodb.py +0 -0
  158. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/file.py +0 -0
  159. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/memory.py +0 -0
  160. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/migrations/__init__.py +0 -0
  161. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/migrations/base.py +0 -0
  162. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/mysql.py +0 -0
  163. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/postgres.py +0 -0
  164. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/schemas.py +0 -0
  165. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/storage/sqlite.py +0 -0
  166. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/__init__.py +0 -0
  167. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/checkpoint.py +0 -0
  168. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/consumer.py +0 -0
  169. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/context.py +0 -0
  170. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/decorator.py +0 -0
  171. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/emit.py +0 -0
  172. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/registry.py +0 -0
  173. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/runtime.py +0 -0
  174. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/signal.py +0 -0
  175. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/streams/step_context.py +0 -0
  176. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/utils/__init__.py +0 -0
  177. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/utils/duration.py +0 -0
  178. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/utils/helpers.py +0 -0
  179. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow/utils/schedule.py +0 -0
  180. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/pyworkflow_engine.egg-info/SOURCES.txt +0 -0
  181. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/setup.cfg +0 -0
  182. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/__init__.py +0 -0
  183. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_cancellation.py +0 -0
  184. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_cassandra_storage.py +0 -0
  185. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_child_workflows.py +0 -0
  186. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_continue_as_new.py +0 -0
  187. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_dynamodb_storage.py +0 -0
  188. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_fault_tolerance.py +0 -0
  189. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_schedule_storage.py +0 -0
  190. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_schema_migrations.py +0 -0
  191. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_singleton.py +0 -0
  192. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_stream_e2e.py +0 -0
  193. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/integration/test_workflow_suspended.py +0 -0
  194. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/__init__.py +0 -0
  195. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/backends/__init__.py +0 -0
  196. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/backends/test_cassandra_storage.py +0 -0
  197. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/backends/test_citus_storage.py +0 -0
  198. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/backends/test_dynamodb_storage.py +0 -0
  199. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/backends/test_postgres_storage.py +0 -0
  200. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/backends/test_sqlite_storage.py +0 -0
  201. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/conftest.py +0 -0
  202. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/storage/__init__.py +0 -0
  203. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/storage/test_migrations.py +0 -0
  204. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_cancellation.py +0 -0
  205. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_child_workflows.py +0 -0
  206. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_cli_worker.py +0 -0
  207. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_continue_as_new.py +0 -0
  208. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_emit.py +0 -0
  209. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_event_limits.py +0 -0
  210. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_executor.py +0 -0
  211. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_fault_tolerance.py +0 -0
  212. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_force_local.py +0 -0
  213. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_hooks.py +0 -0
  214. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_parent_run_id.py +0 -0
  215. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_primitives_from_steps.py +0 -0
  216. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_registry.py +0 -0
  217. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_replay.py +0 -0
  218. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_retention.py +0 -0
  219. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_schedule_schemas.py +0 -0
  220. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_schedule_utils.py +0 -0
  221. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_scheduled_workflow.py +0 -0
  222. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_signal.py +0 -0
  223. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_singleton.py +0 -0
  224. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_step.py +0 -0
  225. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_step_checkpoint.py +0 -0
  226. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_step_context.py +0 -0
  227. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_step_hook.py +0 -0
  228. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_stream_storage.py +0 -0
  229. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_stream_workflow.py +0 -0
  230. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_validation.py +0 -0
  231. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/tests/unit/test_workflow.py +0 -0
  232. {pyworkflow_engine-0.2.13 → pyworkflow_engine-0.2.15}/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.13
3
+ Version: 0.2.15
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.13"
10
+ version = "0.2.15"
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.13"
32
+ __version__ = "0.2.15"
33
33
 
34
34
  # Configuration
35
35
  from pyworkflow.config import (
@@ -508,8 +508,17 @@ async def _record_step_completion_and_resume(
508
508
  run_id, EventType.STEP_COMPLETED.value, step_id=step_id
509
509
  )
510
510
  if already_completed:
511
+ # A prior worker recorded STEP_COMPLETED but may have crashed before
512
+ # scheduling the workflow resume. Re-schedule defensively — the resume
513
+ # task is idempotent via try_claim_run(SUSPENDED -> RUNNING).
514
+ schedule_workflow_resumption(
515
+ run_id,
516
+ datetime.now(UTC),
517
+ storage_config,
518
+ triggered_by="step_completed_idempotent_retry",
519
+ )
511
520
  logger.info(
512
- "Step already completed by another task, skipping",
521
+ "Step already completed by another task, re-scheduled resume",
513
522
  run_id=run_id,
514
523
  step_id=step_id,
515
524
  step_name=step_name,
@@ -537,8 +546,16 @@ async def _record_step_completion_and_resume(
537
546
  run_id, EventType.STEP_COMPLETED.value, step_id=step_id
538
547
  )
539
548
  if already_completed:
549
+ # Defensive re-schedule: the peer that recorded STEP_COMPLETED may
550
+ # have crashed before scheduling resume. Safe due to try_claim_run.
551
+ schedule_workflow_resumption(
552
+ run_id,
553
+ datetime.now(UTC),
554
+ storage_config,
555
+ triggered_by="step_completed_idempotent_retry",
556
+ )
540
557
  logger.info(
541
- "Step already completed by another task during wait, skipping",
558
+ "Step already completed by another task during wait, re-scheduled resume",
542
559
  run_id=run_id,
543
560
  step_id=step_id,
544
561
  step_name=step_name,
@@ -563,6 +580,15 @@ async def _record_step_completion_and_resume(
563
580
  )
564
581
  await storage.record_event(completion_event)
565
582
 
583
+ # Release the resume_workflow_task singleton lock before scheduling the
584
+ # next resume. The parent resume task that dispatched this step may still
585
+ # be holding the (run_id,) lock during its final teardown; without this
586
+ # release the apply_async below sees the lock held and silently drops
587
+ # the schedule as a duplicate, leaving the workflow stuck in SUSPENDED.
588
+ resume_workflow_task.release_lock(
589
+ task_args=[run_id], task_kwargs={"storage_config": storage_config}
590
+ )
591
+
566
592
  # Schedule workflow resumption
567
593
  schedule_workflow_resumption(
568
594
  run_id, datetime.now(UTC), storage_config, triggered_by="step_completed"
@@ -676,8 +702,17 @@ async def _record_step_failure_and_resume(
676
702
  run_id, EventType.STEP_FAILED.value, step_id=step_id, is_retryable="False"
677
703
  )
678
704
  if already_completed or already_failed_terminal:
705
+ # A prior worker recorded the terminal event but may have crashed before
706
+ # scheduling the workflow resume. Re-schedule defensively — safe due to
707
+ # try_claim_run(SUSPENDED -> RUNNING) idempotency.
708
+ schedule_workflow_resumption(
709
+ run_id,
710
+ datetime.now(UTC),
711
+ storage_config,
712
+ triggered_by="step_failed_idempotent_retry",
713
+ )
679
714
  logger.info(
680
- "Step already completed/failed by another task, skipping",
715
+ "Step already completed/failed by another task, re-scheduled resume",
681
716
  run_id=run_id,
682
717
  step_id=step_id,
683
718
  step_name=step_name,
@@ -708,8 +743,16 @@ async def _record_step_failure_and_resume(
708
743
  run_id, EventType.STEP_FAILED.value, step_id=step_id, is_retryable="False"
709
744
  )
710
745
  if already_completed or already_failed_terminal:
746
+ # Defensive re-schedule: peer that recorded the terminal event may
747
+ # have crashed before scheduling resume. Safe due to try_claim_run.
748
+ schedule_workflow_resumption(
749
+ run_id,
750
+ datetime.now(UTC),
751
+ storage_config,
752
+ triggered_by="step_failed_idempotent_retry",
753
+ )
711
754
  logger.info(
712
- "Step already completed/failed by another task during wait, skipping",
755
+ "Step already completed/failed by another task during wait, re-scheduled resume",
713
756
  run_id=run_id,
714
757
  step_id=step_id,
715
758
  step_name=step_name,
@@ -735,6 +778,12 @@ async def _record_step_failure_and_resume(
735
778
  )
736
779
  await storage.record_event(failure_event)
737
780
 
781
+ # Release the resume_workflow_task singleton lock before scheduling the
782
+ # next resume (see _record_step_completion_and_resume for details on why).
783
+ resume_workflow_task.release_lock(
784
+ task_args=[run_id], task_kwargs={"storage_config": storage_config}
785
+ )
786
+
738
787
  # Schedule workflow resumption
739
788
  schedule_workflow_resumption(
740
789
  run_id, datetime.now(UTC), storage_config, triggered_by="step_failed"
@@ -72,9 +72,7 @@ async def dispatch_signal(signal: Signal, storage: Any) -> None:
72
72
  # running step) or by _drain_pending_signals_for_step() when the
73
73
  # step transitions back to "waiting". Use DEBUG to avoid noisy
74
74
  # warnings for this expected scenario.
75
- has_running = any(
76
- s.get("status") == "running" for s in (all_subs or [])
77
- )
75
+ has_running = any(s.get("status") == "running" for s in (all_subs or []))
78
76
  log_fn = logger.debug if has_running else logger.warning
79
77
  log_fn(
80
78
  f"No waiting steps for {signal.signal_type} on {signal.stream_id} "