prefect 3.7.3.dev3__py3-none-any.whl → 3.7.3.dev5__py3-none-any.whl
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/AGENTS.md +1 -0
- prefect/_build_info.py +3 -3
- prefect/_internal/result_records.py +9 -0
- prefect/cli/_server_utils.py +12 -0
- prefect/cli/server.py +9 -0
- prefect/client/orchestration/__init__.py +10 -3
- prefect/results.py +4 -0
- prefect/runner/AGENTS.md +5 -1
- prefect/runner/_workspace_resolver.py +83 -5
- prefect/runner/_workspace_starter.py +4 -0
- prefect/server/AGENTS.md +1 -0
- prefect/server/__init__.py +20 -1
- prefect/server/api/__init__.py +86 -33
- prefect/server/orchestration/core_policy.py +3 -2
- prefect/server/schemas/__init__.py +32 -13
- prefect/server/services/scheduler.py +7 -2
- prefect/server/ui-v2/assets/{artifact._id-Zo42JsyQ.js → artifact._id-B5o4IZAN.js} +2 -2
- prefect/server/ui-v2/assets/{artifact._id-Zo42JsyQ.js.map → artifact._id-B5o4IZAN.js.map} +1 -1
- prefect/server/ui-v2/assets/{artifacts-BdknReie.js → artifacts-Ctaild7x.js} +2 -2
- prefect/server/ui-v2/assets/{artifacts-BdknReie.js.map → artifacts-Ctaild7x.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation-wizard-CqzFukp0.js → automation-wizard-CwysCxB_.js} +2 -2
- prefect/server/ui-v2/assets/{automation-wizard-CqzFukp0.js.map → automation-wizard-CwysCxB_.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation._id-DHR9tHhZ.js → automation._id-BF8uKyjS.js} +2 -2
- prefect/server/ui-v2/assets/{automation._id-DHR9tHhZ.js.map → automation._id-BF8uKyjS.js.map} +1 -1
- prefect/server/ui-v2/assets/{automation_._id.edit-CUgxw4VO.js → automation_._id.edit-B4KXUFIU.js} +2 -2
- prefect/server/ui-v2/assets/{automation_._id.edit-CUgxw4VO.js.map → automation_._id.edit-B4KXUFIU.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-_EtuoGXy.js → automations-ChO76GC4.js} +2 -2
- prefect/server/ui-v2/assets/{automations-_EtuoGXy.js.map → automations-ChO76GC4.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-BteX3VP5.js → automations-DgzCc631.js} +2 -2
- prefect/server/ui-v2/assets/{automations-BteX3VP5.js.map → automations-DgzCc631.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-header-DVHcldsa.js → automations-header-BR_w1Bhm.js} +2 -2
- prefect/server/ui-v2/assets/{automations-header-DVHcldsa.js.map → automations-header-BR_w1Bhm.js.map} +1 -1
- prefect/server/ui-v2/assets/{automations-wizard-BxUMHb1N.js → automations-wizard-Cc5PQ-m-.js} +2 -2
- prefect/server/ui-v2/assets/{automations-wizard-BxUMHb1N.js.map → automations-wizard-Cc5PQ-m-.js.map} +1 -1
- prefect/server/ui-v2/assets/{base-job-template-form-section-B0YP4I3P.js → base-job-template-form-section-Bs8t71Mi.js} +2 -2
- prefect/server/ui-v2/assets/{base-job-template-form-section-B0YP4I3P.js.map → base-job-template-form-section-Bs8t71Mi.js.map} +1 -1
- prefect/server/ui-v2/assets/{block-type-details-B3Vwd-RE.js → block-type-details-Duek8VRa.js} +2 -2
- prefect/server/ui-v2/assets/{block-type-details-B3Vwd-RE.js.map → block-type-details-Duek8VRa.js.map} +1 -1
- prefect/server/ui-v2/assets/{block._id-B3CCPFtJ.js → block._id-CtPAbsBd.js} +2 -2
- prefect/server/ui-v2/assets/{block._id-B3CCPFtJ.js.map → block._id-CtPAbsBd.js.map} +1 -1
- prefect/server/ui-v2/assets/{block_._id.edit-DSO33Cqt.js → block_._id.edit-CqBFmljM.js} +2 -2
- prefect/server/ui-v2/assets/{block_._id.edit-DSO33Cqt.js.map → block_._id.edit-CqBFmljM.js.map} +1 -1
- prefect/server/ui-v2/assets/blocks-CH5PZKMD.js.map +1 -1
- prefect/server/ui-v2/assets/blocks-CYWX8lHn.js +2 -0
- prefect/server/ui-v2/assets/blocks-CYWX8lHn.js.map +1 -0
- prefect/server/ui-v2/assets/{catalog-peZ0ZDPi.js → catalog-D01rbOjr.js} +2 -2
- prefect/server/ui-v2/assets/{catalog-peZ0ZDPi.js.map → catalog-D01rbOjr.js.map} +1 -1
- prefect/server/ui-v2/assets/{catalog_._slug-BUsVdYgf.js → catalog_._slug-CWcK6p_E.js} +2 -2
- prefect/server/ui-v2/assets/{catalog_._slug-BUsVdYgf.js.map → catalog_._slug-CWcK6p_E.js.map} +1 -1
- prefect/server/ui-v2/assets/{catalog_._slug_.create-ByZmibJZ.js → catalog_._slug_.create-BrDeutP_.js} +2 -2
- prefect/server/ui-v2/assets/{catalog_._slug_.create-ByZmibJZ.js.map → catalog_._slug_.create-BrDeutP_.js.map} +1 -1
- prefect/server/ui-v2/assets/{concurrency-limit._id-VxLjP6mE.js → concurrency-limit._id-v9uWcYLo.js} +2 -2
- prefect/server/ui-v2/assets/{concurrency-limit._id-VxLjP6mE.js.map → concurrency-limit._id-v9uWcYLo.js.map} +1 -1
- prefect/server/ui-v2/assets/concurrency-limits--iQ4LePG.js +2 -0
- prefect/server/ui-v2/assets/{concurrency-limits-BI7aLjxZ.js.map → concurrency-limits--iQ4LePG.js.map} +1 -1
- prefect/server/ui-v2/assets/{create-DMBCpuVl.js → create-BOLwAD8-.js} +2 -2
- prefect/server/ui-v2/assets/{create-DMBCpuVl.js.map → create-BOLwAD8-.js.map} +1 -1
- prefect/server/ui-v2/assets/{create-CxHFH55_.js → create-STic_dos.js} +2 -2
- prefect/server/ui-v2/assets/{create-CxHFH55_.js.map → create-STic_dos.js.map} +1 -1
- prefect/server/ui-v2/assets/{data-table-DLh2VpHW.js → data-table-CnCIUIrK.js} +2 -2
- prefect/server/ui-v2/assets/{data-table-DLh2VpHW.js.map → data-table-CnCIUIrK.js.map} +1 -1
- prefect/server/ui-v2/assets/{data-table-BbGyTn8n.js → data-table-XB91Mv7x.js} +2 -2
- prefect/server/ui-v2/assets/{data-table-BbGyTn8n.js.map → data-table-XB91Mv7x.js.map} +1 -1
- prefect/server/ui-v2/assets/deployment-form-BkR3mHkN.js +3 -0
- prefect/server/ui-v2/assets/{deployment-form-CmjkGAeP.js.map → deployment-form-BkR3mHkN.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment-links-BY54Gk6i.js → deployment-links-BF-jQWq8.js} +2 -2
- prefect/server/ui-v2/assets/{deployment-links-BY54Gk6i.js.map → deployment-links-BF-jQWq8.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment._id-PXR53xU4.js → deployment._id-Bu7e5nDn.js} +2 -2
- prefect/server/ui-v2/assets/{deployment._id-PXR53xU4.js.map → deployment._id-Bu7e5nDn.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment_._id.duplicate-DdLQwNw9.js → deployment_._id.duplicate-CVUiK5xi.js} +2 -2
- prefect/server/ui-v2/assets/{deployment_._id.duplicate-DdLQwNw9.js.map → deployment_._id.duplicate-CVUiK5xi.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment_._id.edit-D5bMVvb9.js → deployment_._id.edit-DQDuOF3-.js} +2 -2
- prefect/server/ui-v2/assets/{deployment_._id.edit-D5bMVvb9.js.map → deployment_._id.edit-DQDuOF3-.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployment_._id.run-DczKs3Hq.js → deployment_._id.run-Bfb1JAMA.js} +2 -2
- prefect/server/ui-v2/assets/{deployment_._id.run-DczKs3Hq.js.map → deployment_._id.run-Bfb1JAMA.js.map} +1 -1
- prefect/server/ui-v2/assets/{deployments-CgJ1ie-z.js → deployments-BAr8hYlF.js} +2 -2
- prefect/server/ui-v2/assets/{deployments-CgJ1ie-z.js.map → deployments-BAr8hYlF.js.map} +1 -1
- prefect/server/ui-v2/assets/deployments-BCuQR-Rv.js +2 -0
- prefect/server/ui-v2/assets/{deployments-r9sa-J42.js.map → deployments-BCuQR-Rv.js.map} +1 -1
- prefect/server/ui-v2/assets/error-boundary-GTe7hhSV.js +2 -0
- prefect/server/ui-v2/assets/error-boundary-GTe7hhSV.js.map +1 -0
- prefect/server/ui-v2/assets/{event-resource-display-2u5ia4Md.js → event-resource-display-7RkqYS59.js} +2 -2
- prefect/server/ui-v2/assets/{event-resource-display-2u5ia4Md.js.map → event-resource-display-7RkqYS59.js.map} +1 -1
- prefect/server/ui-v2/assets/{event._eventDate._eventId-BAp6hV6h.js → event._eventDate._eventId-CIk5QcV_.js} +2 -2
- prefect/server/ui-v2/assets/{event._eventDate._eventId-BAp6hV6h.js.map → event._eventDate._eventId-CIk5QcV_.js.map} +1 -1
- prefect/server/ui-v2/assets/{events-BknsFN6O.js → events-C46I_3_q.js} +2 -2
- prefect/server/ui-v2/assets/{events-BknsFN6O.js.map → events-C46I_3_q.js.map} +1 -1
- prefect/server/ui-v2/assets/{events-timeline-Rl2m78Y5.js → events-timeline-DpAjaSUA.js} +2 -2
- prefect/server/ui-v2/assets/{events-timeline-Rl2m78Y5.js.map → events-timeline-DpAjaSUA.js.map} +1 -1
- prefect/server/ui-v2/assets/flow-run-graph-CwfW_BdI.js +2 -0
- prefect/server/ui-v2/assets/flow-run-graph-CwfW_BdI.js.map +1 -0
- prefect/server/ui-v2/assets/flow-run._id-Dd7T5NGk.js +4 -0
- prefect/server/ui-v2/assets/flow-run._id-Dd7T5NGk.js.map +1 -0
- prefect/server/ui-v2/assets/flow-run._id-sCOYzbkr.js +2 -0
- prefect/server/ui-v2/assets/{flow-run._id-CLKdcnle.js.map → flow-run._id-sCOYzbkr.js.map} +1 -1
- prefect/server/ui-v2/assets/{flow._id-BZAOxnsl.js → flow._id-C3nUTsZH.js} +2 -2
- prefect/server/ui-v2/assets/{flow._id-BZAOxnsl.js.map → flow._id-C3nUTsZH.js.map} +1 -1
- prefect/server/ui-v2/assets/flow._id-CjqyQAAC.js +2 -0
- prefect/server/ui-v2/assets/{flow._id-CyI-Q-4Z.js.map → flow._id-CjqyQAAC.js.map} +1 -1
- prefect/server/ui-v2/assets/flows-DCd3xo0Q.js +2 -0
- prefect/server/ui-v2/assets/{flows-CfyGye_i.js.map → flows-DCd3xo0Q.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-B7UaCf9Y.js → header-2itxDfFr.js} +2 -2
- prefect/server/ui-v2/assets/{header-B7UaCf9Y.js.map → header-2itxDfFr.js.map} +1 -1
- prefect/server/ui-v2/assets/header-Ne8GjMqm.js +2 -0
- prefect/server/ui-v2/assets/{header-CfPjWK5N.js.map → header-Ne8GjMqm.js.map} +1 -1
- prefect/server/ui-v2/assets/{header-CZl2UtVY.js → header-vRsd55Bl.js} +2 -2
- prefect/server/ui-v2/assets/{header-CZl2UtVY.js.map → header-vRsd55Bl.js.map} +1 -1
- prefect/server/ui-v2/assets/{index-BiTXO7bZ.js → index-Bkwh5I57.js} +4 -4
- prefect/server/ui-v2/assets/index-Bkwh5I57.js.map +1 -0
- prefect/server/ui-v2/assets/{json-input-DuU-pR4T.js → json-input-DYHPmDXw.js} +2 -2
- prefect/server/ui-v2/assets/{json-input-DuU-pR4T.js.map → json-input-DYHPmDXw.js.map} +1 -1
- prefect/server/ui-v2/assets/{key._key-BfIX2NO0.js → key._key-D9waqPVY.js} +2 -2
- prefect/server/ui-v2/assets/{key._key-BfIX2NO0.js.map → key._key-D9waqPVY.js.map} +1 -1
- prefect/server/ui-v2/assets/{lazy-markdown-C6e3AE83.js → lazy-markdown-91RysaF6.js} +2 -2
- prefect/server/ui-v2/assets/{lazy-markdown-C6e3AE83.js.map → lazy-markdown-91RysaF6.js.map} +1 -1
- prefect/server/ui-v2/assets/{login-BAVVPHlC.js → login-D7uyYnlK.js} +2 -2
- prefect/server/ui-v2/assets/{login-BAVVPHlC.js.map → login-D7uyYnlK.js.map} +1 -1
- prefect/server/ui-v2/assets/runs-B5_rXYcG.js +2 -0
- prefect/server/ui-v2/assets/{runs-HrNDCquv.js.map → runs-B5_rXYcG.js.map} +1 -1
- prefect/server/ui-v2/assets/{runs-J2wsTr98.js → runs-GMnQbC9Q.js} +2 -2
- prefect/server/ui-v2/assets/{runs-J2wsTr98.js.map → runs-GMnQbC9Q.js.map} +1 -1
- prefect/server/ui-v2/assets/{schedule-badge-0fzDLqK0.js → schedule-badge-Cd-fRm5K.js} +2 -2
- prefect/server/ui-v2/assets/{schedule-badge-0fzDLqK0.js.map → schedule-badge-Cd-fRm5K.js.map} +1 -1
- prefect/server/ui-v2/assets/schema-form-Cdy5q5ON.js +6 -0
- prefect/server/ui-v2/assets/schema-form-Cdy5q5ON.js.map +1 -0
- prefect/server/ui-v2/assets/{settings-CKEdr8bc.js → settings-BsGzqy6W.js} +2 -2
- prefect/server/ui-v2/assets/{settings-CKEdr8bc.js.map → settings-BsGzqy6W.js.map} +1 -1
- prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-CSOUIoRP.js → task-run-concurrency-limits-reset-dialog-Cen4RETI.js} +2 -2
- prefect/server/ui-v2/assets/{task-run-concurrency-limits-reset-dialog-CSOUIoRP.js.map → task-run-concurrency-limits-reset-dialog-Cen4RETI.js.map} +1 -1
- prefect/server/ui-v2/assets/task-run._id-bIhtj3BE.js +3 -0
- prefect/server/ui-v2/assets/{task-run._id-BUnHohQT.js.map → task-run._id-bIhtj3BE.js.map} +1 -1
- prefect/server/ui-v2/assets/{timezone-select-Bnsn0RhV.js → timezone-select-rrYri33l.js} +2 -2
- prefect/server/ui-v2/assets/{timezone-select-Bnsn0RhV.js.map → timezone-select-rrYri33l.js.map} +1 -1
- prefect/server/ui-v2/assets/{toggle-group-_iuYMe3I.js → toggle-group-C3LHGX7w.js} +2 -2
- prefect/server/ui-v2/assets/{toggle-group-_iuYMe3I.js.map → toggle-group-C3LHGX7w.js.map} +1 -1
- prefect/server/ui-v2/assets/{trigger-details-CTi7CDXp.js → trigger-details-B5sEwXPp.js} +2 -2
- prefect/server/ui-v2/assets/{trigger-details-CTi7CDXp.js.map → trigger-details-B5sEwXPp.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-Dzh4KhYd.js → use-delete-automation-confirmation-dialog-Bd3dYDWc.js} +2 -2
- prefect/server/ui-v2/assets/{use-delete-automation-confirmation-dialog-Dzh4KhYd.js.map → use-delete-automation-confirmation-dialog-Bd3dYDWc.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-CMUcMn04.js → use-delete-block-document-confirmation-dialog-DgyKK2fk.js} +2 -2
- prefect/server/ui-v2/assets/{use-delete-block-document-confirmation-dialog-CMUcMn04.js.map → use-delete-block-document-confirmation-dialog-DgyKK2fk.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-delete-deployment-confirmation-dialog-DCR3G6aC.js → use-delete-deployment-confirmation-dialog-Co6qSSOK.js} +2 -2
- prefect/server/ui-v2/assets/{use-delete-deployment-confirmation-dialog-DCR3G6aC.js.map → use-delete-deployment-confirmation-dialog-Co6qSSOK.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-CwYIhd7a.js → use-get-artifacts-flow-task-runs-BpN8dMPb.js} +2 -2
- prefect/server/ui-v2/assets/{use-get-artifacts-flow-task-runs-CwYIhd7a.js.map → use-get-artifacts-flow-task-runs-BpN8dMPb.js.map} +1 -1
- prefect/server/ui-v2/assets/{use-resource-options-TivZbz4R.js → use-resource-options-C00eBL9A.js} +2 -2
- prefect/server/ui-v2/assets/{use-resource-options-TivZbz4R.js.map → use-resource-options-C00eBL9A.js.map} +1 -1
- prefect/server/ui-v2/assets/{variables--T46q5I7.js → variables-CsKiip11.js} +2 -2
- prefect/server/ui-v2/assets/{variables--T46q5I7.js.map → variables-CsKiip11.js.map} +1 -1
- prefect/server/ui-v2/assets/variables-ViEl85wc.js +2 -0
- prefect/server/ui-v2/assets/{variables-DohLnyOU.js.map → variables-ViEl85wc.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool-queue-form-BTlH9k-v.js → work-pool-queue-form-BOSESyN3.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool-queue-form-BTlH9k-v.js.map → work-pool-queue-form-BOSESyN3.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool-queue-toggle-DJYRbHHT.js → work-pool-queue-toggle-BFCWL6J2.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool-queue-toggle-DJYRbHHT.js.map → work-pool-queue-toggle-BFCWL6J2.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool._workPoolName-BNogexz_.js → work-pool._workPoolName-DpYDD8xf.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool._workPoolName-BNogexz_.js.map → work-pool._workPoolName-DpYDD8xf.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-BUADYBE8.js → work-pool_._workPoolName.edit-D-ZS5N2n.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.edit-BUADYBE8.js.map → work-pool_._workPoolName.edit-D-ZS5N2n.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-BB5g0Fdn.js → work-pool_._workPoolName.queue._workQueueName-CS62Q2rZ.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue._workQueueName-BB5g0Fdn.js.map → work-pool_._workPoolName.queue._workQueueName-CS62Q2rZ.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue.create-USf-zJSY.js → work-pool_._workPoolName.queue.create-DtYMzrOL.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue.create-USf-zJSY.js.map → work-pool_._workPoolName.queue.create-DtYMzrOL.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue_._workQueueName.edit-DQsfRuma.js → work-pool_._workPoolName.queue_._workQueueName.edit-Dc9_k8ps.js} +2 -2
- prefect/server/ui-v2/assets/{work-pool_._workPoolName.queue_._workQueueName.edit-DQsfRuma.js.map → work-pool_._workPoolName.queue_._workQueueName.edit-Dc9_k8ps.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pools-QaYhK2wz.js → work-pools-C02bLafB.js} +2 -2
- prefect/server/ui-v2/assets/{work-pools-QaYhK2wz.js.map → work-pools-C02bLafB.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-pools-D_2J6ZNf.js → work-pools-CSWGEVgG.js} +2 -2
- prefect/server/ui-v2/assets/{work-pools-D_2J6ZNf.js.map → work-pools-CSWGEVgG.js.map} +1 -1
- prefect/server/ui-v2/assets/{work-queue-icon-text-BI7IQrcX.js → work-queue-icon-text-D8VhfR7N.js} +2 -2
- prefect/server/ui-v2/assets/{work-queue-icon-text-BI7IQrcX.js.map → work-queue-icon-text-D8VhfR7N.js.map} +1 -1
- prefect/server/ui-v2/assets/work-queue-select-qZ6poNqo.js +2 -0
- prefect/server/ui-v2/assets/{work-queue-select-QOtPRzFp.js.map → work-queue-select-qZ6poNqo.js.map} +1 -1
- prefect/server/ui-v2/index.html +1 -1
- prefect/server/worker_communication/__init__.py +3 -0
- prefect/server/worker_communication/cleanup_queue/__init__.py +284 -0
- prefect/server/worker_communication/cleanup_queue/memory.py +723 -0
- prefect/settings/_types.py +225 -0
- prefect/settings/context.py +9 -3
- prefect/settings/models/root.py +56 -11
- prefect/settings/models/runner.py +9 -0
- prefect/settings/models/server/api.py +10 -0
- prefect/settings/models/server/root.py +5 -0
- prefect/settings/models/server/worker_channel.py +54 -0
- prefect/states.py +5 -1
- prefect/workers/_worker_channel/_transport.py +6 -1
- {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev5.dist-info}/METADATA +1 -1
- {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev5.dist-info}/RECORD +191 -184
- prefect/server/ui-v2/assets/blocks-BPxghuZI.js +0 -2
- prefect/server/ui-v2/assets/blocks-BPxghuZI.js.map +0 -1
- prefect/server/ui-v2/assets/concurrency-limits-BI7aLjxZ.js +0 -2
- prefect/server/ui-v2/assets/deployment-form-CmjkGAeP.js +0 -3
- prefect/server/ui-v2/assets/deployments-r9sa-J42.js +0 -2
- prefect/server/ui-v2/assets/flow-run-graph-DT6ORwEA.js +0 -2
- prefect/server/ui-v2/assets/flow-run-graph-DT6ORwEA.js.map +0 -1
- prefect/server/ui-v2/assets/flow-run._id-CLKdcnle.js +0 -2
- prefect/server/ui-v2/assets/flow-run._id-n-hTsvaN.js +0 -4
- prefect/server/ui-v2/assets/flow-run._id-n-hTsvaN.js.map +0 -1
- prefect/server/ui-v2/assets/flow._id-CyI-Q-4Z.js +0 -2
- prefect/server/ui-v2/assets/flows-CfyGye_i.js +0 -2
- prefect/server/ui-v2/assets/header-CfPjWK5N.js +0 -2
- prefect/server/ui-v2/assets/index-BiTXO7bZ.js.map +0 -1
- prefect/server/ui-v2/assets/runs-HrNDCquv.js +0 -2
- prefect/server/ui-v2/assets/schema-form-DLdMdbMj.js +0 -6
- prefect/server/ui-v2/assets/schema-form-DLdMdbMj.js.map +0 -1
- prefect/server/ui-v2/assets/task-run._id-BUnHohQT.js +0 -3
- prefect/server/ui-v2/assets/variables-DohLnyOU.js +0 -2
- prefect/server/ui-v2/assets/work-queue-select-QOtPRzFp.js +0 -2
- {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev5.dist-info}/WHEEL +0 -0
- {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev5.dist-info}/entry_points.txt +0 -0
- {prefect-3.7.3.dev3.dist-info → prefect-3.7.3.dev5.dist-info}/licenses/LICENSE +0 -0
prefect/AGENTS.md
CHANGED
|
@@ -32,6 +32,7 @@ There is no formal public/private boundary beyond the `_` prefix convention. Mod
|
|
|
32
32
|
- **Nested task submissions on a bounded `ThreadPoolTaskRunner` can deadlock.** When a worker task submits children and blocks on `.result()` while all `max_workers` threads are busy, the pool starves. `_warn_if_nested_submit_would_deadlock` detects this and emits a one-time warning — preserve this detection when changing pool management.
|
|
33
33
|
- **Result storage resolves through three tiers, potentially making an API call.** `get_default_result_storage()` checks: (1) `PREFECT_DEFAULT_RESULT_STORAGE_BLOCK` setting, (2) server-configured default block (API call to the server's Configuration store), (3) local storage path. The API call is silently suppressed on any HTTP error. Engines use `_get_default_persist_result()` — not `should_persist_result()` — at context setup time to auto-enable persistence when a server default block is configured. Do not swap `_get_default_persist_result()` back to `should_persist_result()` in engine initialization paths; `should_persist_result()` does not consult the server default.
|
|
34
34
|
- **`ResultRecordMetadata` tolerates unknown serializer types.** When loading persisted metadata, an unrecognized serializer `type` is converted to an `UnknownSerializer` placeholder rather than raising `ValidationError`. This allows inspecting result metadata when the serializer implementation is unavailable in the current environment. However, known serializer types with invalid fields still raise `ValidationError`. `UnknownSerializer.dumps()` and `UnknownSerializer.loads()` raise `RuntimeError` — the tolerance is for inspection only, not actual serialization/deserialization.
|
|
35
|
+
- **`ResultRecord` must be marked persisted after every storage write.** `ResultStore` calls `mark_persisted()` on every record it writes; `to_state_create` in `states.py` consults `is_persisted` as a fallback when `should_persist_result()` returns `False` (e.g., after run context teardown). Any new sync or async persist path that omits `mark_persisted()` will silently drop state metadata for already-written results.
|
|
35
36
|
- **Flow-run suspension is enforced at orchestration boundaries.** Suspension is delivered via `FlowRunSuspensionRequest` and raised with `raise_if_flow_run_suspension_requested()`. When changing engines, futures, task runners, or generator execution, check before returning control to flow user code or proposing a flow state that could leave `Suspended`; keep sync/async paths aligned and avoid per-boundary API reads.
|
|
36
37
|
|
|
37
38
|
## Logging
|
prefect/_build_info.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Generated by versioningit
|
|
2
|
-
__version__ = "3.7.3.
|
|
3
|
-
__build_date__ = "2026-05-
|
|
4
|
-
__git_commit__ = "
|
|
2
|
+
__version__ = "3.7.3.dev5"
|
|
3
|
+
__build_date__ = "2026-05-28 09:25:13.582068+00:00"
|
|
4
|
+
__git_commit__ = "f7d76f21e9731cedf0462e3f9632133e1c23a439"
|
|
5
5
|
__dirty__ = False
|
|
@@ -16,6 +16,7 @@ from uuid import UUID
|
|
|
16
16
|
from pydantic import (
|
|
17
17
|
BaseModel,
|
|
18
18
|
Field,
|
|
19
|
+
PrivateAttr,
|
|
19
20
|
ValidationError,
|
|
20
21
|
field_validator,
|
|
21
22
|
model_validator,
|
|
@@ -105,6 +106,14 @@ class ResultRecord(BaseModel, Generic[R]):
|
|
|
105
106
|
|
|
106
107
|
metadata: ResultRecordMetadata
|
|
107
108
|
result: R
|
|
109
|
+
_persisted: bool = PrivateAttr(default=False)
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def is_persisted(self) -> bool:
|
|
113
|
+
return self._persisted
|
|
114
|
+
|
|
115
|
+
def mark_persisted(self) -> None:
|
|
116
|
+
self._persisted = True
|
|
108
117
|
|
|
109
118
|
@property
|
|
110
119
|
def expiration(self) -> DateTime | None:
|
prefect/cli/_server_utils.py
CHANGED
|
@@ -274,6 +274,9 @@ def _run_in_background(
|
|
|
274
274
|
keep_alive_timeout: int,
|
|
275
275
|
no_services: bool,
|
|
276
276
|
workers: int,
|
|
277
|
+
*,
|
|
278
|
+
ws_ping_interval: float = 20.0,
|
|
279
|
+
ws_ping_timeout: float = 20.0,
|
|
277
280
|
) -> None:
|
|
278
281
|
command = [
|
|
279
282
|
sys.executable,
|
|
@@ -292,6 +295,8 @@ def _run_in_background(
|
|
|
292
295
|
"--workers",
|
|
293
296
|
str(workers),
|
|
294
297
|
]
|
|
298
|
+
command.extend(["--ws-ping-interval", str(ws_ping_interval)])
|
|
299
|
+
command.extend(["--ws-ping-timeout", str(ws_ping_timeout)])
|
|
295
300
|
logger.debug("Opening server process with command: %s", shlex.join(command))
|
|
296
301
|
|
|
297
302
|
env = {**os.environ, **server_settings, "PREFECT__SERVER_FINAL": "1"}
|
|
@@ -322,6 +327,9 @@ def _run_in_foreground(
|
|
|
322
327
|
keep_alive_timeout: int,
|
|
323
328
|
no_services: bool,
|
|
324
329
|
workers: int,
|
|
330
|
+
*,
|
|
331
|
+
ws_ping_interval: float = 20.0,
|
|
332
|
+
ws_ping_timeout: float = 20.0,
|
|
325
333
|
) -> None:
|
|
326
334
|
from prefect.server.api.server import create_app
|
|
327
335
|
|
|
@@ -336,6 +344,8 @@ def _run_in_foreground(
|
|
|
336
344
|
host=host,
|
|
337
345
|
port=port,
|
|
338
346
|
timeout_keep_alive=keep_alive_timeout,
|
|
347
|
+
ws_ping_interval=ws_ping_interval,
|
|
348
|
+
ws_ping_timeout=ws_ping_timeout,
|
|
339
349
|
log_level=server_settings.get(
|
|
340
350
|
"PREFECT_SERVER_LOGGING_LEVEL", "info"
|
|
341
351
|
).lower(),
|
|
@@ -351,6 +361,8 @@ def _run_in_foreground(
|
|
|
351
361
|
host=host,
|
|
352
362
|
port=port,
|
|
353
363
|
timeout_keep_alive=keep_alive_timeout,
|
|
364
|
+
ws_ping_interval=ws_ping_interval,
|
|
365
|
+
ws_ping_timeout=ws_ping_timeout,
|
|
354
366
|
log_level=server_settings.get(
|
|
355
367
|
"PREFECT_SERVER_LOGGING_LEVEL", "info"
|
|
356
368
|
).lower(),
|
prefect/cli/server.py
CHANGED
|
@@ -133,6 +133,8 @@ def start(
|
|
|
133
133
|
PREFECT_SERVER_API_HOST,
|
|
134
134
|
PREFECT_SERVER_API_KEEPALIVE_TIMEOUT,
|
|
135
135
|
PREFECT_SERVER_API_PORT,
|
|
136
|
+
PREFECT_SERVER_API_WEBSOCKET_PING_INTERVAL,
|
|
137
|
+
PREFECT_SERVER_API_WEBSOCKET_PING_TIMEOUT,
|
|
136
138
|
PREFECT_SERVER_LOGGING_LEVEL,
|
|
137
139
|
PREFECT_UI_ENABLED,
|
|
138
140
|
)
|
|
@@ -146,6 +148,9 @@ def start(
|
|
|
146
148
|
keep_alive_timeout = PREFECT_SERVER_API_KEEPALIVE_TIMEOUT.value()
|
|
147
149
|
if log_level is None:
|
|
148
150
|
log_level = PREFECT_SERVER_LOGGING_LEVEL.value()
|
|
151
|
+
|
|
152
|
+
ws_ping_interval = PREFECT_SERVER_API_WEBSOCKET_PING_INTERVAL.value()
|
|
153
|
+
ws_ping_timeout = PREFECT_SERVER_API_WEBSOCKET_PING_TIMEOUT.value()
|
|
149
154
|
if analytics is None:
|
|
150
155
|
analytics = PREFECT_SERVER_ANALYTICS_ENABLED.value()
|
|
151
156
|
if scheduler is None:
|
|
@@ -229,6 +234,8 @@ def start(
|
|
|
229
234
|
keep_alive_timeout,
|
|
230
235
|
no_services,
|
|
231
236
|
workers,
|
|
237
|
+
ws_ping_interval=ws_ping_interval,
|
|
238
|
+
ws_ping_timeout=ws_ping_timeout,
|
|
232
239
|
)
|
|
233
240
|
else:
|
|
234
241
|
_run_in_foreground(
|
|
@@ -239,6 +246,8 @@ def start(
|
|
|
239
246
|
keep_alive_timeout,
|
|
240
247
|
no_services,
|
|
241
248
|
workers,
|
|
249
|
+
ws_ping_interval=ws_ping_interval,
|
|
250
|
+
ws_ping_timeout=ws_ping_timeout,
|
|
242
251
|
)
|
|
243
252
|
|
|
244
253
|
|
|
@@ -137,6 +137,7 @@ from prefect.settings import (
|
|
|
137
137
|
)
|
|
138
138
|
from prefect.types._datetime import now
|
|
139
139
|
|
|
140
|
+
from prefect._internal.urls import strip_auth_from_url
|
|
140
141
|
from prefect._internal.version_checking import (
|
|
141
142
|
_api_version_check_key,
|
|
142
143
|
_cache_api_version_check,
|
|
@@ -1132,7 +1133,9 @@ class PrefectClient(
|
|
|
1132
1133
|
except Exception as e:
|
|
1133
1134
|
if "Unauthorized" in str(e):
|
|
1134
1135
|
raise e
|
|
1135
|
-
raise RuntimeError(
|
|
1136
|
+
raise RuntimeError(
|
|
1137
|
+
f"Failed to reach API at {strip_auth_from_url(str(self.api_url))}"
|
|
1138
|
+
) from e
|
|
1136
1139
|
|
|
1137
1140
|
api_version = version.parse(api_version)
|
|
1138
1141
|
client_version = version.parse(self.client_version())
|
|
@@ -1190,7 +1193,9 @@ class PrefectClient(
|
|
|
1190
1193
|
f"{PREFECT_API_DATABASE_CONNECTION_URL.value()}"
|
|
1191
1194
|
)
|
|
1192
1195
|
else:
|
|
1193
|
-
self.logger.debug(
|
|
1196
|
+
self.logger.debug(
|
|
1197
|
+
f"Connecting to API at {strip_auth_from_url(str(self.api_url))}"
|
|
1198
|
+
)
|
|
1194
1199
|
|
|
1195
1200
|
# Enter the httpx client's context
|
|
1196
1201
|
await self._exit_stack.enter_async_context(self._client)
|
|
@@ -1519,7 +1524,9 @@ class SyncPrefectClient(
|
|
|
1519
1524
|
except Exception as e:
|
|
1520
1525
|
if "Unauthorized" in str(e):
|
|
1521
1526
|
raise e
|
|
1522
|
-
raise RuntimeError(
|
|
1527
|
+
raise RuntimeError(
|
|
1528
|
+
f"Failed to reach API at {strip_auth_from_url(str(self.api_url))}"
|
|
1529
|
+
) from e
|
|
1523
1530
|
|
|
1524
1531
|
api_version = version.parse(api_version)
|
|
1525
1532
|
client_version = version.parse(self.client_version())
|
prefect/results.py
CHANGED
|
@@ -867,6 +867,7 @@ class ResultStore(BaseModel):
|
|
|
867
867
|
|
|
868
868
|
if self.cache_result_in_memory:
|
|
869
869
|
self.cache[resolved_key_path] = result_record
|
|
870
|
+
result_record.mark_persisted()
|
|
870
871
|
return result_record
|
|
871
872
|
|
|
872
873
|
def _read(self, key: str, holder: str) -> "ResultRecord[Any]":
|
|
@@ -936,6 +937,7 @@ class ResultStore(BaseModel):
|
|
|
936
937
|
|
|
937
938
|
if self.cache_result_in_memory:
|
|
938
939
|
self.cache[resolved_key_path] = result_record
|
|
940
|
+
result_record.mark_persisted()
|
|
939
941
|
return result_record
|
|
940
942
|
|
|
941
943
|
def read(
|
|
@@ -1122,6 +1124,7 @@ class ResultStore(BaseModel):
|
|
|
1122
1124
|
(result_record.metadata.storage_key,),
|
|
1123
1125
|
{"content": result_record.serialize()},
|
|
1124
1126
|
)
|
|
1127
|
+
result_record.mark_persisted()
|
|
1125
1128
|
if self.cache_result_in_memory:
|
|
1126
1129
|
self.cache[key] = result_record
|
|
1127
1130
|
|
|
@@ -1185,6 +1188,7 @@ class ResultStore(BaseModel):
|
|
|
1185
1188
|
(result_record.metadata.storage_key,),
|
|
1186
1189
|
{"content": result_record.serialize()},
|
|
1187
1190
|
)
|
|
1191
|
+
result_record.mark_persisted()
|
|
1188
1192
|
if self.cache_result_in_memory:
|
|
1189
1193
|
self.cache[key] = result_record
|
|
1190
1194
|
|
prefect/runner/AGENTS.md
CHANGED
|
@@ -138,7 +138,11 @@ These validations exist to prevent git argument injection. Do not bypass them wh
|
|
|
138
138
|
|
|
139
139
|
**Env/sys.path isolation:** `_prepared_workspace_context` mutates `os.environ` and `sys.path` in the caller process but does NOT change `os.getcwd()`. The parent working directory is preserved.
|
|
140
140
|
|
|
141
|
-
**
|
|
141
|
+
**Local path in-place execution:** When no pull steps are configured and the entrypoint file exists at `deployment.path` but not in the workspace root, `prepare_workspace` sets `working_directory` to the local path — not under `workspace_root`. The workspace directory is still created but is not the execution root. This is the "image-baked" pattern: code lives at a fixed local path (e.g., inside a container), not in object storage.
|
|
142
|
+
|
|
143
|
+
**Pull-step directory fallback:** When pull steps run but none produces a `directory` output or changes CWD, `_ensure_entrypoint_in_workspace` copies storage into the workspace root as a fallback. This handles setup-only pull steps (e.g., `run_shell_script` for environment prep) that do not control the working directory themselves.
|
|
144
|
+
|
|
145
|
+
**Automatic dependency installation:** By default, `WorkspaceResolvingEngineCommandStarter` does not install dependencies before starting a flow run. When no explicit command is passed and `PREFECT_RUNNER_AUTO_INSTALL_DEPENDENCIES` is true, it auto-selects `uv run --no-default-groups --project <project_root> -m prefect.flow_engine` — but only when all three conditions hold: `pyproject.toml` exists at `project_root`, the `project.dependencies` list includes `prefect`, and `uv` is found via the workspace's `PATH` env var (not the system PATH). If the setting is false or any condition fails, the command falls back to `None`. Explicit commands always take precedence.
|
|
142
146
|
|
|
143
147
|
## Reference
|
|
144
148
|
|
|
@@ -174,6 +174,61 @@ def _workspace_destination_for_deployment_path(
|
|
|
174
174
|
return (workspace_root / relative_destination).resolve()
|
|
175
175
|
|
|
176
176
|
|
|
177
|
+
def _resolve_local_runtime_directory(
|
|
178
|
+
path: str | None, source_cwd: Path, storage_base_path: Path | None
|
|
179
|
+
) -> Path:
|
|
180
|
+
resolved_path = _resolve_local_deployment_path(path, source_cwd, storage_base_path)
|
|
181
|
+
return Path(resolved_path).resolve() if resolved_path is not None else source_cwd
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _entrypoint_file_path(entrypoint: str, working_directory: Path) -> Path | None:
|
|
185
|
+
entrypoint = _resolve_runtime_entrypoint(entrypoint)
|
|
186
|
+
if ":" not in entrypoint:
|
|
187
|
+
return None
|
|
188
|
+
|
|
189
|
+
path, _object_name = entrypoint.rsplit(":", 1)
|
|
190
|
+
if not path.endswith(".py"):
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
entrypoint_path = Path(path).expanduser()
|
|
194
|
+
if not entrypoint_path.is_absolute():
|
|
195
|
+
entrypoint_path = working_directory / entrypoint_path
|
|
196
|
+
return entrypoint_path.resolve()
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _has_entrypoint_file(entrypoint: str, working_directory: Path) -> bool:
|
|
200
|
+
entrypoint_path = _entrypoint_file_path(entrypoint, working_directory)
|
|
201
|
+
return entrypoint_path is not None and entrypoint_path.is_file()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
async def _ensure_entrypoint_in_workspace(
|
|
205
|
+
client: "PrefectClient",
|
|
206
|
+
deployment: "DeploymentResponse",
|
|
207
|
+
workspace_root: Path,
|
|
208
|
+
source_cwd: Path,
|
|
209
|
+
storage_base_path: Path | None,
|
|
210
|
+
) -> Path:
|
|
211
|
+
if _has_entrypoint_file(deployment.entrypoint, workspace_root):
|
|
212
|
+
return workspace_root
|
|
213
|
+
|
|
214
|
+
local_runtime_directory = _resolve_local_runtime_directory(
|
|
215
|
+
deployment.path, source_cwd, storage_base_path
|
|
216
|
+
)
|
|
217
|
+
if not deployment.storage_document_id and not _has_entrypoint_file(
|
|
218
|
+
deployment.entrypoint, local_runtime_directory
|
|
219
|
+
):
|
|
220
|
+
return workspace_root
|
|
221
|
+
|
|
222
|
+
await _pull_storage_into_workspace(
|
|
223
|
+
client,
|
|
224
|
+
deployment,
|
|
225
|
+
workspace_root,
|
|
226
|
+
source_cwd,
|
|
227
|
+
storage_base_path,
|
|
228
|
+
)
|
|
229
|
+
return workspace_root
|
|
230
|
+
|
|
231
|
+
|
|
177
232
|
@contextlib.contextmanager
|
|
178
233
|
def _redirect_stdout_to_stderr() -> Any:
|
|
179
234
|
stdout = sys.stdout
|
|
@@ -218,9 +273,12 @@ async def _pull_storage_into_workspace(
|
|
|
218
273
|
else None
|
|
219
274
|
)
|
|
220
275
|
else:
|
|
221
|
-
|
|
276
|
+
resolved_local_path = _resolve_local_deployment_path(
|
|
222
277
|
deployment.path, source_cwd, storage_base_path
|
|
223
278
|
)
|
|
279
|
+
from_path = (
|
|
280
|
+
resolved_local_path if resolved_local_path is not None else str(source_cwd)
|
|
281
|
+
)
|
|
224
282
|
storage_block = LocalFileSystem(basepath=from_path)
|
|
225
283
|
|
|
226
284
|
LOGGER.info("Downloading flow code from storage at %r", from_path)
|
|
@@ -253,11 +311,17 @@ async def prepare_workspace(
|
|
|
253
311
|
source_cwd,
|
|
254
312
|
storage_base_path,
|
|
255
313
|
)
|
|
256
|
-
|
|
257
|
-
|
|
314
|
+
local_runtime_directory = _resolve_local_runtime_directory(
|
|
315
|
+
deployment.path, source_cwd, storage_base_path
|
|
316
|
+
)
|
|
317
|
+
if not _has_entrypoint_file(
|
|
318
|
+
deployment.entrypoint, working_directory
|
|
319
|
+
) and _has_entrypoint_file(deployment.entrypoint, local_runtime_directory):
|
|
320
|
+
working_directory = local_runtime_directory
|
|
258
321
|
else:
|
|
322
|
+
working_directory = resolved_workspace_root
|
|
323
|
+
step_selected_working_directory = False
|
|
259
324
|
os.chdir(resolved_workspace_root)
|
|
260
|
-
working_directory = Path.cwd().resolve()
|
|
261
325
|
LOGGER.info("Running %s deployment pull step(s)", len(deployment.pull_steps))
|
|
262
326
|
|
|
263
327
|
def _track_step_workspace(
|
|
@@ -266,17 +330,19 @@ async def prepare_workspace(
|
|
|
266
330
|
step_start_cwd: Path | None,
|
|
267
331
|
step_end_cwd: Path | None,
|
|
268
332
|
) -> None:
|
|
269
|
-
nonlocal working_directory
|
|
333
|
+
nonlocal step_selected_working_directory, working_directory
|
|
270
334
|
|
|
271
335
|
if isinstance(step_output, dict) and step_output.get("directory"):
|
|
272
336
|
resolved_directory = _resolve_directory_output(
|
|
273
337
|
step_output, step_end_cwd
|
|
274
338
|
)
|
|
275
339
|
if resolved_directory is not None:
|
|
340
|
+
step_selected_working_directory = True
|
|
276
341
|
working_directory = resolved_directory
|
|
277
342
|
return
|
|
278
343
|
|
|
279
344
|
if step_end_cwd is not None and step_end_cwd != step_start_cwd:
|
|
345
|
+
step_selected_working_directory = True
|
|
280
346
|
working_directory = step_end_cwd
|
|
281
347
|
|
|
282
348
|
with _observe_step_completion(_track_step_workspace):
|
|
@@ -288,6 +354,18 @@ async def prepare_workspace(
|
|
|
288
354
|
logger=LOGGER,
|
|
289
355
|
)
|
|
290
356
|
|
|
357
|
+
if not step_selected_working_directory:
|
|
358
|
+
working_directory = await _ensure_entrypoint_in_workspace(
|
|
359
|
+
client,
|
|
360
|
+
deployment,
|
|
361
|
+
resolved_workspace_root,
|
|
362
|
+
source_cwd,
|
|
363
|
+
storage_base_path,
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
os.chdir(working_directory)
|
|
367
|
+
working_directory = Path.cwd().resolve()
|
|
368
|
+
|
|
291
369
|
project_root = _find_project_root(working_directory, resolved_workspace_root)
|
|
292
370
|
return PreparedWorkspace(
|
|
293
371
|
workspace_root=resolved_workspace_root,
|
|
@@ -167,6 +167,9 @@ def _pyproject_declares_prefect_dependency(pyproject: Path) -> bool:
|
|
|
167
167
|
|
|
168
168
|
|
|
169
169
|
def _uv_run_command(workspace: PreparedWorkspace) -> str | None:
|
|
170
|
+
if not get_current_settings().runner.auto_install_dependencies:
|
|
171
|
+
return None
|
|
172
|
+
|
|
170
173
|
project_root = workspace.project_root
|
|
171
174
|
if project_root is None:
|
|
172
175
|
return None
|
|
@@ -188,6 +191,7 @@ def _uv_run_command(workspace: PreparedWorkspace) -> str | None:
|
|
|
188
191
|
[
|
|
189
192
|
uv_executable,
|
|
190
193
|
"run",
|
|
194
|
+
"--no-default-groups",
|
|
191
195
|
"--project",
|
|
192
196
|
str(project_root),
|
|
193
197
|
"-m",
|
prefect/server/AGENTS.md
CHANGED
|
@@ -66,6 +66,7 @@ Both V1 and V2 UI bundles are served simultaneously when available: V1 at `PREFE
|
|
|
66
66
|
- `events/` — Server-side event processing: trigger evaluation, action execution, messaging, streaming (see also `../events/` for client-side schemas)
|
|
67
67
|
- `concurrency/` — Server-side concurrency management
|
|
68
68
|
- `logs/` — Log storage and retrieval
|
|
69
|
+
- `worker_communication/` — Pluggable server-side messaging to workers: cleanup delivery queue for expired/cancelled flow run teardown. The abstract interface is in `cleanup_queue/__init__.py`; the default in-memory backend (`cleanup_queue/memory.py`) is a process-level singleton and is not restart-safe. Configure `PREFECT_SERVER_WORKER_CHANNEL_CLEANUP_QUEUE_STORAGE` to point to a module exposing a concrete `WorkerCleanupQueue` subclass for HA or Redis-backed deployments.
|
|
69
70
|
|
|
70
71
|
## Related
|
|
71
72
|
|
prefect/server/__init__.py
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from prefect.server import models, orchestration, schemas, services
|
|
2
8
|
|
|
3
9
|
__all__ = ["models", "orchestration", "schemas", "services"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def __getattr__(name: str) -> object:
|
|
13
|
+
module_name = f"{__name__}.{name}"
|
|
14
|
+
try:
|
|
15
|
+
module = importlib.import_module(module_name)
|
|
16
|
+
except ModuleNotFoundError as exc:
|
|
17
|
+
if exc.name != module_name:
|
|
18
|
+
raise
|
|
19
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
|
|
20
|
+
|
|
21
|
+
globals()[name] = module
|
|
22
|
+
return module
|
prefect/server/api/__init__.py
CHANGED
|
@@ -1,33 +1,86 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from prefect.server.api import (
|
|
8
|
+
admin,
|
|
9
|
+
artifacts,
|
|
10
|
+
automations,
|
|
11
|
+
block_capabilities,
|
|
12
|
+
block_documents,
|
|
13
|
+
block_schemas,
|
|
14
|
+
block_types,
|
|
15
|
+
collections,
|
|
16
|
+
concurrency_limits,
|
|
17
|
+
concurrency_limits_v2,
|
|
18
|
+
csrf_token,
|
|
19
|
+
dependencies,
|
|
20
|
+
deployments,
|
|
21
|
+
events,
|
|
22
|
+
flow_run_states,
|
|
23
|
+
flow_runs,
|
|
24
|
+
flows,
|
|
25
|
+
logs,
|
|
26
|
+
middleware,
|
|
27
|
+
root,
|
|
28
|
+
run_history,
|
|
29
|
+
saved_searches,
|
|
30
|
+
server,
|
|
31
|
+
task_run_states,
|
|
32
|
+
task_runs,
|
|
33
|
+
task_workers,
|
|
34
|
+
templates,
|
|
35
|
+
ui,
|
|
36
|
+
variables,
|
|
37
|
+
work_queues,
|
|
38
|
+
workers,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
__all__ = [
|
|
42
|
+
"admin",
|
|
43
|
+
"artifacts",
|
|
44
|
+
"automations",
|
|
45
|
+
"block_capabilities",
|
|
46
|
+
"block_documents",
|
|
47
|
+
"block_schemas",
|
|
48
|
+
"block_types",
|
|
49
|
+
"collections",
|
|
50
|
+
"concurrency_limits",
|
|
51
|
+
"concurrency_limits_v2",
|
|
52
|
+
"csrf_token",
|
|
53
|
+
"dependencies",
|
|
54
|
+
"deployments",
|
|
55
|
+
"events",
|
|
56
|
+
"flow_run_states",
|
|
57
|
+
"flow_runs",
|
|
58
|
+
"flows",
|
|
59
|
+
"logs",
|
|
60
|
+
"middleware",
|
|
61
|
+
"root",
|
|
62
|
+
"run_history",
|
|
63
|
+
"saved_searches",
|
|
64
|
+
"server",
|
|
65
|
+
"task_run_states",
|
|
66
|
+
"task_runs",
|
|
67
|
+
"task_workers",
|
|
68
|
+
"templates",
|
|
69
|
+
"ui",
|
|
70
|
+
"variables",
|
|
71
|
+
"work_queues",
|
|
72
|
+
"workers",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def __getattr__(name: str) -> object:
|
|
77
|
+
module_name = f"{__name__}.{name}"
|
|
78
|
+
try:
|
|
79
|
+
module = importlib.import_module(module_name)
|
|
80
|
+
except ModuleNotFoundError as exc:
|
|
81
|
+
if exc.name != module_name:
|
|
82
|
+
raise
|
|
83
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
|
|
84
|
+
|
|
85
|
+
globals()[name] = module
|
|
86
|
+
return module
|
|
@@ -1159,8 +1159,9 @@ class RetryFailedTasks(TaskRunOrchestrationRule):
|
|
|
1159
1159
|
else:
|
|
1160
1160
|
base_delay = delay or 0
|
|
1161
1161
|
|
|
1162
|
-
# guard against negative relative jitter inputs
|
|
1163
|
-
|
|
1162
|
+
# guard against negative relative jitter inputs; also guard against
|
|
1163
|
+
# base_delay == 0: clamped_poisson_interval(0, ...) divides by zero.
|
|
1164
|
+
if run_settings.retry_jitter_factor and base_delay > 0:
|
|
1164
1165
|
delay = clamped_poisson_interval(
|
|
1165
1166
|
base_delay, clamping_factor=run_settings.retry_jitter_factor
|
|
1166
1167
|
)
|
|
@@ -1,25 +1,44 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from prefect.server.schemas import (
|
|
8
|
+
actions,
|
|
9
|
+
core,
|
|
10
|
+
filters,
|
|
11
|
+
internal,
|
|
12
|
+
responses,
|
|
13
|
+
schedules,
|
|
14
|
+
sorting,
|
|
15
|
+
states,
|
|
16
|
+
statuses,
|
|
17
|
+
ui,
|
|
18
|
+
)
|
|
13
19
|
|
|
14
20
|
__all__ = [
|
|
15
21
|
"actions",
|
|
16
22
|
"core",
|
|
17
23
|
"filters",
|
|
24
|
+
"internal",
|
|
18
25
|
"responses",
|
|
19
26
|
"schedules",
|
|
20
27
|
"sorting",
|
|
21
28
|
"states",
|
|
22
29
|
"statuses",
|
|
23
|
-
"internal",
|
|
24
30
|
"ui",
|
|
25
31
|
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def __getattr__(name: str) -> object:
|
|
35
|
+
module_name = f"{__name__}.{name}"
|
|
36
|
+
try:
|
|
37
|
+
module = importlib.import_module(module_name)
|
|
38
|
+
except ModuleNotFoundError as exc:
|
|
39
|
+
if exc.name != module_name:
|
|
40
|
+
raise
|
|
41
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
|
|
42
|
+
|
|
43
|
+
globals()[name] = module
|
|
44
|
+
return module
|
|
@@ -74,7 +74,12 @@ def _get_select_deployments_to_schedule_query(
|
|
|
74
74
|
db.FlowRun.deployment_id == db.DeploymentSchedule.deployment_id,
|
|
75
75
|
db.FlowRun.state_type == StateType.SCHEDULED,
|
|
76
76
|
db.FlowRun.next_scheduled_start_time >= right_now,
|
|
77
|
-
|
|
77
|
+
# `== true` (not `.is_(True)`) so the predicate matches the
|
|
78
|
+
# `auto_scheduled = true` clause of the partial index
|
|
79
|
+
# `ix_flow_run__schedule_id_scheduler`. PostgreSQL's predicate
|
|
80
|
+
# implication prover does not treat `IS true` as implying
|
|
81
|
+
# `= true`, so `.is_(True)` silently disqualifies the index.
|
|
82
|
+
db.FlowRun.auto_scheduled == sa.true(),
|
|
78
83
|
schedule_id_match,
|
|
79
84
|
)
|
|
80
85
|
.correlate(db.DeploymentSchedule)
|
|
@@ -88,7 +93,7 @@ def _get_select_deployments_to_schedule_query(
|
|
|
88
93
|
db.FlowRun.deployment_id == db.DeploymentSchedule.deployment_id,
|
|
89
94
|
db.FlowRun.state_type == StateType.SCHEDULED,
|
|
90
95
|
db.FlowRun.next_scheduled_start_time >= right_now,
|
|
91
|
-
db.FlowRun.auto_scheduled.
|
|
96
|
+
db.FlowRun.auto_scheduled == sa.true(),
|
|
92
97
|
schedule_id_match,
|
|
93
98
|
)
|
|
94
99
|
.correlate(db.DeploymentSchedule)
|