pyworkflow-engine 0.2.9__tar.gz → 0.2.11__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.9 → pyworkflow_engine-0.2.11}/PKG-INFO +1 -1
  2. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyproject.toml +1 -1
  3. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/__init__.py +1 -1
  4. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/celery/app.py +85 -0
  5. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/citus.py +12 -7
  6. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/postgres.py +12 -8
  7. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/CLAUDE.md +0 -0
  8. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/DISTRIBUTED.md +0 -0
  9. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/LICENSE +0 -0
  10. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/MANIFEST.in +0 -0
  11. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/README.md +0 -0
  12. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/RELEASING.md +0 -0
  13. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/architecture.md +0 -0
  14. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/cancellation.mdx +0 -0
  15. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/continue-as-new.mdx +0 -0
  16. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/events.mdx +0 -0
  17. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/fault-tolerance.mdx +0 -0
  18. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/hooks.mdx +0 -0
  19. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/limitations.mdx +0 -0
  20. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/schedules.mdx +0 -0
  21. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/sleep.mdx +0 -0
  22. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/step-context.mdx +0 -0
  23. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/steps.mdx +0 -0
  24. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/stream-steps.mdx +0 -0
  25. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/stream-workflows.mdx +0 -0
  26. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/concepts/workflows.mdx +0 -0
  27. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/conventions.md +0 -0
  28. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/guides/brokers.mdx +0 -0
  29. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/guides/cli.mdx +0 -0
  30. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/guides/configuration.mdx +0 -0
  31. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/harness-gaps.md +0 -0
  32. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/introduction.mdx +0 -0
  33. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/layers.md +0 -0
  34. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/docs/quickstart.mdx +0 -0
  35. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/__init__.py +0 -0
  36. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/__init__.py +0 -0
  37. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/docker-compose.yml +0 -0
  38. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/pyworkflow.config.yaml +0 -0
  39. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/__init__.py +0 -0
  40. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/basic.py +0 -0
  41. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/batch_processing.py +0 -0
  42. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/cancellation.py +0 -0
  43. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/child_workflow_from_step.py +0 -0
  44. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/child_workflow_patterns.py +0 -0
  45. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/child_workflows.py +0 -0
  46. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/continue_as_new.py +0 -0
  47. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/fault_tolerance.py +0 -0
  48. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/hooks.py +0 -0
  49. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/idempotency.py +0 -0
  50. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/long_running.py +0 -0
  51. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/retries.py +0 -0
  52. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/schedules.py +0 -0
  53. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/sleep_in_step.py +0 -0
  54. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/durable/workflows/step_context.py +0 -0
  55. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/transient/01_basic_workflow.py +0 -0
  56. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/transient/02_fault_tolerance.py +0 -0
  57. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/transient/__init__.py +0 -0
  58. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/celery/transient/pyworkflow.config.yaml +0 -0
  59. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/__init__.py +0 -0
  60. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/01_basic_workflow.py +0 -0
  61. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/02_file_storage.py +0 -0
  62. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/03_retries.py +0 -0
  63. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/04_long_running.py +0 -0
  64. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/05_event_log.py +0 -0
  65. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/06_idempotency.py +0 -0
  66. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/07_hooks.py +0 -0
  67. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/08_cancellation.py +0 -0
  68. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/09_child_workflows.py +0 -0
  69. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/10_child_workflow_patterns.py +0 -0
  70. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/11_continue_as_new.py +0 -0
  71. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/12_schedules.py +0 -0
  72. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/13_step_context.py +0 -0
  73. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/14_child_workflow_from_step.py +0 -0
  74. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/durable/__init__.py +0 -0
  75. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/transient/01_quick_tasks.py +0 -0
  76. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/transient/02_retries.py +0 -0
  77. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/transient/03_sleep.py +0 -0
  78. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/examples/local/transient/__init__.py +0 -0
  79. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/aws/__init__.py +0 -0
  80. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/aws/context.py +0 -0
  81. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/aws/handler.py +0 -0
  82. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/aws/testing.py +0 -0
  83. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/celery/__init__.py +0 -0
  84. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/celery/loop.py +0 -0
  85. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/celery/scheduler.py +0 -0
  86. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/celery/singleton.py +0 -0
  87. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/celery/tasks.py +0 -0
  88. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/__init__.py +0 -0
  89. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/__main__.py +0 -0
  90. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/__init__.py +0 -0
  91. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/hooks.py +0 -0
  92. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/quickstart.py +0 -0
  93. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/runs.py +0 -0
  94. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/scheduler.py +0 -0
  95. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/schedules.py +0 -0
  96. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/setup.py +0 -0
  97. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/worker.py +0 -0
  98. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/commands/workflows.py +0 -0
  99. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/output/__init__.py +0 -0
  100. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/output/formatters.py +0 -0
  101. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/output/styles.py +0 -0
  102. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/__init__.py +0 -0
  103. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/async_helpers.py +0 -0
  104. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/config.py +0 -0
  105. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/config_generator.py +0 -0
  106. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/discovery.py +0 -0
  107. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/docker_manager.py +0 -0
  108. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/interactive.py +0 -0
  109. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/cli/utils/storage.py +0 -0
  110. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/config.py +0 -0
  111. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/context/__init__.py +0 -0
  112. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/context/aws.py +0 -0
  113. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/context/base.py +0 -0
  114. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/context/local.py +0 -0
  115. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/context/mock.py +0 -0
  116. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/context/step_context.py +0 -0
  117. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/core/__init__.py +0 -0
  118. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/core/exceptions.py +0 -0
  119. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/core/registry.py +0 -0
  120. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/core/scheduled.py +0 -0
  121. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/core/step.py +0 -0
  122. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/core/validation.py +0 -0
  123. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/core/workflow.py +0 -0
  124. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/discovery.py +0 -0
  125. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/engine/__init__.py +0 -0
  126. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/engine/events.py +0 -0
  127. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/engine/executor.py +0 -0
  128. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/engine/replay.py +0 -0
  129. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/observability/__init__.py +0 -0
  130. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/observability/logging.py +0 -0
  131. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/__init__.py +0 -0
  132. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/child_handle.py +0 -0
  133. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/child_workflow.py +0 -0
  134. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/continue_as_new.py +0 -0
  135. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/define_hook.py +0 -0
  136. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/hooks.py +0 -0
  137. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/resume_hook.py +0 -0
  138. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/schedule.py +0 -0
  139. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/shield.py +0 -0
  140. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/sleep.py +0 -0
  141. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/step_checkpoint.py +0 -0
  142. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/primitives/step_hook.py +0 -0
  143. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/runtime/__init__.py +0 -0
  144. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/runtime/base.py +0 -0
  145. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/runtime/celery.py +0 -0
  146. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/runtime/factory.py +0 -0
  147. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/runtime/local.py +0 -0
  148. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/scheduler/__init__.py +0 -0
  149. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/scheduler/local.py +0 -0
  150. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/serialization/__init__.py +0 -0
  151. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/serialization/decoder.py +0 -0
  152. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/serialization/encoder.py +0 -0
  153. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/__init__.py +0 -0
  154. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/base.py +0 -0
  155. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/cassandra.py +0 -0
  156. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/config.py +0 -0
  157. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/dynamodb.py +0 -0
  158. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/file.py +0 -0
  159. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/memory.py +0 -0
  160. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/migrations/__init__.py +0 -0
  161. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/migrations/base.py +0 -0
  162. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/mysql.py +0 -0
  163. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/schemas.py +0 -0
  164. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/storage/sqlite.py +0 -0
  165. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/__init__.py +0 -0
  166. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/checkpoint.py +0 -0
  167. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/consumer.py +0 -0
  168. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/context.py +0 -0
  169. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/decorator.py +0 -0
  170. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/dispatcher.py +0 -0
  171. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/emit.py +0 -0
  172. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/registry.py +0 -0
  173. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/runtime.py +0 -0
  174. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/signal.py +0 -0
  175. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/streams/step_context.py +0 -0
  176. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/utils/__init__.py +0 -0
  177. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/utils/duration.py +0 -0
  178. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/utils/helpers.py +0 -0
  179. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow/utils/schedule.py +0 -0
  180. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/pyworkflow_engine.egg-info/SOURCES.txt +0 -0
  181. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/setup.cfg +0 -0
  182. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/__init__.py +0 -0
  183. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_cancellation.py +0 -0
  184. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_cassandra_storage.py +0 -0
  185. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_child_workflows.py +0 -0
  186. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_continue_as_new.py +0 -0
  187. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_dynamodb_storage.py +0 -0
  188. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_fault_tolerance.py +0 -0
  189. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_schedule_storage.py +0 -0
  190. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_schema_migrations.py +0 -0
  191. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_singleton.py +0 -0
  192. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_stream_e2e.py +0 -0
  193. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/integration/test_workflow_suspended.py +0 -0
  194. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/__init__.py +0 -0
  195. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/backends/__init__.py +0 -0
  196. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/backends/test_cassandra_storage.py +0 -0
  197. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/backends/test_citus_storage.py +0 -0
  198. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/backends/test_dynamodb_storage.py +0 -0
  199. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/backends/test_postgres_storage.py +0 -0
  200. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/backends/test_sqlite_storage.py +0 -0
  201. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/conftest.py +0 -0
  202. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/storage/__init__.py +0 -0
  203. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/storage/test_migrations.py +0 -0
  204. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_cancellation.py +0 -0
  205. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_child_workflows.py +0 -0
  206. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_cli_worker.py +0 -0
  207. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_continue_as_new.py +0 -0
  208. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_emit.py +0 -0
  209. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_event_limits.py +0 -0
  210. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_executor.py +0 -0
  211. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_fault_tolerance.py +0 -0
  212. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_force_local.py +0 -0
  213. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_hooks.py +0 -0
  214. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_parent_run_id.py +0 -0
  215. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_primitives_from_steps.py +0 -0
  216. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_registry.py +0 -0
  217. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_replay.py +0 -0
  218. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_retention.py +0 -0
  219. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_schedule_schemas.py +0 -0
  220. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_schedule_utils.py +0 -0
  221. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_scheduled_workflow.py +0 -0
  222. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_signal.py +0 -0
  223. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_singleton.py +0 -0
  224. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_step.py +0 -0
  225. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_step_checkpoint.py +0 -0
  226. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_step_context.py +0 -0
  227. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_step_hook.py +0 -0
  228. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_stream_storage.py +0 -0
  229. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_stream_workflow.py +0 -0
  230. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_validation.py +0 -0
  231. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/tests/unit/test_workflow.py +0 -0
  232. {pyworkflow_engine-0.2.9 → pyworkflow_engine-0.2.11}/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.9
3
+ Version: 0.2.11
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.9"
10
+ version = "0.2.11"
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.9"
32
+ __version__ = "0.2.11"
33
33
 
34
34
  # Configuration
35
35
  from pyworkflow.config import (
@@ -61,6 +61,82 @@ def _run_warmup_callable(dotted_path: str) -> None:
61
61
  )
62
62
 
63
63
 
64
+ def _run_startup_migrations() -> None:
65
+ """Run pending DB migrations before the worker accepts tasks.
66
+
67
+ Loads storage configuration from environment variables, creates a throwaway
68
+ backend, calls ``connect()`` (which triggers ``_initialize_schema()`` →
69
+ ``run_migrations()``), and disconnects. The pool is bound to a temporary
70
+ event loop that lives only for this function, so the forked workers below
71
+ start with no inherited state.
72
+
73
+ Behavior:
74
+ - If ``PYWORKFLOW_STORAGE_TYPE`` is unset, or points at a schema-less backend
75
+ (``memory`` / ``file``), this is a no-op and tasks fall back to lazy init.
76
+ - If migrations raise, the exception propagates — the worker fails to start
77
+ rather than accepting tasks against a schema it can't read. That is the
78
+ desired failure mode: a restart loop is louder than silent corruption.
79
+ - Controllable via ``PYWORKFLOW_SKIP_STARTUP_MIGRATIONS=1`` for deployments
80
+ that intentionally migrate out-of-band (e.g. a dedicated job).
81
+ """
82
+ import asyncio
83
+
84
+ from loguru import logger as loguru_logger
85
+
86
+ if os.getenv("PYWORKFLOW_SKIP_STARTUP_MIGRATIONS", "").lower() in ("1", "true", "yes"):
87
+ loguru_logger.info(
88
+ "STARTUP_MIGRATIONS: skipped (PYWORKFLOW_SKIP_STARTUP_MIGRATIONS set)"
89
+ )
90
+ return
91
+
92
+ from pyworkflow.config import _load_env_storage_config
93
+
94
+ config = _load_env_storage_config()
95
+ if not config:
96
+ loguru_logger.info(
97
+ "STARTUP_MIGRATIONS: PYWORKFLOW_STORAGE_TYPE not set — skipping. "
98
+ "Migrations will run lazily on first task that touches storage."
99
+ )
100
+ return
101
+
102
+ storage_type = config.get("type")
103
+ if storage_type in ("memory", "file"):
104
+ loguru_logger.info(
105
+ f"STARTUP_MIGRATIONS: skipping for type={storage_type} (schema-less backend)"
106
+ )
107
+ return
108
+
109
+ loguru_logger.info(
110
+ f"STARTUP_MIGRATIONS: connecting to {storage_type} to apply pending migrations"
111
+ )
112
+
113
+ async def _run() -> None:
114
+ # Create the backend directly (bypassing the cache) so that the pool we
115
+ # open here does not leak into the forked workers' storage cache. The
116
+ # worker processes will each create their own pool on first task.
117
+ from pyworkflow.storage.config import _create_storage_backend
118
+
119
+ backend = _create_storage_backend(config)
120
+ try:
121
+ await backend.connect()
122
+ finally:
123
+ try:
124
+ if hasattr(backend, "disconnect"):
125
+ await backend.disconnect()
126
+ except Exception as e:
127
+ loguru_logger.warning(f"STARTUP_MIGRATIONS: disconnect failed: {e}")
128
+
129
+ try:
130
+ asyncio.run(_run())
131
+ except Exception:
132
+ loguru_logger.opt(exception=True).error(
133
+ "STARTUP_MIGRATIONS: FAILED — worker will not start"
134
+ )
135
+ raise
136
+
137
+ loguru_logger.info("STARTUP_MIGRATIONS: completed successfully")
138
+
139
+
64
140
  def is_sentinel_url(url: str) -> bool:
65
141
  """Check if URL uses sentinel:// or sentinel+ssl:// protocol."""
66
142
  return url.startswith("sentinel://") or url.startswith("sentinel+ssl://")
@@ -420,6 +496,15 @@ def on_worker_init(**kwargs):
420
496
  if warmup_path:
421
497
  _run_warmup_callable(warmup_path)
422
498
 
499
+ # Apply pending DB migrations once per pod, BEFORE any task is dispatched.
500
+ # This replaces the old lazy "first task triggers connect() triggers
501
+ # migrations" path, which was fragile: backend instances cached across
502
+ # restarts (or inherited via fork) would skip migrations entirely because
503
+ # _initialized was True without the migration check ever having run in
504
+ # this process. Running at startup makes migration state observable in
505
+ # the pod logs and fails the pod fast if the schema is incompatible.
506
+ _run_startup_migrations()
507
+
423
508
 
424
509
  @worker_process_init.connect
425
510
  def on_worker_process_init(**kwargs):
@@ -340,9 +340,11 @@ class CitusStorageBackend(PostgresStorageBackend):
340
340
  await conn.execute(
341
341
  "CREATE INDEX IF NOT EXISTS idx_events_run_id_type ON events(run_id, type)"
342
342
  )
343
- await conn.execute(
344
- "CREATE INDEX IF NOT EXISTS idx_events_run_id_step_id_type ON events(run_id, step_id, type)"
345
- )
343
+ # NOTE: idx_events_run_id_step_id_type is intentionally NOT created here.
344
+ # On a pre-v2 database, the step_id column does not yet exist
345
+ # (CREATE TABLE IF NOT EXISTS above is a no-op on existing tables, so
346
+ # the new column declaration is ignored). The v2 migration adds the
347
+ # column AND creates this index — see CitusMigrationRunner version 2.
346
348
 
347
349
  # steps — distributed on run_id, co-located with workflow_runs
348
350
  # Differences vs postgres:
@@ -503,10 +505,13 @@ class CitusStorageBackend(PostgresStorageBackend):
503
505
  await conn.execute(
504
506
  "CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON stream_subscriptions(stream_id, status)"
505
507
  )
506
- await conn.execute(
507
- "CREATE INDEX IF NOT EXISTS idx_subscriptions_stream_run "
508
- "ON stream_subscriptions(stream_id, stream_run_id)"
509
- )
508
+ # NOTE: idx_subscriptions_stream_run is intentionally NOT created here.
509
+ # On a pre-v5 database, the stream_run_id column does not yet exist
510
+ # (CREATE TABLE IF NOT EXISTS above is a no-op on existing tables, so
511
+ # the new column declarations are ignored). The v5 migration adds the
512
+ # column AND creates this index idempotently — see CitusMigrationRunner
513
+ # version 5. Creating the index here would crash _initialize_schema
514
+ # before run_migrations() ever gets a chance to run.
510
515
 
511
516
  # scheduled_signals — reference table (polled globally by runtime)
512
517
  await conn.execute("""
@@ -446,10 +446,11 @@ class PostgresStorageBackend(StorageBackend):
446
446
  await conn.execute(
447
447
  "CREATE INDEX IF NOT EXISTS idx_events_run_id_type ON events(run_id, type)"
448
448
  )
449
- # Optimized index for has_event() with step_id filter (V2 migration)
450
- await conn.execute(
451
- "CREATE INDEX IF NOT EXISTS idx_events_run_id_step_id_type ON events(run_id, step_id, type)"
452
- )
449
+ # NOTE: idx_events_run_id_step_id_type is intentionally NOT created here.
450
+ # On a pre-v2 database, the step_id column does not yet exist
451
+ # (CREATE TABLE IF NOT EXISTS above is a no-op on existing tables, so
452
+ # the new column declaration is ignored). The v2 migration adds the
453
+ # column AND creates this index — see PostgresMigrationRunner version 2.
453
454
 
454
455
  # Steps table
455
456
  await conn.execute("""
@@ -593,10 +594,13 @@ class PostgresStorageBackend(StorageBackend):
593
594
  await conn.execute(
594
595
  "CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON stream_subscriptions(stream_id, status)"
595
596
  )
596
- await conn.execute(
597
- "CREATE INDEX IF NOT EXISTS idx_subscriptions_stream_run "
598
- "ON stream_subscriptions(stream_id, stream_run_id)"
599
- )
597
+ # NOTE: idx_subscriptions_stream_run is intentionally NOT created here.
598
+ # On a pre-v5 database, the stream_run_id column does not yet exist
599
+ # (CREATE TABLE IF NOT EXISTS above is a no-op on existing tables, so
600
+ # the new column declarations are ignored). The v5 migration adds the
601
+ # column AND creates this index idempotently — see PostgresMigrationRunner
602
+ # version 5. Creating the index here would crash _initialize_schema
603
+ # before run_migrations() ever gets a chance to run.
600
604
 
601
605
  # Scheduled signals table (for schedule_signal() primitive)
602
606
  await conn.execute("""