prefect-client 3.2.5__tar.gz → 3.2.7__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.2.5 → prefect_client-3.2.7}/PKG-INFO +1 -1
- prefect_client-3.2.7/src/prefect/_build_info.py +5 -0
- prefect_client-3.2.7/src/prefect/_experimental/bundles.py +143 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/__init__.py +21 -2
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/engine.py +63 -29
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/schemas/automations.py +1 -1
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/flow_engine.py +2 -32
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/flows.py +8 -2
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/configuration.py +3 -1
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runner/runner.py +142 -10
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/server.py +9 -2
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/base.py +18 -3
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/root.py +5 -1
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/api.py +7 -1
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/database.py +14 -0
- prefect_client-3.2.5/src/prefect/_build_info.py +0 -5
- {prefect_client-3.2.5 → prefect_client-3.2.7}/.gitignore +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/LICENSE +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/README.md +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/pyproject.toml +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/.prefectignore +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/__main__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_experimental/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_experimental/lineage.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_experimental/sla/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_experimental/sla/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_experimental/sla/objects.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/_logging.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/compatibility/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/compatibility/async_dispatch.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/compatibility/deprecated.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/compatibility/migration.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/api.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/calls.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/cancellation.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/event_loop.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/inspection.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/primitives.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/services.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/threads.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/concurrency/waiters.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/integrations.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pydantic/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pydantic/annotations/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pydantic/annotations/pendulum.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pydantic/schemas.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pydantic/v1_schema.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pydantic/v2_schema.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pydantic/v2_validated_func.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/pytz.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/retries.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/schemas/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/schemas/bases.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/schemas/fields.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/schemas/serializers.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_internal/schemas/validators.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_result_records.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_vendor/croniter/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/_vendor/croniter/croniter.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/agent.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/artifacts.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/automations.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/abstract.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/core.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/fields.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/notifications.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/redis.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/system.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/blocks/webhook.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/cache_policies.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/base.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/cloud.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/collections.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/constants.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_artifacts/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_artifacts/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_automations/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_automations/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_blocks_documents/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_blocks_schemas/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_blocks_types/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_blocks_types/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_concurrency_limits/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_concurrency_limits/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_deployments/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_deployments/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_flow_runs/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_flow_runs/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_flows/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_flows/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_logs/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_logs/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_variables/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_variables/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_work_pools/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/_work_pools/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/base.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/orchestration/routes.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/schemas/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/schemas/actions.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/schemas/filters.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/schemas/objects.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/schemas/responses.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/schemas/schedules.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/schemas/sorting.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/subscriptions.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/types/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/types/flexible_schedule_list.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/client/utilities.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/_asyncio.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/_events.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/asyncio.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/context.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/services.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/sync.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/v1/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/v1/_asyncio.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/v1/_events.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/v1/asyncio.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/v1/context.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/v1/services.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/concurrency/v1/sync.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/context.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/base.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/deployments.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/flow_runs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/runner.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/schedules.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/steps/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/steps/core.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/steps/pull.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/deployments/steps/utility.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/docker/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/docker/docker_image.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/actions.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/cli/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/cli/automations.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/clients.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/filters.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/related.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/schemas/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/schemas/deployment_triggers.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/schemas/events.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/schemas/labelling.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/utilities.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/events/worker.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/exceptions.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/filesystems.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/flow_runs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/futures.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/base.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/provisioners/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/provisioners/cloud_run.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/provisioners/coiled.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/provisioners/container_instance.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/provisioners/ecs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/infrastructure/provisioners/modal.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/input/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/input/actions.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/input/run_input.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/locking/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/locking/filesystem.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/locking/memory.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/locking/protocol.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/filters.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/formatters.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/handlers.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/highlighters.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/loggers.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/logging/logging.yml +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/main.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/plugins.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/py.typed +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/results.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runner/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runner/server.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runner/storage.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runner/submit.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runner/utils.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runtime/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runtime/deployment.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runtime/flow_run.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/runtime/task_run.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/schedules.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/serializers.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/admin.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/artifacts.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/automations.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/block_capabilities.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/block_documents.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/block_schemas.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/block_types.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/clients.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/collections.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/collections_data/views/aggregate-worker-metadata.json +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/concurrency_limits.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/concurrency_limits_v2.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/csrf_token.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/dependencies.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/deployments.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/events.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/flow_run_notification_policies.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/flow_run_states.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/flow_runs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/flows.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/logs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/middleware.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/root.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/run_history.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/saved_searches.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/static/prefect-logo-mark-gradient.png +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/task_run_states.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/task_runs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/task_workers.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/templates.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/ui/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/ui/flow_runs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/ui/flows.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/ui/schemas.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/ui/task_runs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/validation.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/variables.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/work_queues.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/server/api/workers.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/constants.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/context.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/legacy.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/api.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/cli.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/client.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/cloud.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/deployments.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/experiments.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/flows.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/internal.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/logging.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/results.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/runner.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/deployments.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/ephemeral.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/events.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/flow_run_graph.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/root.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/services.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/tasks.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/server/ui.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/tasks.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/testing.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/models/worker.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/profiles.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/profiles.toml +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/settings/sources.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/states.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/task_engine.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/task_runners.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/task_runs.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/task_worker.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/tasks.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/telemetry/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/telemetry/bootstrap.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/telemetry/instrumentation.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/telemetry/logging.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/telemetry/processors.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/telemetry/run_telemetry.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/telemetry/services.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/transactions.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/types/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/types/_datetime.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/types/entrypoint.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/_deprecated.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/_engine.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/_git.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/annotations.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/asyncutils.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/callables.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/collections.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/compat.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/context.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/dispatch.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/dockerutils.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/engine.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/filesystem.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/generics.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/hashing.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/importtools.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/math.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/names.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/processutils.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/pydantic.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/render_swagger.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/schema_tools/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/schema_tools/hydration.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/schema_tools/validation.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/services.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/slugify.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/templating.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/text.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/timeout.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/urls.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/utilities/visualization.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/variables.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/workers/__init__.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/workers/base.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/workers/block.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/workers/cloud.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/workers/process.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/workers/server.py +0 -0
- {prefect_client-3.2.5 → prefect_client-3.2.7}/src/prefect/workers/utilities.py +0 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import asyncio
|
4
|
+
import base64
|
5
|
+
import gzip
|
6
|
+
import multiprocessing
|
7
|
+
import multiprocessing.context
|
8
|
+
import os
|
9
|
+
from typing import Any, TypedDict
|
10
|
+
|
11
|
+
import cloudpickle
|
12
|
+
|
13
|
+
from prefect.client.schemas.objects import FlowRun
|
14
|
+
from prefect.context import SettingsContext, get_settings_context, serialize_context
|
15
|
+
from prefect.engine import handle_engine_signals
|
16
|
+
from prefect.flow_engine import run_flow
|
17
|
+
from prefect.flows import Flow
|
18
|
+
from prefect.settings.context import get_current_settings
|
19
|
+
from prefect.settings.models.root import Settings
|
20
|
+
|
21
|
+
|
22
|
+
class SerializedBundle(TypedDict):
|
23
|
+
"""
|
24
|
+
A serialized bundle is a serialized function, context, and flow run that can be
|
25
|
+
easily transported for later execution.
|
26
|
+
"""
|
27
|
+
|
28
|
+
function: str
|
29
|
+
context: str
|
30
|
+
flow_run: dict[str, Any]
|
31
|
+
|
32
|
+
|
33
|
+
def _serialize_bundle_object(obj: Any) -> str:
|
34
|
+
"""
|
35
|
+
Serializes an object to a string.
|
36
|
+
"""
|
37
|
+
return base64.b64encode(gzip.compress(cloudpickle.dumps(obj))).decode()
|
38
|
+
|
39
|
+
|
40
|
+
def _deserialize_bundle_object(serialized_obj: str) -> Any:
|
41
|
+
"""
|
42
|
+
Deserializes an object from a string.
|
43
|
+
"""
|
44
|
+
return cloudpickle.loads(gzip.decompress(base64.b64decode(serialized_obj)))
|
45
|
+
|
46
|
+
|
47
|
+
def create_bundle_for_flow_run(
|
48
|
+
flow: Flow[Any, Any],
|
49
|
+
flow_run: FlowRun,
|
50
|
+
context: dict[str, Any] | None = None,
|
51
|
+
) -> SerializedBundle:
|
52
|
+
"""
|
53
|
+
Creates a bundle for a flow run.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
flow: The flow to bundle.
|
57
|
+
flow_run: The flow run to bundle.
|
58
|
+
context: The context to use when running the flow.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
A serialized bundle.
|
62
|
+
"""
|
63
|
+
context = context or serialize_context()
|
64
|
+
|
65
|
+
return {
|
66
|
+
"function": _serialize_bundle_object(flow),
|
67
|
+
"context": _serialize_bundle_object(context),
|
68
|
+
"flow_run": flow_run.model_dump(mode="json"),
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
def extract_flow_from_bundle(bundle: SerializedBundle) -> Flow[Any, Any]:
|
73
|
+
"""
|
74
|
+
Extracts a flow from a bundle.
|
75
|
+
"""
|
76
|
+
return _deserialize_bundle_object(bundle["function"])
|
77
|
+
|
78
|
+
|
79
|
+
def _extract_and_run_flow(
|
80
|
+
bundle: SerializedBundle, env: dict[str, Any] | None = None
|
81
|
+
) -> None:
|
82
|
+
"""
|
83
|
+
Extracts a flow from a bundle and runs it.
|
84
|
+
|
85
|
+
Designed to be run in a subprocess.
|
86
|
+
|
87
|
+
Args:
|
88
|
+
bundle: The bundle to extract and run.
|
89
|
+
env: The environment to use when running the flow.
|
90
|
+
"""
|
91
|
+
|
92
|
+
os.environ.update(env or {})
|
93
|
+
# TODO: make this a thing we can pass directly to the engine
|
94
|
+
os.environ["PREFECT__ENABLE_CANCELLATION_AND_CRASHED_HOOKS"] = "false"
|
95
|
+
settings_context = get_settings_context()
|
96
|
+
|
97
|
+
flow = _deserialize_bundle_object(bundle["function"])
|
98
|
+
context = _deserialize_bundle_object(bundle["context"])
|
99
|
+
flow_run = FlowRun.model_validate(bundle["flow_run"])
|
100
|
+
|
101
|
+
with SettingsContext(
|
102
|
+
profile=settings_context.profile,
|
103
|
+
settings=Settings(),
|
104
|
+
):
|
105
|
+
with handle_engine_signals(flow_run.id):
|
106
|
+
maybe_coro = run_flow(
|
107
|
+
flow=flow,
|
108
|
+
flow_run=flow_run,
|
109
|
+
context=context,
|
110
|
+
)
|
111
|
+
if asyncio.iscoroutine(maybe_coro):
|
112
|
+
# This is running in a brand new process, so there won't be an existing
|
113
|
+
# event loop.
|
114
|
+
asyncio.run(maybe_coro)
|
115
|
+
|
116
|
+
|
117
|
+
def execute_bundle_in_subprocess(
|
118
|
+
bundle: SerializedBundle,
|
119
|
+
) -> multiprocessing.context.SpawnProcess:
|
120
|
+
"""
|
121
|
+
Executes a bundle in a subprocess.
|
122
|
+
|
123
|
+
Args:
|
124
|
+
bundle: The bundle to execute.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
A multiprocessing.context.SpawnProcess.
|
128
|
+
"""
|
129
|
+
|
130
|
+
ctx = multiprocessing.get_context("spawn")
|
131
|
+
|
132
|
+
process = ctx.Process(
|
133
|
+
target=_extract_and_run_flow,
|
134
|
+
kwargs={
|
135
|
+
"bundle": bundle,
|
136
|
+
"env": get_current_settings().to_environment_variables(exclude_unset=True)
|
137
|
+
| os.environ,
|
138
|
+
},
|
139
|
+
)
|
140
|
+
|
141
|
+
process.start()
|
142
|
+
|
143
|
+
return process
|
@@ -81,6 +81,7 @@ from prefect.client.orchestration._blocks_types.client import (
|
|
81
81
|
|
82
82
|
import prefect
|
83
83
|
import prefect.exceptions
|
84
|
+
from prefect.logging.loggers import get_run_logger
|
84
85
|
import prefect.settings
|
85
86
|
import prefect.states
|
86
87
|
from prefect.client.constants import SERVER_API_VERSION
|
@@ -1182,8 +1183,17 @@ class PrefectClient(
|
|
1182
1183
|
if api_version.major != client_version.major:
|
1183
1184
|
raise RuntimeError(
|
1184
1185
|
f"Found incompatible versions: client: {client_version}, server: {api_version}. "
|
1185
|
-
|
1186
|
+
"Major versions must match."
|
1186
1187
|
)
|
1188
|
+
if api_version < client_version:
|
1189
|
+
warning_message = (
|
1190
|
+
"Your Prefect server is running an older version of Prefect than your client which may result in unexpected behavior. "
|
1191
|
+
f"Please upgrade your Prefect server from version {api_version} to version {client_version} or higher."
|
1192
|
+
)
|
1193
|
+
try:
|
1194
|
+
get_run_logger().warning(warning_message)
|
1195
|
+
except prefect.context.MissingContextError:
|
1196
|
+
self.logger.warning(warning_message)
|
1187
1197
|
|
1188
1198
|
async def __aenter__(self) -> Self:
|
1189
1199
|
"""
|
@@ -1523,8 +1533,17 @@ class SyncPrefectClient(
|
|
1523
1533
|
if api_version.major != client_version.major:
|
1524
1534
|
raise RuntimeError(
|
1525
1535
|
f"Found incompatible versions: client: {client_version}, server: {api_version}. "
|
1526
|
-
|
1536
|
+
"Major versions must match."
|
1527
1537
|
)
|
1538
|
+
if api_version < client_version:
|
1539
|
+
warning_message = (
|
1540
|
+
"Your Prefect server is running an older version of Prefect than your client which may result in unexpected behavior. "
|
1541
|
+
f"Please upgrade your Prefect server from version {api_version} to version {client_version} or higher."
|
1542
|
+
)
|
1543
|
+
try:
|
1544
|
+
get_run_logger().warning(warning_message)
|
1545
|
+
except prefect.context.MissingContextError:
|
1546
|
+
self.logger.warning(warning_message)
|
1528
1547
|
|
1529
1548
|
def set_task_run_name(self, task_run_id: UUID, name: str) -> httpx.Response:
|
1530
1549
|
task_run_data = TaskRunUpdate(name=name)
|
@@ -1,5 +1,8 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import os
|
2
4
|
import sys
|
5
|
+
from contextlib import contextmanager
|
3
6
|
from typing import TYPE_CHECKING, Any, Callable
|
4
7
|
from uuid import UUID
|
5
8
|
|
@@ -18,13 +21,71 @@ from prefect.utilities.asyncutils import (
|
|
18
21
|
if TYPE_CHECKING:
|
19
22
|
import logging
|
20
23
|
|
21
|
-
from prefect.
|
24
|
+
from prefect.client.schemas.objects import FlowRun
|
22
25
|
from prefect.flows import Flow
|
23
26
|
from prefect.logging.loggers import LoggingAdapter
|
24
27
|
|
25
28
|
engine_logger: "logging.Logger" = get_logger("engine")
|
26
29
|
|
27
30
|
|
31
|
+
@contextmanager
|
32
|
+
def handle_engine_signals(flow_run_id: UUID | None = None):
|
33
|
+
"""
|
34
|
+
Handle signals from the orchestrator to abort or pause the flow run or otherwise
|
35
|
+
handle unexpected exceptions.
|
36
|
+
|
37
|
+
This context manager will handle exiting the process depending on the signal received.
|
38
|
+
|
39
|
+
Args:
|
40
|
+
flow_run_id: The ID of the flow run to handle signals for.
|
41
|
+
|
42
|
+
Example:
|
43
|
+
```python
|
44
|
+
from prefect import flow
|
45
|
+
from prefect.engine import handle_engine_signals
|
46
|
+
from prefect.flow_engine import run_flow
|
47
|
+
|
48
|
+
@flow
|
49
|
+
def my_flow():
|
50
|
+
print("Hello, world!")
|
51
|
+
|
52
|
+
with handle_engine_signals():
|
53
|
+
run_flow(my_flow)
|
54
|
+
```
|
55
|
+
"""
|
56
|
+
try:
|
57
|
+
yield
|
58
|
+
except Abort:
|
59
|
+
if flow_run_id:
|
60
|
+
msg = f"Execution of flow run '{flow_run_id}' aborted by orchestrator."
|
61
|
+
else:
|
62
|
+
msg = "Execution aborted by orchestrator."
|
63
|
+
engine_logger.info(msg)
|
64
|
+
exit(0)
|
65
|
+
except Pause:
|
66
|
+
if flow_run_id:
|
67
|
+
msg = f"Execution of flow run '{flow_run_id}' is paused."
|
68
|
+
else:
|
69
|
+
msg = "Execution is paused."
|
70
|
+
engine_logger.info(msg)
|
71
|
+
exit(0)
|
72
|
+
except Exception:
|
73
|
+
if flow_run_id:
|
74
|
+
msg = f"Execution of flow run '{flow_run_id}' exited with unexpected exception"
|
75
|
+
else:
|
76
|
+
msg = "Execution exited with unexpected exception"
|
77
|
+
engine_logger.error(msg, exc_info=True)
|
78
|
+
exit(1)
|
79
|
+
except BaseException:
|
80
|
+
if flow_run_id:
|
81
|
+
msg = f"Execution of flow run '{flow_run_id}' interrupted by base exception"
|
82
|
+
else:
|
83
|
+
msg = "Execution interrupted by base exception"
|
84
|
+
engine_logger.error(msg, exc_info=True)
|
85
|
+
# Let the exit code be determined by the base exception type
|
86
|
+
raise
|
87
|
+
|
88
|
+
|
28
89
|
if __name__ == "__main__":
|
29
90
|
try:
|
30
91
|
flow_run_id: UUID = UUID(
|
@@ -36,7 +97,7 @@ if __name__ == "__main__":
|
|
36
97
|
)
|
37
98
|
exit(1)
|
38
99
|
|
39
|
-
|
100
|
+
with handle_engine_signals(flow_run_id):
|
40
101
|
from prefect.flow_engine import (
|
41
102
|
flow_run_logger,
|
42
103
|
load_flow,
|
@@ -62,32 +123,5 @@ if __name__ == "__main__":
|
|
62
123
|
else:
|
63
124
|
run_flow(flow, flow_run=flow_run, error_logger=run_logger)
|
64
125
|
|
65
|
-
except Abort:
|
66
|
-
engine_logger.info(
|
67
|
-
f"Engine execution of flow run '{flow_run_id}' aborted by orchestrator."
|
68
|
-
)
|
69
|
-
exit(0)
|
70
|
-
except Pause:
|
71
|
-
engine_logger.info(f"Engine execution of flow run '{flow_run_id}' is paused.")
|
72
|
-
exit(0)
|
73
|
-
except Exception:
|
74
|
-
engine_logger.error(
|
75
|
-
(
|
76
|
-
f"Engine execution of flow run '{flow_run_id}' exited with unexpected "
|
77
|
-
"exception"
|
78
|
-
),
|
79
|
-
exc_info=True,
|
80
|
-
)
|
81
|
-
exit(1)
|
82
|
-
except BaseException:
|
83
|
-
engine_logger.error(
|
84
|
-
(
|
85
|
-
f"Engine execution of flow run '{flow_run_id}' interrupted by base "
|
86
|
-
"exception"
|
87
|
-
),
|
88
|
-
exc_info=True,
|
89
|
-
)
|
90
|
-
# Let the exit code be determined by the base exception type
|
91
|
-
raise
|
92
126
|
|
93
127
|
__getattr__: Callable[[str], Any] = getattr_migration(__name__)
|
@@ -84,7 +84,7 @@ class Trigger(PrefectBaseModel, abc.ABC, extra="ignore"): # type: ignore[call-a
|
|
84
84
|
getattr(self, "name", None)
|
85
85
|
or f"Automation for deployment {self._deployment_id}"
|
86
86
|
),
|
87
|
-
description="",
|
87
|
+
description=getattr(self, "description", ""),
|
88
88
|
enabled=getattr(self, "enabled", True),
|
89
89
|
trigger=trigger,
|
90
90
|
actions=self.actions(),
|
@@ -47,6 +47,7 @@ from prefect.context import (
|
|
47
47
|
hydrated_context,
|
48
48
|
serialize_context,
|
49
49
|
)
|
50
|
+
from prefect.engine import handle_engine_signals
|
50
51
|
from prefect.exceptions import (
|
51
52
|
Abort,
|
52
53
|
MissingFlowError,
|
@@ -1592,8 +1593,6 @@ def run_flow_in_subprocess(
|
|
1592
1593
|
"""
|
1593
1594
|
Wrapper function to update environment variables and settings before running the flow.
|
1594
1595
|
"""
|
1595
|
-
engine_logger = logging.getLogger("prefect.engine")
|
1596
|
-
|
1597
1596
|
os.environ.update(env or {})
|
1598
1597
|
settings_context = get_settings_context()
|
1599
1598
|
# Create a new settings context with a new settings object to pick up the updated
|
@@ -1602,41 +1601,12 @@ def run_flow_in_subprocess(
|
|
1602
1601
|
profile=settings_context.profile,
|
1603
1602
|
settings=Settings(),
|
1604
1603
|
):
|
1605
|
-
|
1604
|
+
with handle_engine_signals(getattr(flow_run, "id", None)):
|
1606
1605
|
maybe_coro = run_flow(*args, **kwargs)
|
1607
1606
|
if asyncio.iscoroutine(maybe_coro):
|
1608
1607
|
# This is running in a brand new process, so there won't be an existing
|
1609
1608
|
# event loop.
|
1610
1609
|
asyncio.run(maybe_coro)
|
1611
|
-
except Abort:
|
1612
|
-
if flow_run:
|
1613
|
-
msg = f"Execution of flow run '{flow_run.id}' aborted by orchestrator."
|
1614
|
-
else:
|
1615
|
-
msg = "Execution aborted by orchestrator."
|
1616
|
-
engine_logger.info(msg)
|
1617
|
-
exit(0)
|
1618
|
-
except Pause:
|
1619
|
-
if flow_run:
|
1620
|
-
msg = f"Execution of flow run '{flow_run.id}' is paused."
|
1621
|
-
else:
|
1622
|
-
msg = "Execution is paused."
|
1623
|
-
engine_logger.info(msg)
|
1624
|
-
exit(0)
|
1625
|
-
except Exception:
|
1626
|
-
if flow_run:
|
1627
|
-
msg = f"Execution of flow run '{flow_run.id}' exited with unexpected exception"
|
1628
|
-
else:
|
1629
|
-
msg = "Execution exited with unexpected exception"
|
1630
|
-
engine_logger.error(msg, exc_info=True)
|
1631
|
-
exit(1)
|
1632
|
-
except BaseException:
|
1633
|
-
if flow_run:
|
1634
|
-
msg = f"Execution of flow run '{flow_run.id}' interrupted by base exception"
|
1635
|
-
else:
|
1636
|
-
msg = "Execution interrupted by base exception"
|
1637
|
-
engine_logger.error(msg, exc_info=True)
|
1638
|
-
# Let the exit code be determined by the base exception type
|
1639
|
-
raise
|
1640
1610
|
|
1641
1611
|
ctx = multiprocessing.get_context("spawn")
|
1642
1612
|
|
@@ -2350,9 +2350,15 @@ async def load_flow_from_flow_run(
|
|
2350
2350
|
f"Running {len(deployment.pull_steps)} deployment pull step(s)"
|
2351
2351
|
)
|
2352
2352
|
|
2353
|
-
from prefect.deployments.steps.core import run_steps
|
2353
|
+
from prefect.deployments.steps.core import StepExecutionError, run_steps
|
2354
|
+
|
2355
|
+
try:
|
2356
|
+
output = await run_steps(deployment.pull_steps)
|
2357
|
+
except StepExecutionError as e:
|
2358
|
+
e = e.__cause__ or e
|
2359
|
+
run_logger.error(str(e))
|
2360
|
+
raise
|
2354
2361
|
|
2355
|
-
output = await run_steps(deployment.pull_steps)
|
2356
2362
|
if output.get("directory"):
|
2357
2363
|
run_logger.debug(f"Changing working directory to {output['directory']!r}")
|
2358
2364
|
os.chdir(output["directory"])
|
@@ -38,7 +38,9 @@ def load_logging_config(path: Path) -> dict[str, Any]:
|
|
38
38
|
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
39
39
|
config = yaml.safe_load(
|
40
40
|
# Substitute settings into the template in format $SETTING / ${SETTING}
|
41
|
-
template.substitute(
|
41
|
+
template.substitute(
|
42
|
+
current_settings.to_environment_variables(include_aliases=True)
|
43
|
+
)
|
42
44
|
)
|
43
45
|
|
44
46
|
# Load overrides from the environment
|
@@ -64,9 +64,15 @@ from uuid import UUID, uuid4
|
|
64
64
|
|
65
65
|
import anyio
|
66
66
|
import anyio.abc
|
67
|
+
import anyio.to_thread
|
67
68
|
from cachetools import LRUCache
|
68
69
|
from typing_extensions import Self
|
69
70
|
|
71
|
+
from prefect._experimental.bundles import (
|
72
|
+
SerializedBundle,
|
73
|
+
execute_bundle_in_subprocess,
|
74
|
+
extract_flow_from_bundle,
|
75
|
+
)
|
70
76
|
from prefect._internal.concurrency.api import (
|
71
77
|
create_call,
|
72
78
|
from_async,
|
@@ -135,7 +141,7 @@ __all__ = ["Runner"]
|
|
135
141
|
|
136
142
|
|
137
143
|
class ProcessMapEntry(TypedDict):
|
138
|
-
flow_run: FlowRun
|
144
|
+
flow_run: "FlowRun"
|
139
145
|
pid: int
|
140
146
|
|
141
147
|
|
@@ -221,6 +227,7 @@ class Runner:
|
|
221
227
|
self._scheduled_task_scopes: set[anyio.abc.CancelScope] = set()
|
222
228
|
self._deployment_ids: set[UUID] = set()
|
223
229
|
self._flow_run_process_map: dict[UUID, ProcessMapEntry] = dict()
|
230
|
+
self._flow_run_bundle_map: dict[UUID, SerializedBundle] = dict()
|
224
231
|
|
225
232
|
self._tmp_dir: Path = (
|
226
233
|
Path(tempfile.gettempdir()) / "runner_storage" / str(uuid4())
|
@@ -508,7 +515,7 @@ class Runner:
|
|
508
515
|
return asyncio.run_coroutine_threadsafe(func(*args, **kwargs), self._loop)
|
509
516
|
|
510
517
|
async def cancel_all(self) -> None:
|
511
|
-
runs_to_cancel: list[FlowRun] = []
|
518
|
+
runs_to_cancel: list["FlowRun"] = []
|
512
519
|
|
513
520
|
# done to avoid dictionary size changing during iteration
|
514
521
|
for info in self._flow_run_process_map.values():
|
@@ -602,7 +609,120 @@ class Runner:
|
|
602
609
|
)
|
603
610
|
)
|
604
611
|
|
605
|
-
def
|
612
|
+
async def execute_bundle(self, bundle: SerializedBundle) -> None:
|
613
|
+
"""
|
614
|
+
Executes a bundle in a subprocess.
|
615
|
+
"""
|
616
|
+
from prefect.client.schemas.objects import FlowRun
|
617
|
+
|
618
|
+
self.pause_on_shutdown = False
|
619
|
+
context = self if not self.started else asyncnullcontext()
|
620
|
+
|
621
|
+
flow_run = FlowRun.model_validate(bundle["flow_run"])
|
622
|
+
|
623
|
+
async with context:
|
624
|
+
if not self._acquire_limit_slot(flow_run.id):
|
625
|
+
return
|
626
|
+
|
627
|
+
process = execute_bundle_in_subprocess(bundle)
|
628
|
+
|
629
|
+
if process.pid is None:
|
630
|
+
# This shouldn't happen because `execute_bundle_in_subprocess` starts the process
|
631
|
+
# but we'll handle it gracefully anyway
|
632
|
+
msg = "Failed to start process for flow execution. No PID returned."
|
633
|
+
await self._propose_crashed_state(flow_run, msg)
|
634
|
+
raise RuntimeError(msg)
|
635
|
+
|
636
|
+
self._flow_run_process_map[flow_run.id] = ProcessMapEntry(
|
637
|
+
pid=process.pid, flow_run=flow_run
|
638
|
+
)
|
639
|
+
self._flow_run_bundle_map[flow_run.id] = bundle
|
640
|
+
|
641
|
+
tasks: list[asyncio.Task[None]] = []
|
642
|
+
tasks.append(
|
643
|
+
asyncio.create_task(
|
644
|
+
critical_service_loop(
|
645
|
+
workload=self._check_for_cancelled_flow_runs,
|
646
|
+
interval=self.query_seconds,
|
647
|
+
jitter_range=0.3,
|
648
|
+
)
|
649
|
+
)
|
650
|
+
)
|
651
|
+
if self.heartbeat_seconds is not None:
|
652
|
+
tasks.append(
|
653
|
+
asyncio.create_task(
|
654
|
+
critical_service_loop(
|
655
|
+
workload=self._emit_flow_run_heartbeats,
|
656
|
+
interval=self.heartbeat_seconds,
|
657
|
+
jitter_range=0.1,
|
658
|
+
)
|
659
|
+
)
|
660
|
+
)
|
661
|
+
|
662
|
+
await anyio.to_thread.run_sync(process.join)
|
663
|
+
|
664
|
+
for task in tasks:
|
665
|
+
task.cancel()
|
666
|
+
|
667
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
668
|
+
|
669
|
+
self._flow_run_process_map.pop(flow_run.id)
|
670
|
+
|
671
|
+
flow_run_logger = self._get_flow_run_logger(flow_run)
|
672
|
+
if process.exitcode is None:
|
673
|
+
raise RuntimeError("Process has no exit code")
|
674
|
+
|
675
|
+
if process.exitcode:
|
676
|
+
help_message = None
|
677
|
+
level = logging.ERROR
|
678
|
+
if process.exitcode == -9:
|
679
|
+
level = logging.INFO
|
680
|
+
help_message = (
|
681
|
+
"This indicates that the process exited due to a SIGKILL signal. "
|
682
|
+
"Typically, this is either caused by manual cancellation or "
|
683
|
+
"high memory usage causing the operating system to "
|
684
|
+
"terminate the process."
|
685
|
+
)
|
686
|
+
if process.exitcode == -15:
|
687
|
+
level = logging.INFO
|
688
|
+
help_message = (
|
689
|
+
"This indicates that the process exited due to a SIGTERM signal. "
|
690
|
+
"Typically, this is caused by manual cancellation."
|
691
|
+
)
|
692
|
+
elif process.exitcode == 247:
|
693
|
+
help_message = (
|
694
|
+
"This indicates that the process was terminated due to high "
|
695
|
+
"memory usage."
|
696
|
+
)
|
697
|
+
elif (
|
698
|
+
sys.platform == "win32"
|
699
|
+
and process.returncode == STATUS_CONTROL_C_EXIT
|
700
|
+
):
|
701
|
+
level = logging.INFO
|
702
|
+
help_message = (
|
703
|
+
"Process was terminated due to a Ctrl+C or Ctrl+Break signal. "
|
704
|
+
"Typically, this is caused by manual cancellation."
|
705
|
+
)
|
706
|
+
|
707
|
+
flow_run_logger.log(
|
708
|
+
level,
|
709
|
+
f"Process for flow run {flow_run.name!r} exited with status code:"
|
710
|
+
f" {process.exitcode}"
|
711
|
+
+ (f"; {help_message}" if help_message else ""),
|
712
|
+
)
|
713
|
+
terminal_state = await self._propose_crashed_state(
|
714
|
+
flow_run, help_message or "Process exited with non-zero exit code"
|
715
|
+
)
|
716
|
+
if terminal_state:
|
717
|
+
await self._run_on_crashed_hooks(
|
718
|
+
flow_run=flow_run, state=terminal_state
|
719
|
+
)
|
720
|
+
else:
|
721
|
+
flow_run_logger.info(
|
722
|
+
f"Process for flow run {flow_run.name!r} exited cleanly."
|
723
|
+
)
|
724
|
+
|
725
|
+
def _get_flow_run_logger(self, flow_run: "FlowRun") -> PrefectLogAdapter:
|
606
726
|
return flow_run_logger(flow_run=flow_run).getChild(
|
607
727
|
"runner",
|
608
728
|
extra={
|
@@ -1308,8 +1428,11 @@ class Runner:
|
|
1308
1428
|
exc_info=True,
|
1309
1429
|
)
|
1310
1430
|
|
1311
|
-
async def _propose_crashed_state(
|
1431
|
+
async def _propose_crashed_state(
|
1432
|
+
self, flow_run: "FlowRun", message: str
|
1433
|
+
) -> State[Any] | None:
|
1312
1434
|
run_logger = self._get_flow_run_logger(flow_run)
|
1435
|
+
state = None
|
1313
1436
|
try:
|
1314
1437
|
state = await propose_state(
|
1315
1438
|
self._client,
|
@@ -1326,6 +1449,7 @@ class Runner:
|
|
1326
1449
|
run_logger.info(
|
1327
1450
|
f"Reported flow run '{flow_run.id}' as crashed: {message}"
|
1328
1451
|
)
|
1452
|
+
return state
|
1329
1453
|
|
1330
1454
|
async def _mark_flow_run_as_cancelled(
|
1331
1455
|
self, flow_run: "FlowRun", state_updates: Optional[dict[str, Any]] = None
|
@@ -1391,9 +1515,14 @@ class Runner:
|
|
1391
1515
|
"""
|
1392
1516
|
if state.is_cancelling():
|
1393
1517
|
try:
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1518
|
+
if flow_run.id in self._flow_run_bundle_map:
|
1519
|
+
flow = extract_flow_from_bundle(
|
1520
|
+
self._flow_run_bundle_map[flow_run.id]
|
1521
|
+
)
|
1522
|
+
else:
|
1523
|
+
flow = await load_flow_from_flow_run(
|
1524
|
+
flow_run, storage_base_path=str(self._tmp_dir)
|
1525
|
+
)
|
1397
1526
|
hooks = flow.on_cancellation_hooks or []
|
1398
1527
|
|
1399
1528
|
await _run_hooks(hooks, flow_run, flow, state)
|
@@ -1412,9 +1541,12 @@ class Runner:
|
|
1412
1541
|
Run the hooks for a flow.
|
1413
1542
|
"""
|
1414
1543
|
if state.is_crashed():
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1544
|
+
if flow_run.id in self._flow_run_bundle_map:
|
1545
|
+
flow = extract_flow_from_bundle(self._flow_run_bundle_map[flow_run.id])
|
1546
|
+
else:
|
1547
|
+
flow = await load_flow_from_flow_run(
|
1548
|
+
flow_run, storage_base_path=str(self._tmp_dir)
|
1549
|
+
)
|
1418
1550
|
hooks = flow.on_crashed_hooks or []
|
1419
1551
|
|
1420
1552
|
await _run_hooks(hooks, flow_run, flow, state)
|
@@ -55,6 +55,7 @@ from prefect.settings import (
|
|
55
55
|
PREFECT_DEBUG_MODE,
|
56
56
|
PREFECT_MEMO_STORE_PATH,
|
57
57
|
PREFECT_MEMOIZE_BLOCK_AUTO_REGISTRATION,
|
58
|
+
PREFECT_SERVER_API_BASE_PATH,
|
58
59
|
PREFECT_SERVER_EPHEMERAL_STARTUP_TIMEOUT_SECONDS,
|
59
60
|
PREFECT_UI_SERVE_BASE,
|
60
61
|
get_current_settings,
|
@@ -356,7 +357,10 @@ def create_api_app(
|
|
356
357
|
header_token = request.headers.get("Authorization")
|
357
358
|
|
358
359
|
# used for probes in k8s and such
|
359
|
-
if
|
360
|
+
if (
|
361
|
+
request.url.path.endswith(("health", "ready"))
|
362
|
+
and request.method.upper() == "GET"
|
363
|
+
):
|
360
364
|
return await call_next(request)
|
361
365
|
try:
|
362
366
|
if header_token is None:
|
@@ -691,7 +695,10 @@ def create_app(
|
|
691
695
|
name="static",
|
692
696
|
)
|
693
697
|
app.api_app = api_app
|
694
|
-
|
698
|
+
if PREFECT_SERVER_API_BASE_PATH:
|
699
|
+
app.mount(PREFECT_SERVER_API_BASE_PATH.value(), app=api_app, name="api")
|
700
|
+
else:
|
701
|
+
app.mount("/api", app=api_app, name="api")
|
695
702
|
app.mount("/", app=ui_app, name="ui")
|
696
703
|
|
697
704
|
def openapi():
|