prefect-client 3.0.0rc11__tar.gz → 3.0.0rc13__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 (203) hide show
  1. {prefect-client-3.0.0rc11/src/prefect_client.egg-info → prefect-client-3.0.0rc13}/PKG-INFO +1 -1
  2. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/requirements-client.txt +1 -1
  3. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/requirements-dev.txt +0 -1
  4. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/services.py +9 -0
  5. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/artifacts.py +12 -0
  6. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/schemas/actions.py +4 -0
  7. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/clients.py +5 -0
  8. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/schemas/events.py +10 -0
  9. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/flow_engine.py +5 -2
  10. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/flows.py +17 -5
  11. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/results.py +1 -46
  12. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runner/runner.py +3 -3
  13. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/settings.py +0 -22
  14. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/task_engine.py +163 -48
  15. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/task_worker.py +24 -16
  16. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/tasks.py +164 -17
  17. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/transactions.py +2 -31
  18. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/asyncutils.py +12 -9
  19. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13/src/prefect_client.egg-info}/PKG-INFO +1 -1
  20. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect_client.egg-info/requires.txt +1 -1
  21. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/LICENSE +0 -0
  22. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/MANIFEST.in +0 -0
  23. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/README.md +0 -0
  24. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/requirements.txt +0 -0
  25. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/setup.cfg +0 -0
  26. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/setup.py +0 -0
  27. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/.prefectignore +0 -0
  28. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/__init__.py +0 -0
  29. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/__init__.py +0 -0
  30. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/_logging.py +0 -0
  31. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/compatibility/__init__.py +0 -0
  32. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/compatibility/deprecated.py +0 -0
  33. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/compatibility/experimental.py +0 -0
  34. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/compatibility/migration.py +0 -0
  35. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/__init__.py +0 -0
  36. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/api.py +0 -0
  37. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/calls.py +0 -0
  38. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/cancellation.py +0 -0
  39. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/event_loop.py +0 -0
  40. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/inspection.py +0 -0
  41. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/primitives.py +0 -0
  42. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/threads.py +0 -0
  43. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/concurrency/waiters.py +0 -0
  44. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/integrations.py +0 -0
  45. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pydantic/__init__.py +0 -0
  46. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pydantic/annotations/__init__.py +0 -0
  47. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pydantic/annotations/pendulum.py +0 -0
  48. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pydantic/schemas.py +0 -0
  49. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pydantic/v1_schema.py +0 -0
  50. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pydantic/v2_schema.py +0 -0
  51. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pydantic/v2_validated_func.py +0 -0
  52. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/pytz.py +0 -0
  53. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/retries.py +0 -0
  54. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/schemas/__init__.py +0 -0
  55. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/schemas/bases.py +0 -0
  56. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/schemas/fields.py +0 -0
  57. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/schemas/serializers.py +0 -0
  58. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_internal/schemas/validators.py +0 -0
  59. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/_version.py +0 -0
  60. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/agent.py +0 -0
  61. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/automations.py +0 -0
  62. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/__init__.py +0 -0
  63. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/abstract.py +0 -0
  64. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/core.py +0 -0
  65. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/fields.py +0 -0
  66. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/notifications.py +0 -0
  67. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/redis.py +0 -0
  68. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/system.py +0 -0
  69. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/blocks/webhook.py +0 -0
  70. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/cache_policies.py +0 -0
  71. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/__init__.py +0 -0
  72. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/base.py +0 -0
  73. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/cloud.py +0 -0
  74. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/collections.py +0 -0
  75. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/constants.py +0 -0
  76. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/orchestration.py +0 -0
  77. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/schemas/__init__.py +0 -0
  78. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/schemas/filters.py +0 -0
  79. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/schemas/objects.py +0 -0
  80. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/schemas/responses.py +0 -0
  81. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/schemas/schedules.py +0 -0
  82. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/schemas/sorting.py +0 -0
  83. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/subscriptions.py +0 -0
  84. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/types/__init__.py +0 -0
  85. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/types/flexible_schedule_list.py +0 -0
  86. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/client/utilities.py +0 -0
  87. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/concurrency/__init__.py +0 -0
  88. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/concurrency/asyncio.py +0 -0
  89. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/concurrency/events.py +0 -0
  90. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/concurrency/services.py +0 -0
  91. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/concurrency/sync.py +0 -0
  92. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/context.py +0 -0
  93. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/__init__.py +0 -0
  94. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/base.py +0 -0
  95. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/deployments.py +0 -0
  96. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/flow_runs.py +0 -0
  97. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/runner.py +0 -0
  98. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/schedules.py +0 -0
  99. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/steps/__init__.py +0 -0
  100. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/steps/core.py +0 -0
  101. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/steps/pull.py +0 -0
  102. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/deployments/steps/utility.py +0 -0
  103. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/docker/__init__.py +0 -0
  104. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/docker/docker_image.py +0 -0
  105. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/engine.py +0 -0
  106. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/__init__.py +0 -0
  107. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/actions.py +0 -0
  108. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/cli/__init__.py +0 -0
  109. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/cli/automations.py +0 -0
  110. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/filters.py +0 -0
  111. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/related.py +0 -0
  112. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/schemas/__init__.py +0 -0
  113. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/schemas/automations.py +0 -0
  114. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/schemas/deployment_triggers.py +0 -0
  115. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/schemas/labelling.py +0 -0
  116. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/utilities.py +0 -0
  117. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/events/worker.py +0 -0
  118. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/exceptions.py +0 -0
  119. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/filesystems.py +0 -0
  120. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/flow_runs.py +0 -0
  121. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/futures.py +0 -0
  122. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/infrastructure/__init__.py +0 -0
  123. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/infrastructure/base.py +0 -0
  124. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/infrastructure/provisioners/__init__.py +0 -0
  125. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/infrastructure/provisioners/cloud_run.py +0 -0
  126. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/infrastructure/provisioners/container_instance.py +0 -0
  127. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/infrastructure/provisioners/ecs.py +0 -0
  128. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/infrastructure/provisioners/modal.py +0 -0
  129. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/input/__init__.py +0 -0
  130. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/input/actions.py +0 -0
  131. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/input/run_input.py +0 -0
  132. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/__init__.py +0 -0
  133. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/configuration.py +0 -0
  134. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/filters.py +0 -0
  135. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/formatters.py +0 -0
  136. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/handlers.py +0 -0
  137. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/highlighters.py +0 -0
  138. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/loggers.py +0 -0
  139. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/logging/logging.yml +0 -0
  140. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/main.py +0 -0
  141. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/manifests.py +0 -0
  142. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/plugins.py +0 -0
  143. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/profiles.toml +0 -0
  144. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/py.typed +0 -0
  145. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/records/__init__.py +0 -0
  146. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/records/result_store.py +0 -0
  147. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/records/store.py +0 -0
  148. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runner/__init__.py +0 -0
  149. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runner/server.py +0 -0
  150. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runner/storage.py +0 -0
  151. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runner/submit.py +0 -0
  152. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runner/utils.py +0 -0
  153. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runtime/__init__.py +0 -0
  154. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runtime/deployment.py +0 -0
  155. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runtime/flow_run.py +0 -0
  156. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/runtime/task_run.py +0 -0
  157. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/serializers.py +0 -0
  158. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/server/api/collections_data/views/aggregate-worker-metadata.json +0 -0
  159. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/server/api/static/prefect-logo-mark-gradient.png +0 -0
  160. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/states.py +0 -0
  161. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/task_runners.py +0 -0
  162. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/task_runs.py +0 -0
  163. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/types/__init__.py +0 -0
  164. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/types/entrypoint.py +0 -0
  165. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/__init__.py +0 -0
  166. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/annotations.py +0 -0
  167. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/callables.py +0 -0
  168. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/collections.py +0 -0
  169. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/compat.py +0 -0
  170. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/context.py +0 -0
  171. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/dispatch.py +0 -0
  172. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/dockerutils.py +0 -0
  173. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/engine.py +0 -0
  174. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/filesystem.py +0 -0
  175. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/hashing.py +0 -0
  176. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/importtools.py +0 -0
  177. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/math.py +0 -0
  178. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/names.py +0 -0
  179. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/processutils.py +0 -0
  180. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/pydantic.py +0 -0
  181. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/render_swagger.py +0 -0
  182. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/schema_tools/__init__.py +0 -0
  183. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/schema_tools/hydration.py +0 -0
  184. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/schema_tools/validation.py +0 -0
  185. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/services.py +0 -0
  186. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/slugify.py +0 -0
  187. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/templating.py +0 -0
  188. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/text.py +0 -0
  189. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/timeout.py +0 -0
  190. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/urls.py +0 -0
  191. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/utilities/visualization.py +0 -0
  192. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/variables.py +0 -0
  193. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/workers/__init__.py +0 -0
  194. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/workers/base.py +0 -0
  195. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/workers/block.py +0 -0
  196. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/workers/cloud.py +0 -0
  197. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/workers/process.py +0 -0
  198. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/workers/server.py +0 -0
  199. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect/workers/utilities.py +0 -0
  200. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect_client.egg-info/SOURCES.txt +0 -0
  201. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect_client.egg-info/dependency_links.txt +0 -0
  202. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/src/prefect_client.egg-info/top_level.txt +0 -0
  203. {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc13}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prefect-client
3
- Version: 3.0.0rc11
3
+ Version: 3.0.0rc13
4
4
  Summary: Workflow orchestration and management.
5
5
  Home-page: https://www.prefect.io
6
6
  Author: Prefect Technologies, Inc.
@@ -3,7 +3,7 @@ asgi-lifespan >= 1.0, < 3.0
3
3
  cachetools >= 5.3, < 6.0
4
4
  cloudpickle >= 2.0, < 4.0
5
5
  coolname >= 1.0.4, < 3.0.0
6
- croniter >= 1.0.12, < 3.0.0
6
+ croniter >= 1.0.12, < 4.0.0
7
7
  exceptiongroup >= 1.0.0
8
8
  fastapi >= 0.111.0, < 1.0.0
9
9
  fsspec >= 2022.5.0
@@ -1,7 +1,6 @@
1
1
  ruff
2
2
  cairosvg
3
3
  codespell>=2.2.6
4
- ddtrace
5
4
  ipython
6
5
  jinja2
7
6
  moto >= 5
@@ -151,6 +151,7 @@ class QueueService(abc.ABC, Generic[T]):
151
151
 
152
152
  if item is None:
153
153
  logger.debug("Exiting service %r", self)
154
+ self._queue.task_done()
154
155
  break
155
156
 
156
157
  try:
@@ -164,6 +165,8 @@ class QueueService(abc.ABC, Generic[T]):
164
165
  item,
165
166
  exc_info=log_traceback,
166
167
  )
168
+ finally:
169
+ self._queue.task_done()
167
170
 
168
171
  @abc.abstractmethod
169
172
  async def _handle(self, item: T):
@@ -235,6 +238,12 @@ class QueueService(abc.ABC, Generic[T]):
235
238
  else:
236
239
  return concurrent.futures.wait(futures, timeout=timeout)
237
240
 
241
+ def wait_until_empty(self):
242
+ """
243
+ Wait until the queue is empty and all items have been processed.
244
+ """
245
+ self._queue.join()
246
+
238
247
  @classmethod
239
248
  def instance(cls: Type[Self], *args) -> Self:
240
249
  """
@@ -6,6 +6,7 @@ from __future__ import annotations
6
6
 
7
7
  import json # noqa: I001
8
8
  import math
9
+ import warnings
9
10
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
10
11
  from uuid import UUID
11
12
 
@@ -54,8 +55,19 @@ class Artifact(ArtifactRequest):
54
55
  Returns:
55
56
  - The created artifact.
56
57
  """
58
+ from prefect.context import MissingContextError, get_run_context
59
+
57
60
  client, _ = get_or_create_client(client)
58
61
  task_run_id, flow_run_id = get_task_and_flow_run_ids()
62
+
63
+ try:
64
+ get_run_context()
65
+ except MissingContextError:
66
+ warnings.warn(
67
+ "Artifact creation outside of a flow or task run is deprecated and will be removed in a later version.",
68
+ FutureWarning,
69
+ )
70
+
59
71
  return await client.create_artifact(
60
72
  artifact=ArtifactRequest(
61
73
  type=self.type,
@@ -377,6 +377,10 @@ class DeploymentFlowRunCreate(ActionBaseModel):
377
377
  parameters: Dict[str, Any] = Field(
378
378
  default_factory=dict, description="The parameters for the flow run."
379
379
  )
380
+ enforce_parameter_schema: Optional[bool] = Field(
381
+ default=None,
382
+ description="Whether or not to enforce the parameter schema on this run.",
383
+ )
380
384
  context: Dict[str, Any] = Field(
381
385
  default_factory=dict, description="The context for the flow run."
382
386
  )
@@ -140,6 +140,11 @@ class AssertingEventsClient(EventsClient):
140
140
  cls.last = None
141
141
  cls.all = []
142
142
 
143
+ def pop_events(self) -> List[Event]:
144
+ events = self.events
145
+ self.events = []
146
+ return events
147
+
143
148
  async def _emit(self, event: Event) -> None:
144
149
  self.events.append(event)
145
150
 
@@ -60,6 +60,16 @@ class Resource(Labelled):
60
60
  def name(self) -> Optional[str]:
61
61
  return self.get("prefect.resource.name")
62
62
 
63
+ def prefect_object_id(self, kind: str) -> UUID:
64
+ """Extracts the UUID from an event's resource ID if it's the expected kind
65
+ of prefect resource"""
66
+ prefix = f"{kind}." if not kind.endswith(".") else kind
67
+
68
+ if not self.id.startswith(prefix):
69
+ raise ValueError(f"Resource ID {self.id} does not start with {prefix}")
70
+
71
+ return UUID(self.id[len(prefix) :])
72
+
63
73
 
64
74
  class RelatedResource(Resource):
65
75
  """A Resource with a specific role in an Event"""
@@ -91,9 +91,12 @@ def load_flow_and_flow_run(flow_run_id: UUID) -> Tuple[FlowRun, Flow]:
91
91
 
92
92
  flow_run = client.read_flow_run(flow_run_id)
93
93
  if entrypoint:
94
- flow = load_flow_from_entrypoint(entrypoint)
94
+ # we should not accept a placeholder flow at runtime
95
+ flow = load_flow_from_entrypoint(entrypoint, use_placeholder_flow=False)
95
96
  else:
96
- flow = run_coro_as_sync(load_flow_from_flow_run(flow_run))
97
+ flow = run_coro_as_sync(
98
+ load_flow_from_flow_run(flow_run, use_placeholder_flow=False)
99
+ )
97
100
 
98
101
  return flow_run, flow
99
102
 
@@ -798,7 +798,7 @@ class Flow(Generic[P, R]):
798
798
  cron: Optional[Union[Iterable[str], str]] = None,
799
799
  rrule: Optional[Union[Iterable[str], str]] = None,
800
800
  paused: Optional[bool] = None,
801
- schedules: Optional[List["FlexibleScheduleList"]] = None,
801
+ schedules: Optional["FlexibleScheduleList"] = None,
802
802
  schedule: Optional[SCHEDULE_TYPES] = None,
803
803
  is_schedule_active: Optional[bool] = None,
804
804
  triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
@@ -1704,6 +1704,7 @@ def select_flow(
1704
1704
 
1705
1705
  def load_flow_from_entrypoint(
1706
1706
  entrypoint: str,
1707
+ use_placeholder_flow: bool = True,
1707
1708
  ) -> Flow:
1708
1709
  """
1709
1710
  Extract a flow object from a script at an entrypoint by running all of the code in the file.
@@ -1711,6 +1712,8 @@ def load_flow_from_entrypoint(
1711
1712
  Args:
1712
1713
  entrypoint: a string in the format `<path_to_script>:<flow_func_name>` or a module path
1713
1714
  to a flow function
1715
+ use_placeholder_flow: if True, use a placeholder Flow object if the actual flow object
1716
+ cannot be loaded from the entrypoint (e.g. dependencies are missing)
1714
1717
 
1715
1718
  Returns:
1716
1719
  The flow object from the script
@@ -1737,8 +1740,10 @@ def load_flow_from_entrypoint(
1737
1740
  # drawback of this approach is that we're unable to actually load the
1738
1741
  # function, so we create a placeholder flow that will re-raise this
1739
1742
  # exception when called.
1740
-
1741
- flow = load_placeholder_flow(entrypoint=entrypoint, raises=exc)
1743
+ if use_placeholder_flow:
1744
+ flow = load_placeholder_flow(entrypoint=entrypoint, raises=exc)
1745
+ else:
1746
+ raise
1742
1747
 
1743
1748
  if not isinstance(flow, Flow):
1744
1749
  raise MissingFlowError(
@@ -1856,6 +1861,7 @@ async def load_flow_from_flow_run(
1856
1861
  flow_run: "FlowRun",
1857
1862
  ignore_storage: bool = False,
1858
1863
  storage_base_path: Optional[str] = None,
1864
+ use_placeholder_flow: bool = True,
1859
1865
  ) -> Flow:
1860
1866
  """
1861
1867
  Load a flow from the location/script provided in a deployment's storage document.
@@ -1882,7 +1888,9 @@ async def load_flow_from_flow_run(
1882
1888
  f"Importing flow code from module path {deployment.entrypoint}"
1883
1889
  )
1884
1890
  flow = await run_sync_in_worker_thread(
1885
- load_flow_from_entrypoint, deployment.entrypoint
1891
+ load_flow_from_entrypoint,
1892
+ deployment.entrypoint,
1893
+ use_placeholder_flow=use_placeholder_flow,
1886
1894
  )
1887
1895
  return flow
1888
1896
 
@@ -1924,7 +1932,11 @@ async def load_flow_from_flow_run(
1924
1932
  import_path = relative_path_to_current_platform(deployment.entrypoint)
1925
1933
  run_logger.debug(f"Importing flow code from '{import_path}'")
1926
1934
 
1927
- flow = await run_sync_in_worker_thread(load_flow_from_entrypoint, str(import_path))
1935
+ flow = await run_sync_in_worker_thread(
1936
+ load_flow_from_entrypoint,
1937
+ str(import_path),
1938
+ use_placeholder_flow=use_placeholder_flow,
1939
+ )
1928
1940
 
1929
1941
  return flow
1930
1942
 
@@ -25,7 +25,7 @@ from typing_extensions import ParamSpec, Self
25
25
  import prefect
26
26
  from prefect.blocks.core import Block
27
27
  from prefect.client.utilities import inject_client
28
- from prefect.exceptions import MissingResult, ObjectAlreadyExists
28
+ from prefect.exceptions import MissingResult
29
29
  from prefect.filesystems import (
30
30
  LocalFileSystem,
31
31
  WritableFileSystem,
@@ -64,51 +64,6 @@ R = TypeVar("R")
64
64
  _default_storages: Dict[Tuple[str, str], WritableFileSystem] = {}
65
65
 
66
66
 
67
- async def _get_or_create_default_storage(block_document_slug: str) -> ResultStorage:
68
- """
69
- Generate a default file system for storage.
70
- """
71
- default_storage_name, storage_path = cache_key = (
72
- block_document_slug,
73
- PREFECT_LOCAL_STORAGE_PATH.value(),
74
- )
75
-
76
- async def get_storage() -> WritableFileSystem:
77
- try:
78
- return await Block.load(default_storage_name)
79
- except ValueError as e:
80
- if "Unable to find" not in str(e):
81
- raise e
82
-
83
- block_type_slug, name = default_storage_name.split("/")
84
- if block_type_slug == "local-file-system":
85
- block = LocalFileSystem(basepath=storage_path)
86
- else:
87
- raise ValueError(
88
- "The default storage block does not exist, but it is of type "
89
- f"'{block_type_slug}' which cannot be created implicitly. Please create "
90
- "the block manually."
91
- )
92
-
93
- try:
94
- await block.save(name, overwrite=False)
95
- except ValueError as e:
96
- if "already in use" not in str(e):
97
- raise e
98
- except ObjectAlreadyExists:
99
- # Another client created the block before we reached this line
100
- block = await Block.load(default_storage_name)
101
-
102
- return block
103
-
104
- try:
105
- return _default_storages[cache_key]
106
- except KeyError:
107
- storage = await get_storage()
108
- _default_storages[cache_key] = storage
109
- return storage
110
-
111
-
112
67
  @sync_compatible
113
68
  async def get_default_result_storage() -> ResultStorage:
114
69
  """
@@ -167,9 +167,7 @@ class Runner:
167
167
  self.query_seconds = query_seconds or PREFECT_RUNNER_POLL_FREQUENCY.value()
168
168
  self._prefetch_seconds = prefetch_seconds
169
169
 
170
- self._limiter: Optional[anyio.CapacityLimiter] = anyio.CapacityLimiter(
171
- self.limit
172
- )
170
+ self._limiter: Optional[anyio.CapacityLimiter] = None
173
171
  self._client = get_client()
174
172
  self._submitting_flow_run_ids = set()
175
173
  self._cancelling_flow_run_ids = set()
@@ -1227,6 +1225,8 @@ class Runner:
1227
1225
  self._client = get_client()
1228
1226
  self._tmp_dir.mkdir(parents=True)
1229
1227
 
1228
+ self._limiter = anyio.CapacityLimiter(self.limit)
1229
+
1230
1230
  if not hasattr(self, "_loop") or not self._loop:
1231
1231
  self._loop = asyncio.get_event_loop()
1232
1232
 
@@ -481,18 +481,6 @@ PREFECT_HOME = Setting(
481
481
  directory may be created automatically when required.
482
482
  """
483
483
 
484
- PREFECT_EXTRA_ENTRYPOINTS = Setting(
485
- str,
486
- default="",
487
- )
488
- """
489
- Modules for Prefect to import when Prefect is imported.
490
-
491
- Values should be separated by commas, e.g. `my_module,my_other_module`.
492
- Objects within modules may be specified by a ':' partition, e.g. `my_module:my_object`.
493
- If a callable object is provided, it will be called with no arguments on import.
494
- """
495
-
496
484
  PREFECT_DEBUG_MODE = Setting(
497
485
  bool,
498
486
  default=False,
@@ -1395,11 +1383,6 @@ PREFECT_WORKER_WEBSERVER_PORT = Setting(
1395
1383
  The port the worker's webserver should bind to.
1396
1384
  """
1397
1385
 
1398
- PREFECT_API_SERVICES_TASK_SCHEDULING_ENABLED = Setting(bool, default=True)
1399
- """
1400
- Whether or not to start the task scheduling service in the server application.
1401
- """
1402
-
1403
1386
  PREFECT_TASK_SCHEDULING_DEFAULT_STORAGE_BLOCK = Setting(Optional[str], default=None)
1404
1387
  """The `block-type/block-document` slug of a block to use as the default storage
1405
1388
  for autonomous tasks."""
@@ -1438,11 +1421,6 @@ a task worker should move a task from PENDING to RUNNING very quickly, so runs s
1438
1421
  PENDING for a while is a sign that the task worker may have crashed.
1439
1422
  """
1440
1423
 
1441
- PREFECT_EXPERIMENTAL_DISABLE_SYNC_COMPAT = Setting(bool, default=False)
1442
- """
1443
- Whether or not to disable the sync_compatible decorator utility.
1444
- """
1445
-
1446
1424
  PREFECT_EXPERIMENTAL_ENABLE_SCHEDULE_CONCURRENCY = Setting(bool, default=False)
1447
1425
 
1448
1426
  # Defaults -----------------------------------------------------------------------------
@@ -5,6 +5,7 @@ import time
5
5
  from asyncio import CancelledError
6
6
  from contextlib import ExitStack, contextmanager
7
7
  from dataclasses import dataclass, field
8
+ from functools import wraps
8
9
  from textwrap import dedent
9
10
  from typing import (
10
11
  Any,
@@ -53,6 +54,7 @@ from prefect.records.result_store import ResultFactoryStore
53
54
  from prefect.results import BaseResult, ResultFactory, _format_user_supplied_storage_key
54
55
  from prefect.settings import (
55
56
  PREFECT_DEBUG_MODE,
57
+ PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION,
56
58
  PREFECT_TASKS_REFRESH_CACHE,
57
59
  )
58
60
  from prefect.states import (
@@ -124,8 +126,7 @@ class TaskRunEngine(Generic[P, R]):
124
126
  raise ValueError("Task run is not set")
125
127
  return self.task_run.state
126
128
 
127
- @property
128
- def can_retry(self) -> bool:
129
+ def can_retry(self, exc: Exception) -> bool:
129
130
  retry_condition: Optional[
130
131
  Callable[[Task[P, Coroutine[Any, Any, R]], TaskRun, State], bool]
131
132
  ] = self.task.retry_condition_fn
@@ -136,9 +137,19 @@ class TaskRunEngine(Generic[P, R]):
136
137
  f"Running `retry_condition_fn` check {retry_condition!r} for task"
137
138
  f" {self.task.name!r}"
138
139
  )
139
- return not retry_condition or retry_condition(
140
- self.task, self.task_run, self.state
140
+ state = Failed(
141
+ data=exc,
142
+ message=f"Task run encountered unexpected exception: {repr(exc)}",
141
143
  )
144
+ if inspect.iscoroutinefunction(retry_condition):
145
+ should_retry = run_coro_as_sync(
146
+ retry_condition(self.task, self.task_run, state)
147
+ )
148
+ elif inspect.isfunction(retry_condition):
149
+ should_retry = retry_condition(self.task, self.task_run, state)
150
+ else:
151
+ should_retry = not retry_condition
152
+ return should_retry
142
153
  except Exception:
143
154
  self.logger.error(
144
155
  (
@@ -269,6 +280,17 @@ class TaskRunEngine(Generic[P, R]):
269
280
  return
270
281
 
271
282
  new_state = Running()
283
+
284
+ if PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
285
+ self.task_run.start_time = new_state.timestamp
286
+ self.task_run.run_count += 1
287
+
288
+ flow_run_context = FlowRunContext.get()
289
+ if flow_run_context:
290
+ # Carry forward any task run information from the flow run
291
+ flow_run = flow_run_context.flow_run
292
+ self.task_run.flow_run_run_count = flow_run.run_count
293
+
272
294
  state = self.set_state(new_state)
273
295
 
274
296
  # TODO: this is temporary until the API stops rejecting state transitions
@@ -298,24 +320,37 @@ class TaskRunEngine(Generic[P, R]):
298
320
  last_state = self.state
299
321
  if not self.task_run:
300
322
  raise ValueError("Task run is not set")
301
- try:
302
- new_state = propose_state_sync(
303
- self.client, state, task_run_id=self.task_run.id, force=force
304
- )
305
- except Pause as exc:
306
- # We shouldn't get a pause signal without a state, but if this happens,
307
- # just use a Paused state to assume an in-process pause.
308
- new_state = exc.state if exc.state else Paused()
309
- if new_state.state_details.pause_reschedule:
310
- # If we're being asked to pause and reschedule, we should exit the
311
- # task and expect to be resumed later.
312
- raise
313
323
 
314
- # currently this is a hack to keep a reference to the state object
315
- # that has an in-memory result attached to it; using the API state
324
+ if PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
325
+ self.task_run.state = new_state = state
326
+
327
+ # Ensure that the state_details are populated with the current run IDs
328
+ new_state.state_details.task_run_id = self.task_run.id
329
+ new_state.state_details.flow_run_id = self.task_run.flow_run_id
330
+
331
+ # Predictively update the de-normalized task_run.state_* attributes
332
+ self.task_run.state_id = new_state.id
333
+ self.task_run.state_type = new_state.type
334
+ self.task_run.state_name = new_state.name
335
+ else:
336
+ try:
337
+ new_state = propose_state_sync(
338
+ self.client, state, task_run_id=self.task_run.id, force=force
339
+ )
340
+ except Pause as exc:
341
+ # We shouldn't get a pause signal without a state, but if this happens,
342
+ # just use a Paused state to assume an in-process pause.
343
+ new_state = exc.state if exc.state else Paused()
344
+ if new_state.state_details.pause_reschedule:
345
+ # If we're being asked to pause and reschedule, we should exit the
346
+ # task and expect to be resumed later.
347
+ raise
348
+
349
+ # currently this is a hack to keep a reference to the state object
350
+ # that has an in-memory result attached to it; using the API state
351
+ # could result in losing that reference
352
+ self.task_run.state = new_state
316
353
 
317
- # could result in losing that reference
318
- self.task_run.state = new_state
319
354
  # emit a state change event
320
355
  self._last_event = emit_task_run_state_change_event(
321
356
  task_run=self.task_run,
@@ -323,6 +358,7 @@ class TaskRunEngine(Generic[P, R]):
323
358
  validated_state=self.task_run.state,
324
359
  follows=self._last_event,
325
360
  )
361
+
326
362
  return new_state
327
363
 
328
364
  def result(self, raise_on_failure: bool = True) -> "Union[R, State, None]":
@@ -367,11 +403,19 @@ class TaskRunEngine(Generic[P, R]):
367
403
  )
368
404
  transaction.stage(
369
405
  terminal_state.data,
370
- on_rollback_hooks=self.task.on_rollback_hooks,
371
- on_commit_hooks=self.task.on_commit_hooks,
406
+ on_rollback_hooks=[
407
+ _with_transaction_hook_logging(hook, "rollback", self.logger)
408
+ for hook in self.task.on_rollback_hooks
409
+ ],
410
+ on_commit_hooks=[
411
+ _with_transaction_hook_logging(hook, "commit", self.logger)
412
+ for hook in self.task.on_commit_hooks
413
+ ],
372
414
  )
373
415
  if transaction.is_committed():
374
416
  terminal_state.name = "Cached"
417
+
418
+ self.record_terminal_state_timing(terminal_state)
375
419
  self.set_state(terminal_state)
376
420
  self._return_value = result
377
421
  return result
@@ -383,7 +427,7 @@ class TaskRunEngine(Generic[P, R]):
383
427
  - If the task has a retry delay, place in AwaitingRetry state with a delayed scheduled time.
384
428
  - If the task has no retries left, or the retry condition is not met, return False.
385
429
  """
386
- if self.retries < self.task.retries and self.can_retry:
430
+ if self.retries < self.task.retries and self.can_retry(exc):
387
431
  if self.task.retry_delay_seconds:
388
432
  delay = (
389
433
  self.task.retry_delay_seconds[
@@ -398,6 +442,8 @@ class TaskRunEngine(Generic[P, R]):
398
442
  else:
399
443
  delay = None
400
444
  new_state = Retrying()
445
+ if PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
446
+ self.task_run.run_count += 1
401
447
 
402
448
  self.logger.info(
403
449
  "Task run failed with exception: %r - " "Retry %s/%s will start %s",
@@ -432,6 +478,7 @@ class TaskRunEngine(Generic[P, R]):
432
478
  result_factory=getattr(context, "result_factory", None),
433
479
  )
434
480
  )
481
+ self.record_terminal_state_timing(state)
435
482
  self.set_state(state)
436
483
  self._raised = exc
437
484
 
@@ -454,9 +501,20 @@ class TaskRunEngine(Generic[P, R]):
454
501
  state = run_coro_as_sync(exception_to_crashed_state(exc))
455
502
  self.logger.error(f"Crash detected! {state.message}")
456
503
  self.logger.debug("Crash details:", exc_info=exc)
504
+ self.record_terminal_state_timing(state)
457
505
  self.set_state(state, force=True)
458
506
  self._raised = exc
459
507
 
508
+ def record_terminal_state_timing(self, state: State) -> None:
509
+ if PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
510
+ if self.task_run.start_time and not self.task_run.end_time:
511
+ self.task_run.end_time = state.timestamp
512
+
513
+ if self.task_run.state.is_running():
514
+ self.task_run.total_run_time += (
515
+ state.timestamp - self.task_run.state.timestamp
516
+ )
517
+
460
518
  @contextmanager
461
519
  def setup_run_context(self, client: Optional[SyncPrefectClient] = None):
462
520
  from prefect.utilities.engine import (
@@ -469,7 +527,8 @@ class TaskRunEngine(Generic[P, R]):
469
527
  if not self.task_run:
470
528
  raise ValueError("Task run is not set")
471
529
 
472
- self.task_run = client.read_task_run(self.task_run.id)
530
+ if not PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
531
+ self.task_run = client.read_task_run(self.task_run.id)
473
532
  with ExitStack() as stack:
474
533
  if log_prints := should_log_prints(self.task):
475
534
  stack.enter_context(patch_print())
@@ -483,23 +542,24 @@ class TaskRunEngine(Generic[P, R]):
483
542
  client=client,
484
543
  )
485
544
  )
486
- # set the logger to the task run logger
545
+
487
546
  self.logger = task_run_logger(task_run=self.task_run, task=self.task) # type: ignore
488
547
 
489
- # update the task run name if necessary
490
- if not self._task_name_set and self.task.task_run_name:
491
- task_run_name = _resolve_custom_task_run_name(
492
- task=self.task, parameters=self.parameters
493
- )
494
- self.client.set_task_run_name(
495
- task_run_id=self.task_run.id, name=task_run_name
496
- )
497
- self.logger.extra["task_run_name"] = task_run_name
498
- self.logger.debug(
499
- f"Renamed task run {self.task_run.name!r} to {task_run_name!r}"
500
- )
501
- self.task_run.name = task_run_name
502
- self._task_name_set = True
548
+ if not PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
549
+ # update the task run name if necessary
550
+ if not self._task_name_set and self.task.task_run_name:
551
+ task_run_name = _resolve_custom_task_run_name(
552
+ task=self.task, parameters=self.parameters
553
+ )
554
+ self.client.set_task_run_name(
555
+ task_run_id=self.task_run.id, name=task_run_name
556
+ )
557
+ self.logger.extra["task_run_name"] = task_run_name
558
+ self.logger.debug(
559
+ f"Renamed task run {self.task_run.name!r} to {task_run_name!r}"
560
+ )
561
+ self.task_run.name = task_run_name
562
+ self._task_name_set = True
503
563
  yield
504
564
 
505
565
  @contextmanager
@@ -511,22 +571,52 @@ class TaskRunEngine(Generic[P, R]):
511
571
  """
512
572
  Enters a client context and creates a task run if needed.
513
573
  """
574
+
514
575
  with hydrated_context(self.context):
515
576
  with ClientContext.get_or_create() as client_ctx:
516
577
  self._client = client_ctx.sync_client
517
578
  self._is_started = True
518
579
  try:
519
- if not self.task_run:
520
- self.task_run = run_coro_as_sync(
521
- self.task.create_run(
522
- id=task_run_id,
523
- parameters=self.parameters,
524
- flow_run_context=FlowRunContext.get(),
525
- parent_task_run_context=TaskRunContext.get(),
526
- wait_for=self.wait_for,
527
- extra_task_inputs=dependencies,
580
+ if PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
581
+ from prefect.utilities.engine import (
582
+ _resolve_custom_task_run_name,
583
+ )
584
+
585
+ task_run_name = (
586
+ _resolve_custom_task_run_name(
587
+ task=self.task, parameters=self.parameters
528
588
  )
589
+ if self.task.task_run_name
590
+ else None
529
591
  )
592
+
593
+ if self.task_run and task_run_name:
594
+ self.task_run.name = task_run_name
595
+
596
+ if not self.task_run:
597
+ self.task_run = run_coro_as_sync(
598
+ self.task.create_local_run(
599
+ id=task_run_id,
600
+ parameters=self.parameters,
601
+ flow_run_context=FlowRunContext.get(),
602
+ parent_task_run_context=TaskRunContext.get(),
603
+ wait_for=self.wait_for,
604
+ extra_task_inputs=dependencies,
605
+ task_run_name=task_run_name,
606
+ )
607
+ )
608
+ else:
609
+ if not self.task_run:
610
+ self.task_run = run_coro_as_sync(
611
+ self.task.create_run(
612
+ id=task_run_id,
613
+ parameters=self.parameters,
614
+ flow_run_context=FlowRunContext.get(),
615
+ parent_task_run_context=TaskRunContext.get(),
616
+ wait_for=self.wait_for,
617
+ extra_task_inputs=dependencies,
618
+ )
619
+ )
530
620
  # Emit an event to capture that the task run was in the `PENDING` state.
531
621
  self._last_event = emit_task_run_state_change_event(
532
622
  task_run=self.task_run,
@@ -916,3 +1006,28 @@ def run_task(
916
1006
  return run_task_async(**kwargs)
917
1007
  else:
918
1008
  return run_task_sync(**kwargs)
1009
+
1010
+
1011
+ def _with_transaction_hook_logging(
1012
+ hook: Callable[[Transaction], None],
1013
+ hook_type: Literal["rollback", "commit"],
1014
+ logger: logging.Logger,
1015
+ ) -> Callable[[Transaction], None]:
1016
+ @wraps(hook)
1017
+ def _hook(txn: Transaction) -> None:
1018
+ hook_name = _get_hook_name(hook)
1019
+ logger.info(f"Running {hook_type} hook {hook_name!r}")
1020
+
1021
+ try:
1022
+ hook(txn)
1023
+ except Exception as exc:
1024
+ logger.error(
1025
+ f"An error was encountered while running {hook_type} hook {hook_name!r}",
1026
+ )
1027
+ raise exc
1028
+ else:
1029
+ logger.info(
1030
+ f"{hook_type.capitalize()} hook {hook_name!r} finished running successfully"
1031
+ )
1032
+
1033
+ return _hook