prefect-client 3.0.0rc11__tar.gz → 3.0.0rc12__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.
- {prefect-client-3.0.0rc11/src/prefect_client.egg-info → prefect-client-3.0.0rc12}/PKG-INFO +1 -1
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/requirements-client.txt +1 -1
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/requirements-dev.txt +0 -1
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/services.py +9 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/artifacts.py +12 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/schemas/actions.py +4 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/schemas/events.py +10 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/flow_engine.py +5 -2
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/flows.py +17 -5
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/results.py +1 -46
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runner/runner.py +3 -3
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/settings.py +0 -17
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/task_engine.py +158 -48
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/tasks.py +164 -17
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/transactions.py +2 -31
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/asyncutils.py +12 -9
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12/src/prefect_client.egg-info}/PKG-INFO +1 -1
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect_client.egg-info/requires.txt +1 -1
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/LICENSE +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/MANIFEST.in +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/README.md +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/requirements.txt +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/setup.cfg +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/setup.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/.prefectignore +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/_logging.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/compatibility/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/compatibility/deprecated.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/compatibility/experimental.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/compatibility/migration.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/api.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/calls.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/cancellation.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/event_loop.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/inspection.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/primitives.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/threads.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/waiters.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/integrations.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pydantic/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pydantic/annotations/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pydantic/annotations/pendulum.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pydantic/schemas.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pydantic/v1_schema.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pydantic/v2_schema.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pydantic/v2_validated_func.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/pytz.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/retries.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/schemas/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/schemas/bases.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/schemas/fields.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/schemas/serializers.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/schemas/validators.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_version.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/agent.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/automations.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/abstract.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/core.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/fields.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/notifications.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/redis.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/system.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/blocks/webhook.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/cache_policies.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/base.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/cloud.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/collections.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/constants.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/orchestration.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/schemas/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/schemas/filters.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/schemas/objects.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/schemas/responses.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/schemas/schedules.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/schemas/sorting.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/subscriptions.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/types/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/types/flexible_schedule_list.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/client/utilities.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/concurrency/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/concurrency/asyncio.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/concurrency/events.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/concurrency/services.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/concurrency/sync.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/context.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/base.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/deployments.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/flow_runs.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/runner.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/schedules.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/steps/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/steps/core.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/steps/pull.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/deployments/steps/utility.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/docker/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/docker/docker_image.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/engine.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/actions.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/cli/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/cli/automations.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/clients.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/filters.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/related.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/schemas/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/schemas/automations.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/schemas/deployment_triggers.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/schemas/labelling.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/utilities.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/events/worker.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/exceptions.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/filesystems.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/flow_runs.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/futures.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/infrastructure/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/infrastructure/base.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/infrastructure/provisioners/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/infrastructure/provisioners/cloud_run.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/infrastructure/provisioners/container_instance.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/infrastructure/provisioners/ecs.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/infrastructure/provisioners/modal.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/input/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/input/actions.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/input/run_input.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/configuration.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/filters.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/formatters.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/handlers.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/highlighters.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/loggers.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/logging/logging.yml +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/main.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/manifests.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/plugins.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/profiles.toml +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/py.typed +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/records/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/records/result_store.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/records/store.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runner/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runner/server.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runner/storage.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runner/submit.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runner/utils.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runtime/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runtime/deployment.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runtime/flow_run.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/runtime/task_run.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/serializers.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/server/api/collections_data/views/aggregate-worker-metadata.json +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/server/api/static/prefect-logo-mark-gradient.png +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/states.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/task_runners.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/task_runs.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/task_worker.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/types/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/types/entrypoint.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/annotations.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/callables.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/collections.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/compat.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/context.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/dispatch.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/dockerutils.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/engine.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/filesystem.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/hashing.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/importtools.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/math.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/names.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/processutils.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/pydantic.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/render_swagger.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/schema_tools/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/schema_tools/hydration.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/schema_tools/validation.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/services.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/slugify.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/templating.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/text.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/timeout.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/urls.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/utilities/visualization.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/variables.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/workers/__init__.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/workers/base.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/workers/block.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/workers/cloud.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/workers/process.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/workers/server.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/workers/utilities.py +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect_client.egg-info/SOURCES.txt +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect_client.egg-info/dependency_links.txt +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect_client.egg-info/top_level.txt +0 -0
- {prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/versioneer.py +0 -0
{prefect-client-3.0.0rc11 → prefect-client-3.0.0rc12}/src/prefect/_internal/concurrency/services.py
RENAMED
@@ -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
|
)
|
@@ -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
|
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(
|
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[
|
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
|
-
|
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,
|
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(
|
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
|
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] =
|
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,
|
@@ -1438,11 +1426,6 @@ a task worker should move a task from PENDING to RUNNING very quickly, so runs s
|
|
1438
1426
|
PENDING for a while is a sign that the task worker may have crashed.
|
1439
1427
|
"""
|
1440
1428
|
|
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
1429
|
PREFECT_EXPERIMENTAL_ENABLE_SCHEDULE_CONCURRENCY = Setting(bool, default=False)
|
1447
1430
|
|
1448
1431
|
# 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
|
-
|
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
|
-
|
140
|
-
|
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
|
-
|
315
|
-
|
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=
|
371
|
-
|
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
|
-
|
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
|
-
|
545
|
+
|
487
546
|
self.logger = task_run_logger(task_run=self.task_run, task=self.task) # type: ignore
|
488
547
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
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,47 @@ 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
580
|
if not self.task_run:
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
581
|
+
if PREFECT_EXPERIMENTAL_ENABLE_CLIENT_SIDE_TASK_ORCHESTRATION:
|
582
|
+
# TODO - this maybe should be a method on Task?
|
583
|
+
from prefect.utilities.engine import (
|
584
|
+
_resolve_custom_task_run_name,
|
585
|
+
)
|
586
|
+
|
587
|
+
task_run_name = None
|
588
|
+
if not self._task_name_set and self.task.task_run_name:
|
589
|
+
task_run_name = _resolve_custom_task_run_name(
|
590
|
+
task=self.task, parameters=self.parameters
|
591
|
+
)
|
592
|
+
|
593
|
+
self.task_run = run_coro_as_sync(
|
594
|
+
self.task.create_local_run(
|
595
|
+
id=task_run_id,
|
596
|
+
parameters=self.parameters,
|
597
|
+
flow_run_context=FlowRunContext.get(),
|
598
|
+
parent_task_run_context=TaskRunContext.get(),
|
599
|
+
wait_for=self.wait_for,
|
600
|
+
extra_task_inputs=dependencies,
|
601
|
+
task_run_name=task_run_name,
|
602
|
+
)
|
603
|
+
)
|
604
|
+
else:
|
605
|
+
self.task_run = run_coro_as_sync(
|
606
|
+
self.task.create_run(
|
607
|
+
id=task_run_id,
|
608
|
+
parameters=self.parameters,
|
609
|
+
flow_run_context=FlowRunContext.get(),
|
610
|
+
parent_task_run_context=TaskRunContext.get(),
|
611
|
+
wait_for=self.wait_for,
|
612
|
+
extra_task_inputs=dependencies,
|
613
|
+
)
|
528
614
|
)
|
529
|
-
)
|
530
615
|
# Emit an event to capture that the task run was in the `PENDING` state.
|
531
616
|
self._last_event = emit_task_run_state_change_event(
|
532
617
|
task_run=self.task_run,
|
@@ -916,3 +1001,28 @@ def run_task(
|
|
916
1001
|
return run_task_async(**kwargs)
|
917
1002
|
else:
|
918
1003
|
return run_task_sync(**kwargs)
|
1004
|
+
|
1005
|
+
|
1006
|
+
def _with_transaction_hook_logging(
|
1007
|
+
hook: Callable[[Transaction], None],
|
1008
|
+
hook_type: Literal["rollback", "commit"],
|
1009
|
+
logger: logging.Logger,
|
1010
|
+
) -> Callable[[Transaction], None]:
|
1011
|
+
@wraps(hook)
|
1012
|
+
def _hook(txn: Transaction) -> None:
|
1013
|
+
hook_name = _get_hook_name(hook)
|
1014
|
+
logger.info(f"Running {hook_type} hook {hook_name!r}")
|
1015
|
+
|
1016
|
+
try:
|
1017
|
+
hook(txn)
|
1018
|
+
except Exception as exc:
|
1019
|
+
logger.error(
|
1020
|
+
f"An error was encountered while running {hook_type} hook {hook_name!r}",
|
1021
|
+
)
|
1022
|
+
raise exc
|
1023
|
+
else:
|
1024
|
+
logger.info(
|
1025
|
+
f"{hook_type.capitalize()} hook {hook_name!r} finished running successfully"
|
1026
|
+
)
|
1027
|
+
|
1028
|
+
return _hook
|