prefect 3.6.5__py3-none-any.whl → 3.6.5.dev1__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/_build_info.py +3 -3
- prefect/blocks/notifications.py +0 -71
- prefect/cli/deploy/_models.py +2 -3
- prefect/concurrency/services.py +6 -71
- prefect/events/schemas/events.py +0 -4
- prefect/events/utilities.py +0 -9
- prefect/exceptions.py +0 -11
- prefect/flows.py +1 -1
- prefect/results.py +1 -1
- prefect/server/database/dependencies.py +2 -2
- prefect/server/events/schemas/events.py +0 -4
- prefect/server/events/services/event_persister.py +0 -1
- prefect/server/events/services/triggers.py +1 -4
- prefect/server/models/task_runs.py +9 -30
- prefect/server/schemas/filters.py +5 -8
- prefect/server/schemas/sorting.py +23 -37
- prefect/server/services/task_run_recorder.py +0 -1
- prefect/server/ui/assets/404-U2KQOqzV.js +2 -0
- prefect/server/ui/assets/{404-cNTfarkM.js.map → 404-U2KQOqzV.js.map} +1 -1
- prefect/server/ui/assets/AppRouterView-DnlTfFmZ.js +2 -0
- prefect/server/ui/assets/AppRouterView-DnlTfFmZ.js.map +1 -0
- prefect/server/ui/assets/{Artifact-D9pQzQmC.js → Artifact-C_GJ_Wwg.js} +2 -2
- prefect/server/ui/assets/{Artifact-D9pQzQmC.js.map → Artifact-C_GJ_Wwg.js.map} +1 -1
- prefect/server/ui/assets/{ArtifactKey-Dci9S885.js → ArtifactKey-CJu4-81M.js} +2 -2
- prefect/server/ui/assets/{ArtifactKey-Dci9S885.js.map → ArtifactKey-CJu4-81M.js.map} +1 -1
- prefect/server/ui/assets/{Artifacts-3_tnsqcP.js → Artifacts-DBLGdr0r.js} +2 -2
- prefect/server/ui/assets/{Artifacts-3_tnsqcP.js.map → Artifacts-DBLGdr0r.js.map} +1 -1
- prefect/server/ui/assets/{Automation-WWzefaIP.js → Automation-CHjqUyhY.js} +2 -2
- prefect/server/ui/assets/{Automation-WWzefaIP.js.map → Automation-CHjqUyhY.js.map} +1 -1
- prefect/server/ui/assets/{AutomationCreate-BXntaZwK.js → AutomationCreate-B9suteEb.js} +2 -2
- prefect/server/ui/assets/{AutomationCreate-BXntaZwK.js.map → AutomationCreate-B9suteEb.js.map} +1 -1
- prefect/server/ui/assets/{AutomationEdit-Nmj5pgV7.js → AutomationEdit-0LbdV6Ww.js} +2 -2
- prefect/server/ui/assets/{AutomationEdit-Nmj5pgV7.js.map → AutomationEdit-0LbdV6Ww.js.map} +1 -1
- prefect/server/ui/assets/{AutomationWizard.vue_vue_type_script_setup_true_lang-C0eUtYtR.js → AutomationWizard.vue_vue_type_script_setup_true_lang-BKawaUBD.js} +2 -2
- prefect/server/ui/assets/{AutomationWizard.vue_vue_type_script_setup_true_lang-C0eUtYtR.js.map → AutomationWizard.vue_vue_type_script_setup_true_lang-BKawaUBD.js.map} +1 -1
- prefect/server/ui/assets/{Automations-BTByQSIa.js → Automations-Bx2GWCSi.js} +2 -2
- prefect/server/ui/assets/{Automations-BTByQSIa.js.map → Automations-Bx2GWCSi.js.map} +1 -1
- prefect/server/ui/assets/{BlockEdit-TXsu808p.js → BlockEdit-D0ze825D.js} +2 -2
- prefect/server/ui/assets/{BlockEdit-TXsu808p.js.map → BlockEdit-D0ze825D.js.map} +1 -1
- prefect/server/ui/assets/{BlockView-ClO3cjvJ.js → BlockView-Bd1J8dbH.js} +2 -2
- prefect/server/ui/assets/{BlockView-ClO3cjvJ.js.map → BlockView-Bd1J8dbH.js.map} +1 -1
- prefect/server/ui/assets/{Blocks-BkExfYYT.js → Blocks-BfGokvlq.js} +2 -2
- prefect/server/ui/assets/{Blocks-BkExfYYT.js.map → Blocks-BfGokvlq.js.map} +1 -1
- prefect/server/ui/assets/{BlocksCatalog-EKrfg03a.js → BlocksCatalog-DIoY03PO.js} +2 -2
- prefect/server/ui/assets/{BlocksCatalog-EKrfg03a.js.map → BlocksCatalog-DIoY03PO.js.map} +1 -1
- prefect/server/ui/assets/{BlocksCatalogCreate-BkEaFm81.js → BlocksCatalogCreate-KGE2Eauv.js} +2 -2
- prefect/server/ui/assets/{BlocksCatalogCreate-BkEaFm81.js.map → BlocksCatalogCreate-KGE2Eauv.js.map} +1 -1
- prefect/server/ui/assets/{BlocksCatalogView-Dra7rjpU.js → BlocksCatalogView-qlD5J9Xo.js} +2 -2
- prefect/server/ui/assets/{BlocksCatalogView-Dra7rjpU.js.map → BlocksCatalogView-qlD5J9Xo.js.map} +1 -1
- prefect/server/ui/assets/{ConcurrencyLimit-Dja_e7Qi.js → ConcurrencyLimit-CV4LJtq0.js} +2 -2
- prefect/server/ui/assets/{ConcurrencyLimit-Dja_e7Qi.js.map → ConcurrencyLimit-CV4LJtq0.js.map} +1 -1
- prefect/server/ui/assets/{ConcurrencyLimits-BhgfLozN.js → ConcurrencyLimits-DdzVXpyn.js} +2 -2
- prefect/server/ui/assets/{ConcurrencyLimits-BhgfLozN.js.map → ConcurrencyLimits-DdzVXpyn.js.map} +1 -1
- prefect/server/ui/assets/{Dashboard-DU4NaIUe.js → Dashboard-Bhe8HF89.js} +2 -2
- prefect/server/ui/assets/{Dashboard-DU4NaIUe.js.map → Dashboard-Bhe8HF89.js.map} +1 -1
- prefect/server/ui/assets/{Deployment-26av4B2n.js → Deployment-Dy6W3fmS.js} +2 -2
- prefect/server/ui/assets/{Deployment-26av4B2n.js.map → Deployment-Dy6W3fmS.js.map} +1 -1
- prefect/server/ui/assets/{DeploymentDuplicate-DrHdbfGO.js → DeploymentDuplicate-D--6CH0b.js} +2 -2
- prefect/server/ui/assets/{DeploymentDuplicate-DrHdbfGO.js.map → DeploymentDuplicate-D--6CH0b.js.map} +1 -1
- prefect/server/ui/assets/{DeploymentEdit-CTlfod0i.js → DeploymentEdit-CCWux4XP.js} +2 -2
- prefect/server/ui/assets/{DeploymentEdit-CTlfod0i.js.map → DeploymentEdit-CCWux4XP.js.map} +1 -1
- prefect/server/ui/assets/{Deployments-BqQB3LD3.js → Deployments-DV03_V2d.js} +2 -2
- prefect/server/ui/assets/{Deployments-BqQB3LD3.js.map → Deployments-DV03_V2d.js.map} +1 -1
- prefect/server/ui/assets/{Event-Ddqkp5Eb.js → Event-CR8eAMth.js} +2 -2
- prefect/server/ui/assets/{Event-Ddqkp5Eb.js.map → Event-CR8eAMth.js.map} +1 -1
- prefect/server/ui/assets/{Events-DVhuODUR.js → Events-73DIQpjK.js} +2 -2
- prefect/server/ui/assets/{Events-DVhuODUR.js.map → Events-73DIQpjK.js.map} +1 -1
- prefect/server/ui/assets/{Flow-CAl7lKeq.js → Flow-Dj94GRjt.js} +2 -2
- prefect/server/ui/assets/{Flow-CAl7lKeq.js.map → Flow-Dj94GRjt.js.map} +1 -1
- prefect/server/ui/assets/{FlowRun-h0x5CxKG.js → FlowRun-Difiqz5F.js} +2 -2
- prefect/server/ui/assets/{FlowRun-h0x5CxKG.js.map → FlowRun-Difiqz5F.js.map} +1 -1
- prefect/server/ui/assets/{FlowRunCreate-DLYa_njJ.js → FlowRunCreate-C15hcUnz.js} +2 -2
- prefect/server/ui/assets/{FlowRunCreate-DLYa_njJ.js.map → FlowRunCreate-C15hcUnz.js.map} +1 -1
- prefect/server/ui/assets/{Flows-DJ-cJREs.js → Flows-y-EKyQtq.js} +2 -2
- prefect/server/ui/assets/{Flows-DJ-cJREs.js.map → Flows-y-EKyQtq.js.map} +1 -1
- prefect/server/ui/assets/{Runs-rPCeL6qJ.js → Runs-ChDNmYZa.js} +2 -2
- prefect/server/ui/assets/{Runs-rPCeL6qJ.js.map → Runs-ChDNmYZa.js.map} +1 -1
- prefect/server/ui/assets/{RunsPageWithDefaultFilter-CceYGNey-BtMS3SJk.js → RunsPageWithDefaultFilter-CceYGNey-Ca54l1eH.js} +2 -2
- prefect/server/ui/assets/{RunsPageWithDefaultFilter-CceYGNey-BtMS3SJk.js.map → RunsPageWithDefaultFilter-CceYGNey-Ca54l1eH.js.map} +1 -1
- prefect/server/ui/assets/{Settings-w2bn-3ns.js → Settings-DKQCv00B.js} +2 -2
- prefect/server/ui/assets/{Settings-w2bn-3ns.js.map → Settings-DKQCv00B.js.map} +1 -1
- prefect/server/ui/assets/{TaskRun-CPjqF2yp.js → TaskRun-U9jCz08z.js} +2 -2
- prefect/server/ui/assets/{TaskRun-CPjqF2yp.js.map → TaskRun-U9jCz08z.js.map} +1 -1
- prefect/server/ui/assets/{Unauthenticated-Yg8XqjIn.js → Unauthenticated-DNxb3CVl.js} +2 -2
- prefect/server/ui/assets/{Unauthenticated-Yg8XqjIn.js.map → Unauthenticated-DNxb3CVl.js.map} +1 -1
- prefect/server/ui/assets/{Variables-CaD3bA0b.js → Variables-Db73bUnI.js} +2 -2
- prefect/server/ui/assets/{Variables-CaD3bA0b.js.map → Variables-Db73bUnI.js.map} +1 -1
- prefect/server/ui/assets/{WorkPool-BCBo-n5K.js → WorkPool-DvcSLUL2.js} +2 -2
- prefect/server/ui/assets/{WorkPool-BCBo-n5K.js.map → WorkPool-DvcSLUL2.js.map} +1 -1
- prefect/server/ui/assets/{WorkPoolCreate-DZbqjYpg.js → WorkPoolCreate-Ba51_j6H.js} +2 -2
- prefect/server/ui/assets/{WorkPoolCreate-DZbqjYpg.js.map → WorkPoolCreate-Ba51_j6H.js.map} +1 -1
- prefect/server/ui/assets/{WorkPoolEdit-BNqs1-RP.js → WorkPoolEdit-BX6sq21G.js} +2 -2
- prefect/server/ui/assets/{WorkPoolEdit-BNqs1-RP.js.map → WorkPoolEdit-BX6sq21G.js.map} +1 -1
- prefect/server/ui/assets/{WorkPoolQueue-CpbBSFRw.js → WorkPoolQueue-CrhLOB9z.js} +2 -2
- prefect/server/ui/assets/{WorkPoolQueue-CpbBSFRw.js.map → WorkPoolQueue-CrhLOB9z.js.map} +1 -1
- prefect/server/ui/assets/{WorkPoolQueueCreate-DavJ3kww.js → WorkPoolQueueCreate-NBYMDZiu.js} +2 -2
- prefect/server/ui/assets/{WorkPoolQueueCreate-DavJ3kww.js.map → WorkPoolQueueCreate-NBYMDZiu.js.map} +1 -1
- prefect/server/ui/assets/{WorkPoolQueueEdit-B-UNXtv9.js → WorkPoolQueueEdit-aDYoZnft.js} +2 -2
- prefect/server/ui/assets/{WorkPoolQueueEdit-B-UNXtv9.js.map → WorkPoolQueueEdit-aDYoZnft.js.map} +1 -1
- prefect/server/ui/assets/{WorkPools-8Aq4RA_W.js → WorkPools-A1onpvmM.js} +2 -2
- prefect/server/ui/assets/{WorkPools-8Aq4RA_W.js.map → WorkPools-A1onpvmM.js.map} +1 -1
- prefect/server/ui/assets/{WorkQueueToWorkPoolQueueRedirect-C9AtKf4r-ByNdkwZz.js → WorkQueueToWorkPoolQueueRedirect-C9AtKf4r-DpZf1FHA.js} +2 -2
- prefect/server/ui/assets/{WorkQueueToWorkPoolQueueRedirect-C9AtKf4r-ByNdkwZz.js.map → WorkQueueToWorkPoolQueueRedirect-C9AtKf4r-DpZf1FHA.js.map} +1 -1
- prefect/server/ui/assets/{index-B2Mqn-oh.js → index-BRrm8IYN.js} +4 -4
- prefect/server/ui/assets/{index-B2Mqn-oh.js.map → index-BRrm8IYN.js.map} +1 -1
- prefect/server/ui/assets/{mapper-Dc-EvePY.js → mapper-DJ53lQ_S.js} +2 -2
- prefect/server/ui/assets/{mapper-Dc-EvePY.js.map → mapper-DJ53lQ_S.js.map} +1 -1
- prefect/server/ui/assets/useCan-BidbvPHp.js +2 -0
- prefect/server/ui/assets/{useCan-UjdHjQ2R.js.map → useCan-BidbvPHp.js.map} +1 -1
- prefect/server/ui/assets/{usePageTitle-CuMQMQX5.js → usePageTitle-D8ThwtpL.js} +2 -2
- prefect/server/ui/assets/{usePageTitle-CuMQMQX5.js.map → usePageTitle-D8ThwtpL.js.map} +1 -1
- prefect/server/ui/assets/{usePrefectApi-CVNyESB6.js → usePrefectApi-CPise1aa.js} +2 -2
- prefect/server/ui/assets/{usePrefectApi-CVNyESB6.js.map → usePrefectApi-CPise1aa.js.map} +1 -1
- prefect/server/ui/index.html +1 -1
- prefect/settings/models/server/services.py +0 -23
- prefect/task_engine.py +32 -138
- prefect/tasks.py +1 -2
- prefect/testing/fixtures.py +0 -4
- prefect/workers/base.py +1 -23
- {prefect-3.6.5.dist-info → prefect-3.6.5.dev1.dist-info}/METADATA +1 -1
- {prefect-3.6.5.dist-info → prefect-3.6.5.dev1.dist-info}/RECORD +124 -125
- {prefect-3.6.5.dist-info → prefect-3.6.5.dev1.dist-info}/WHEEL +1 -1
- prefect/_states.py +0 -292
- prefect/server/ui/assets/404-cNTfarkM.js +0 -2
- prefect/server/ui/assets/AppRouterView-CsqzqHZP.js +0 -2
- prefect/server/ui/assets/AppRouterView-CsqzqHZP.js.map +0 -1
- prefect/server/ui/assets/useCan-UjdHjQ2R.js +0 -2
- {prefect-3.6.5.dist-info → prefect-3.6.5.dev1.dist-info}/entry_points.txt +0 -0
- {prefect-3.6.5.dist-info → prefect-3.6.5.dev1.dist-info}/licenses/LICENSE +0 -0
prefect/_build_info.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Generated by versioningit
|
|
2
|
-
__version__ = "3.6.5"
|
|
3
|
-
__build_date__ = "2025-
|
|
4
|
-
__git_commit__ = "
|
|
2
|
+
__version__ = "3.6.5.dev1"
|
|
3
|
+
__build_date__ = "2025-11-23 08:08:52.119698+00:00"
|
|
4
|
+
__git_commit__ = "8db23793dc00b6daae43d30b3d5b902dc91373e1"
|
|
5
5
|
__dirty__ = False
|
prefect/blocks/notifications.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import re
|
|
5
4
|
from abc import ABC
|
|
6
5
|
from typing import Any, Optional, cast
|
|
7
6
|
|
|
@@ -106,9 +105,6 @@ class SlackWebhook(AppriseNotificationBlock):
|
|
|
106
105
|
"""
|
|
107
106
|
Enables sending notifications via a provided Slack webhook.
|
|
108
107
|
|
|
109
|
-
Supports both standard Slack webhooks (hooks.slack.com) and Slack GovCloud
|
|
110
|
-
webhooks (hooks.slack-gov.com).
|
|
111
|
-
|
|
112
108
|
Examples:
|
|
113
109
|
Load a saved Slack webhook and send a message:
|
|
114
110
|
```python
|
|
@@ -134,73 +130,6 @@ class SlackWebhook(AppriseNotificationBlock):
|
|
|
134
130
|
examples=["https://hooks.slack.com/XXX"],
|
|
135
131
|
)
|
|
136
132
|
|
|
137
|
-
_SLACK_WEBHOOK_URL_PATTERN: re.Pattern[str] = re.compile(
|
|
138
|
-
r"^https?://(?P<host>hooks\.slack(?:-gov)?\.com)/services/"
|
|
139
|
-
r"(?P<token_a>[A-Z0-9]+)/"
|
|
140
|
-
r"(?P<token_b>[A-Z0-9]+)/"
|
|
141
|
-
r"(?P<token_c>[A-Z0-9]+)/?$",
|
|
142
|
-
re.I,
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
def block_initialization(self) -> None:
|
|
146
|
-
"""Initialize the Slack webhook client.
|
|
147
|
-
|
|
148
|
-
This method handles both standard Slack webhooks and Slack GovCloud webhooks.
|
|
149
|
-
Apprise's built-in Slack plugin only supports hooks.slack.com, so we need to
|
|
150
|
-
manually construct the NotifySlack instance for slack-gov.com URLs to ensure
|
|
151
|
-
notifications are sent to the correct host.
|
|
152
|
-
|
|
153
|
-
See: https://github.com/caronc/apprise/issues/XXXX (upstream issue)
|
|
154
|
-
"""
|
|
155
|
-
webhook_url = self.url.get_secret_value()
|
|
156
|
-
match = self._SLACK_WEBHOOK_URL_PATTERN.match(webhook_url)
|
|
157
|
-
|
|
158
|
-
# If it's not a recognized Slack webhook shape, delegate to the base behavior.
|
|
159
|
-
# This lets restricted-URL checks and existing Apprise validation run as before.
|
|
160
|
-
if not match:
|
|
161
|
-
self._start_apprise_client(self.url)
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
host = match.group("host")
|
|
165
|
-
|
|
166
|
-
# Standard Slack: let Apprise handle it like it always has.
|
|
167
|
-
if host == "hooks.slack.com":
|
|
168
|
-
self._start_apprise_client(self.url)
|
|
169
|
-
return
|
|
170
|
-
|
|
171
|
-
# GovCloud: we know it's a valid Slack webhook and host is hooks.slack-gov.com
|
|
172
|
-
# We must add the NotifySlack instance directly to the apprise client
|
|
173
|
-
# (rather than passing slack_instance.url()) because the webhook_url
|
|
174
|
-
# override is an instance attribute that would be lost if apprise
|
|
175
|
-
# re-parsed the URL string.
|
|
176
|
-
from apprise import Apprise, AppriseAsset
|
|
177
|
-
|
|
178
|
-
try:
|
|
179
|
-
from apprise.plugins.slack import NotifySlack
|
|
180
|
-
except ImportError:
|
|
181
|
-
from apprise.plugins.NotifySlack import (
|
|
182
|
-
NotifySlack, # pyright: ignore[reportMissingImports]
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
token_a = match.group("token_a")
|
|
186
|
-
token_b = match.group("token_b")
|
|
187
|
-
token_c = match.group("token_c")
|
|
188
|
-
|
|
189
|
-
slack_instance = NotifySlack(
|
|
190
|
-
token_a=token_a,
|
|
191
|
-
token_b=token_b,
|
|
192
|
-
token_c=token_c,
|
|
193
|
-
)
|
|
194
|
-
slack_instance.webhook_url = f"https://{host}/services"
|
|
195
|
-
|
|
196
|
-
prefect_app_data = AppriseAsset(
|
|
197
|
-
app_id="Prefect Notifications",
|
|
198
|
-
app_desc="Prefect Notifications",
|
|
199
|
-
app_url="https://prefect.io",
|
|
200
|
-
)
|
|
201
|
-
self._apprise_client = Apprise(asset=prefect_app_data)
|
|
202
|
-
self._apprise_client.add(slack_instance)
|
|
203
|
-
|
|
204
133
|
|
|
205
134
|
class MicrosoftTeamsWebhook(AppriseNotificationBlock):
|
|
206
135
|
"""
|
prefect/cli/deploy/_models.py
CHANGED
|
@@ -7,6 +7,7 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_valida
|
|
|
7
7
|
from prefect._experimental.sla.objects import SlaTypes
|
|
8
8
|
from prefect.client.schemas.actions import DeploymentScheduleCreate
|
|
9
9
|
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
|
10
|
+
from prefect.events import DeploymentTriggerTypes
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class WorkPoolConfig(BaseModel):
|
|
@@ -51,9 +52,7 @@ class DeploymentConfig(BaseModel):
|
|
|
51
52
|
work_pool: Optional[WorkPoolConfig] = None
|
|
52
53
|
|
|
53
54
|
# automations metadata
|
|
54
|
-
|
|
55
|
-
# Strict validation happens later in _initialize_deployment_triggers after template resolution
|
|
56
|
-
triggers: Optional[List[Dict[str, Any]]] = None
|
|
55
|
+
triggers: Optional[List[DeploymentTriggerTypes]] = None
|
|
57
56
|
sla: Optional[List[SlaTypes]] = None
|
|
58
57
|
|
|
59
58
|
|
prefect/concurrency/services.py
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import json
|
|
3
2
|
from collections.abc import AsyncGenerator
|
|
4
3
|
from contextlib import asynccontextmanager
|
|
5
|
-
from threading import Lock
|
|
6
4
|
from typing import TYPE_CHECKING, Literal, Optional
|
|
7
|
-
from uuid import uuid4
|
|
8
5
|
|
|
9
|
-
import cachetools
|
|
10
6
|
import httpx
|
|
11
7
|
from starlette import status
|
|
12
8
|
from typing_extensions import TypeAlias, Unpack
|
|
@@ -20,14 +16,6 @@ if TYPE_CHECKING:
|
|
|
20
16
|
from prefect.client.orchestration import PrefectClient
|
|
21
17
|
from prefect.client.schemas.objects import ConcurrencyLeaseHolder
|
|
22
18
|
|
|
23
|
-
# Shared cache for tags with no concurrency limits.
|
|
24
|
-
# When a set of tags is known to have no limits, we cache that result
|
|
25
|
-
# to avoid unnecessary API calls.
|
|
26
|
-
_no_limits_cache: cachetools.TTLCache[frozenset[str], bool] = cachetools.TTLCache(
|
|
27
|
-
maxsize=1000, ttl=5.0
|
|
28
|
-
)
|
|
29
|
-
_cache_lock = Lock()
|
|
30
|
-
|
|
31
19
|
_Item: TypeAlias = tuple[
|
|
32
20
|
int, Literal["concurrency", "rate_limit"], Optional[float], Optional[int]
|
|
33
21
|
]
|
|
@@ -139,37 +127,16 @@ class ConcurrencySlotAcquisitionWithLeaseService(
|
|
|
139
127
|
httpx.HTTPStatusError: If the server returns an error other than 423 LOCKED
|
|
140
128
|
TimeoutError: If acquisition times out
|
|
141
129
|
"""
|
|
142
|
-
use_cache = _should_use_cache(self.concurrency_limit_names, holder)
|
|
143
|
-
cache_key = frozenset(self.concurrency_limit_names)
|
|
144
|
-
|
|
145
130
|
with timeout_async(seconds=timeout_seconds):
|
|
146
131
|
while True:
|
|
147
132
|
try:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
await self._client.increment_concurrency_slots_with_lease(
|
|
155
|
-
names=self.concurrency_limit_names,
|
|
156
|
-
slots=slots,
|
|
157
|
-
mode=mode,
|
|
158
|
-
lease_duration=lease_duration,
|
|
159
|
-
holder=holder,
|
|
160
|
-
)
|
|
133
|
+
return await self._client.increment_concurrency_slots_with_lease(
|
|
134
|
+
names=self.concurrency_limit_names,
|
|
135
|
+
slots=slots,
|
|
136
|
+
mode=mode,
|
|
137
|
+
lease_duration=lease_duration,
|
|
138
|
+
holder=holder,
|
|
161
139
|
)
|
|
162
|
-
|
|
163
|
-
if use_cache:
|
|
164
|
-
try:
|
|
165
|
-
response_data = response.json()
|
|
166
|
-
if not response_data.get("limits"):
|
|
167
|
-
with _cache_lock:
|
|
168
|
-
_no_limits_cache[cache_key] = True
|
|
169
|
-
except Exception:
|
|
170
|
-
pass
|
|
171
|
-
|
|
172
|
-
return response
|
|
173
140
|
except httpx.HTTPStatusError as exc:
|
|
174
141
|
if exc.response.status_code != status.HTTP_423_LOCKED:
|
|
175
142
|
raise
|
|
@@ -184,35 +151,3 @@ class ConcurrencySlotAcquisitionWithLeaseService(
|
|
|
184
151
|
await asyncio.sleep(retry_after)
|
|
185
152
|
if max_retries is not None:
|
|
186
153
|
max_retries -= 1
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
def _should_use_cache(
|
|
190
|
-
names: list[str], holder: Optional["ConcurrencyLeaseHolder"]
|
|
191
|
-
) -> bool:
|
|
192
|
-
"""Determine if caching should be used for this concurrency acquisition.
|
|
193
|
-
|
|
194
|
-
Caching is only enabled for task-run tag-based concurrency checks to avoid
|
|
195
|
-
unnecessary API calls when no limits exist for those tags. This specifically
|
|
196
|
-
targets the task engine path that uses names like "tag:..." with a task_run holder.
|
|
197
|
-
"""
|
|
198
|
-
if holder is None:
|
|
199
|
-
return False
|
|
200
|
-
if getattr(holder, "type", None) != "task_run":
|
|
201
|
-
return False
|
|
202
|
-
if not names:
|
|
203
|
-
return False
|
|
204
|
-
return all(name.startswith("tag:") for name in names)
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
def _create_empty_limits_response() -> httpx.Response:
|
|
208
|
-
"""Create a synthetic httpx.Response indicating no concurrency limits exist.
|
|
209
|
-
|
|
210
|
-
This is used when we've cached that a set of tags has no limits,
|
|
211
|
-
allowing us to skip the API call entirely.
|
|
212
|
-
"""
|
|
213
|
-
response_data = {"lease_id": str(uuid4()), "limits": []}
|
|
214
|
-
return httpx.Response(
|
|
215
|
-
status_code=200,
|
|
216
|
-
content=json.dumps(response_data).encode(),
|
|
217
|
-
headers={"content-type": "application/json"},
|
|
218
|
-
)
|
prefect/events/schemas/events.py
CHANGED
|
@@ -149,10 +149,6 @@ class Event(PrefectBaseModel):
|
|
|
149
149
|
),
|
|
150
150
|
)
|
|
151
151
|
|
|
152
|
-
@property
|
|
153
|
-
def size_bytes(self) -> int:
|
|
154
|
-
return len(self.model_dump_json().encode())
|
|
155
|
-
|
|
156
152
|
@property
|
|
157
153
|
def involved_resources(self) -> Sequence[Resource]:
|
|
158
154
|
return [self.resource] + list(self.related)
|
prefect/events/utilities.py
CHANGED
|
@@ -6,9 +6,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
6
6
|
from uuid import UUID
|
|
7
7
|
|
|
8
8
|
import prefect.types._datetime
|
|
9
|
-
from prefect.exceptions import EventTooLarge
|
|
10
9
|
from prefect.logging.loggers import get_logger
|
|
11
|
-
from prefect.settings import get_current_settings
|
|
12
10
|
|
|
13
11
|
from .clients import (
|
|
14
12
|
AssertingEventsClient,
|
|
@@ -96,16 +94,9 @@ def emit_event(
|
|
|
96
94
|
event_kwargs["follows"] = follows.id
|
|
97
95
|
|
|
98
96
|
event_obj = Event(**event_kwargs)
|
|
99
|
-
|
|
100
|
-
max_size = get_current_settings().server.events.maximum_size_bytes
|
|
101
|
-
if event_obj.size_bytes > max_size:
|
|
102
|
-
raise EventTooLarge(event_obj.size_bytes, max_size)
|
|
103
|
-
|
|
104
97
|
worker_instance.send(event_obj)
|
|
105
98
|
|
|
106
99
|
return event_obj
|
|
107
|
-
except EventTooLarge:
|
|
108
|
-
raise
|
|
109
100
|
except Exception:
|
|
110
101
|
logger.exception(f"Error emitting event: {event}")
|
|
111
102
|
return None
|
prefect/exceptions.py
CHANGED
|
@@ -446,17 +446,6 @@ class ConfigurationError(PrefectException):
|
|
|
446
446
|
"""
|
|
447
447
|
|
|
448
448
|
|
|
449
|
-
class EventTooLarge(PrefectException):
|
|
450
|
-
"""
|
|
451
|
-
Raised when an event exceeds the configured maximum size.
|
|
452
|
-
"""
|
|
453
|
-
|
|
454
|
-
def __init__(self, size: int, maximum: int):
|
|
455
|
-
super().__init__(f"Event is too large to emit ({size} > {maximum} bytes)")
|
|
456
|
-
self.size = size
|
|
457
|
-
self.maximum = maximum
|
|
458
|
-
|
|
459
|
-
|
|
460
449
|
class ProfileSettingsValidationError(PrefectException):
|
|
461
450
|
"""
|
|
462
451
|
Raised when a profile settings are invalid.
|
prefect/flows.py
CHANGED
|
@@ -372,7 +372,7 @@ class Flow(Generic[P, R]):
|
|
|
372
372
|
persist_result = True
|
|
373
373
|
|
|
374
374
|
self.persist_result = persist_result
|
|
375
|
-
if result_storage and not isinstance(result_storage,
|
|
375
|
+
if result_storage and not isinstance(result_storage, str):
|
|
376
376
|
if getattr(result_storage, "_block_document_id", None) is None:
|
|
377
377
|
raise TypeError(
|
|
378
378
|
"Result storage configuration must be persisted server-side."
|
prefect/results.py
CHANGED
|
@@ -61,7 +61,7 @@ if TYPE_CHECKING:
|
|
|
61
61
|
from prefect.transactions import IsolationLevel
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
ResultStorage = Union[WritableFileSystem, str
|
|
64
|
+
ResultStorage = Union[WritableFileSystem, str]
|
|
65
65
|
ResultSerializer = Union[Serializer, str]
|
|
66
66
|
LITERAL_TYPES: set[type] = {type(None), bool, UUID}
|
|
67
67
|
|
|
@@ -31,12 +31,12 @@ from prefect.server.database.configurations import (
|
|
|
31
31
|
AsyncPostgresConfiguration,
|
|
32
32
|
BaseDatabaseConfiguration,
|
|
33
33
|
)
|
|
34
|
-
from prefect.server.database.interface import PrefectDBInterface
|
|
35
34
|
from prefect.server.utilities.database import get_dialect
|
|
36
35
|
from prefect.server.utilities.schemas import PrefectDescriptorBase
|
|
37
36
|
from prefect.settings import PREFECT_API_DATABASE_CONNECTION_URL
|
|
38
37
|
|
|
39
38
|
if TYPE_CHECKING:
|
|
39
|
+
from prefect.server.database.interface import PrefectDBInterface
|
|
40
40
|
from prefect.server.database.orm_models import BaseORMConfiguration
|
|
41
41
|
from prefect.server.database.query_components import BaseQueryComponents
|
|
42
42
|
|
|
@@ -65,7 +65,7 @@ MODELS_DEPENDENCIES: _ModelDependencies = {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def provide_database_interface() -> PrefectDBInterface:
|
|
68
|
+
def provide_database_interface() -> "PrefectDBInterface":
|
|
69
69
|
"""
|
|
70
70
|
Get the current Prefect REST API database interface.
|
|
71
71
|
|
|
@@ -144,10 +144,6 @@ class Event(PrefectBaseModel):
|
|
|
144
144
|
),
|
|
145
145
|
)
|
|
146
146
|
|
|
147
|
-
@property
|
|
148
|
-
def size_bytes(self) -> int:
|
|
149
|
-
return len(self.model_dump_json().encode())
|
|
150
|
-
|
|
151
147
|
@property
|
|
152
148
|
def involved_resources(self) -> Sequence[Resource]:
|
|
153
149
|
return [self.resource] + list(self.related)
|
|
@@ -109,7 +109,6 @@ class EventPersister(RunInEphemeralServers, Service):
|
|
|
109
109
|
"events",
|
|
110
110
|
group="event-persister",
|
|
111
111
|
name=generate_unique_consumer_name("event-persister"),
|
|
112
|
-
read_batch_size=self.service_settings().read_batch_size,
|
|
113
112
|
)
|
|
114
113
|
|
|
115
114
|
async with create_handler(
|
|
@@ -37,10 +37,7 @@ class ReactiveTriggers(RunInEphemeralServers, Service):
|
|
|
37
37
|
f"ReactiveTriggers starting with unique consumer name: {consumer_name}"
|
|
38
38
|
)
|
|
39
39
|
self.consumer: Consumer = create_consumer(
|
|
40
|
-
"events",
|
|
41
|
-
group="reactive-triggers",
|
|
42
|
-
name=consumer_name,
|
|
43
|
-
read_batch_size=self.service_settings().read_batch_size,
|
|
40
|
+
"events", group="reactive-triggers", name=consumer_name
|
|
44
41
|
)
|
|
45
42
|
|
|
46
43
|
async with triggers.consumer() as handler:
|
|
@@ -379,36 +379,16 @@ async def count_task_runs(
|
|
|
379
379
|
int: count of task runs
|
|
380
380
|
"""
|
|
381
381
|
|
|
382
|
-
|
|
383
|
-
query = select(sa.func.count(None)).select_from(db.TaskRun)
|
|
384
|
-
query = query.join(db.FlowRun, db.TaskRun.flow_run_id == db.FlowRun.id)
|
|
382
|
+
query = select(sa.func.count(None)).select_from(db.TaskRun)
|
|
385
383
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
query = query.join(
|
|
395
|
-
db.Deployment, db.Deployment.id == db.FlowRun.deployment_id
|
|
396
|
-
)
|
|
397
|
-
query = query.where(deployment_filter.as_sql_filter())
|
|
398
|
-
|
|
399
|
-
if task_run_filter:
|
|
400
|
-
query = query.where(task_run_filter.as_sql_filter())
|
|
401
|
-
else:
|
|
402
|
-
query = select(sa.func.count(None)).select_from(db.TaskRun)
|
|
403
|
-
|
|
404
|
-
query = await _apply_task_run_filters(
|
|
405
|
-
db,
|
|
406
|
-
query,
|
|
407
|
-
flow_filter=flow_filter,
|
|
408
|
-
flow_run_filter=flow_run_filter,
|
|
409
|
-
task_run_filter=task_run_filter,
|
|
410
|
-
deployment_filter=deployment_filter,
|
|
411
|
-
)
|
|
384
|
+
query = await _apply_task_run_filters(
|
|
385
|
+
db,
|
|
386
|
+
query,
|
|
387
|
+
flow_filter=flow_filter,
|
|
388
|
+
flow_run_filter=flow_run_filter,
|
|
389
|
+
task_run_filter=task_run_filter,
|
|
390
|
+
deployment_filter=deployment_filter,
|
|
391
|
+
)
|
|
412
392
|
|
|
413
393
|
result = await session.execute(query)
|
|
414
394
|
return result.scalar_one()
|
|
@@ -440,7 +420,6 @@ async def count_task_runs_by_state(
|
|
|
440
420
|
select(db.TaskRun.state_type, sa.func.count(None).label("count"))
|
|
441
421
|
.select_from(db.TaskRun)
|
|
442
422
|
.group_by(db.TaskRun.state_type)
|
|
443
|
-
.where(db.TaskRun.state_type.isnot(None))
|
|
444
423
|
)
|
|
445
424
|
|
|
446
425
|
query = await _apply_task_run_filters(
|
|
@@ -12,6 +12,7 @@ from pydantic import ConfigDict, Field
|
|
|
12
12
|
from sqlalchemy.sql.functions import coalesce
|
|
13
13
|
|
|
14
14
|
import prefect.server.schemas as schemas
|
|
15
|
+
from prefect.server.utilities.database import db_injector
|
|
15
16
|
from prefect.server.utilities.schemas.bases import PrefectBaseModel
|
|
16
17
|
from prefect.server.utilities.text_search_parser import (
|
|
17
18
|
parse_text_search_query,
|
|
@@ -51,11 +52,9 @@ class PrefectFilterBaseModel(PrefectBaseModel):
|
|
|
51
52
|
|
|
52
53
|
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
@db_injector
|
|
56
|
+
def as_sql_filter(self, db: "PrefectDBInterface") -> sa.ColumnElement[bool]:
|
|
55
57
|
"""Generate SQL filter from provided filter parameters. If no filters parameters are available, return a TRUE filter."""
|
|
56
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
57
|
-
|
|
58
|
-
db = provide_database_interface()
|
|
59
58
|
filters = self._get_filter_list(db)
|
|
60
59
|
if not filters:
|
|
61
60
|
return sa.true()
|
|
@@ -76,10 +75,8 @@ class PrefectOperatorFilterBaseModel(PrefectFilterBaseModel):
|
|
|
76
75
|
description="Operator for combining filter criteria. Defaults to 'and_'.",
|
|
77
76
|
)
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
db = provide_database_interface()
|
|
78
|
+
@db_injector
|
|
79
|
+
def as_sql_filter(self, db: "PrefectDBInterface") -> sa.ColumnElement[bool]:
|
|
83
80
|
filters = self._get_filter_list(db)
|
|
84
81
|
if not filters:
|
|
85
82
|
return sa.true()
|
|
@@ -3,12 +3,16 @@ Schemas for sorting Prefect REST API objects.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from collections.abc import Iterable
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
import sqlalchemy as sa
|
|
9
9
|
|
|
10
|
+
from prefect.server.utilities.database import db_injector
|
|
10
11
|
from prefect.utilities.collections import AutoEnum
|
|
11
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from prefect.server.database import PrefectDBInterface
|
|
15
|
+
|
|
12
16
|
# TODO: Consider moving the `as_sql_sort` functions out of here since they are a
|
|
13
17
|
# database model level function and do not properly separate concerns when
|
|
14
18
|
# present in the schemas module
|
|
@@ -27,11 +31,9 @@ class FlowRunSort(AutoEnum):
|
|
|
27
31
|
NEXT_SCHEDULED_START_TIME_ASC = AutoEnum.auto()
|
|
28
32
|
END_TIME_DESC = AutoEnum.auto()
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
@db_injector
|
|
35
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
31
36
|
"""Return an expression used to sort flow runs"""
|
|
32
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
33
|
-
|
|
34
|
-
db = provide_database_interface()
|
|
35
37
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
36
38
|
"ID_DESC": [db.FlowRun.id.desc()],
|
|
37
39
|
"START_TIME_ASC": [
|
|
@@ -67,11 +69,9 @@ class TaskRunSort(AutoEnum):
|
|
|
67
69
|
NEXT_SCHEDULED_START_TIME_ASC = AutoEnum.auto()
|
|
68
70
|
END_TIME_DESC = AutoEnum.auto()
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
@db_injector
|
|
73
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
71
74
|
"""Return an expression used to sort task runs"""
|
|
72
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
73
|
-
|
|
74
|
-
db = provide_database_interface()
|
|
75
75
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
76
76
|
"ID_DESC": [db.TaskRun.id.desc()],
|
|
77
77
|
"EXPECTED_START_TIME_ASC": [db.TaskRun.expected_start_time.asc()],
|
|
@@ -92,11 +92,9 @@ class LogSort(AutoEnum):
|
|
|
92
92
|
TIMESTAMP_ASC = AutoEnum.auto()
|
|
93
93
|
TIMESTAMP_DESC = AutoEnum.auto()
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
@db_injector
|
|
96
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
96
97
|
"""Return an expression used to sort task runs"""
|
|
97
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
98
|
-
|
|
99
|
-
db = provide_database_interface()
|
|
100
98
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
101
99
|
"TIMESTAMP_ASC": [db.Log.timestamp.asc()],
|
|
102
100
|
"TIMESTAMP_DESC": [db.Log.timestamp.desc()],
|
|
@@ -112,11 +110,9 @@ class FlowSort(AutoEnum):
|
|
|
112
110
|
NAME_ASC = AutoEnum.auto()
|
|
113
111
|
NAME_DESC = AutoEnum.auto()
|
|
114
112
|
|
|
115
|
-
|
|
113
|
+
@db_injector
|
|
114
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
116
115
|
"""Return an expression used to sort task runs"""
|
|
117
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
118
|
-
|
|
119
|
-
db = provide_database_interface()
|
|
120
116
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
121
117
|
"CREATED_DESC": [db.Flow.created.desc()],
|
|
122
118
|
"UPDATED_DESC": [db.Flow.updated.desc()],
|
|
@@ -134,11 +130,9 @@ class DeploymentSort(AutoEnum):
|
|
|
134
130
|
NAME_ASC = AutoEnum.auto()
|
|
135
131
|
NAME_DESC = AutoEnum.auto()
|
|
136
132
|
|
|
137
|
-
|
|
133
|
+
@db_injector
|
|
134
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
138
135
|
"""Return an expression used to sort task runs"""
|
|
139
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
140
|
-
|
|
141
|
-
db = provide_database_interface()
|
|
142
136
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
143
137
|
"CREATED_DESC": [db.Deployment.created.desc()],
|
|
144
138
|
"UPDATED_DESC": [db.Deployment.updated.desc()],
|
|
@@ -157,11 +151,9 @@ class ArtifactSort(AutoEnum):
|
|
|
157
151
|
KEY_DESC = AutoEnum.auto()
|
|
158
152
|
KEY_ASC = AutoEnum.auto()
|
|
159
153
|
|
|
160
|
-
|
|
154
|
+
@db_injector
|
|
155
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
161
156
|
"""Return an expression used to sort task runs"""
|
|
162
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
163
|
-
|
|
164
|
-
db = provide_database_interface()
|
|
165
157
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
166
158
|
"CREATED_DESC": [db.Artifact.created.desc()],
|
|
167
159
|
"UPDATED_DESC": [db.Artifact.updated.desc()],
|
|
@@ -181,11 +173,9 @@ class ArtifactCollectionSort(AutoEnum):
|
|
|
181
173
|
KEY_DESC = AutoEnum.auto()
|
|
182
174
|
KEY_ASC = AutoEnum.auto()
|
|
183
175
|
|
|
184
|
-
|
|
176
|
+
@db_injector
|
|
177
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
185
178
|
"""Return an expression used to sort task runs"""
|
|
186
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
187
|
-
|
|
188
|
-
db = provide_database_interface()
|
|
189
179
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
190
180
|
"CREATED_DESC": [db.ArtifactCollection.created.desc()],
|
|
191
181
|
"UPDATED_DESC": [db.ArtifactCollection.updated.desc()],
|
|
@@ -204,11 +194,9 @@ class VariableSort(AutoEnum):
|
|
|
204
194
|
NAME_DESC = "NAME_DESC"
|
|
205
195
|
NAME_ASC = "NAME_ASC"
|
|
206
196
|
|
|
207
|
-
|
|
197
|
+
@db_injector
|
|
198
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
208
199
|
"""Return an expression used to sort task runs"""
|
|
209
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
210
|
-
|
|
211
|
-
db = provide_database_interface()
|
|
212
200
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
213
201
|
"CREATED_DESC": [db.Variable.created.desc()],
|
|
214
202
|
"UPDATED_DESC": [db.Variable.updated.desc()],
|
|
@@ -225,11 +213,9 @@ class BlockDocumentSort(AutoEnum):
|
|
|
225
213
|
NAME_ASC = "NAME_ASC"
|
|
226
214
|
BLOCK_TYPE_AND_NAME_ASC = "BLOCK_TYPE_AND_NAME_ASC"
|
|
227
215
|
|
|
228
|
-
|
|
216
|
+
@db_injector
|
|
217
|
+
def as_sql_sort(self, db: "PrefectDBInterface") -> Iterable[sa.ColumnElement[Any]]:
|
|
229
218
|
"""Return an expression used to sort task runs"""
|
|
230
|
-
from prefect.server.database.dependencies import provide_database_interface
|
|
231
|
-
|
|
232
|
-
db = provide_database_interface()
|
|
233
219
|
sort_mapping: dict[str, Iterable[sa.ColumnElement[Any]]] = {
|
|
234
220
|
"NAME_DESC": [db.BlockDocument.name.desc()],
|
|
235
221
|
"NAME_ASC": [db.BlockDocument.name.asc()],
|
|
@@ -270,7 +270,6 @@ class TaskRunRecorder(RunInEphemeralServers, Service):
|
|
|
270
270
|
"events",
|
|
271
271
|
group="task-run-recorder",
|
|
272
272
|
name=generate_unique_consumer_name("task-run-recorder"),
|
|
273
|
-
read_batch_size=self.service_settings().read_batch_size,
|
|
274
273
|
)
|
|
275
274
|
|
|
276
275
|
async with consumer() as handler:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"404-
|
|
1
|
+
{"version":3,"file":"404-U2KQOqzV.js","sources":["../../src/pages/404.vue"],"sourcesContent":["<template>\n <FourZeroFour />\n</template>\n\n<script lang=\"ts\" setup>\n import { FourZeroFour } from '@prefecthq/prefect-ui-library'\n import { usePageTitle } from '@/compositions/usePageTitle'\n usePageTitle('Page Not Found')\n</script>"],"names":["usePageTitle","_createBlock","_unref","FourZeroFour"],"mappings":"qJAOE,OAAAA,EAAa,gBAAgB,cAN7BC,EAAgBC,EAAAC,CAAA,CAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{d as B,M as O,ae as U,V as R,h as c,c as w,o as p,i as n,k as t,D as S,l as V,a as y,n as D,m as e,t as q,L as j,de as K,df as L,K as F,g as J,cB as W,dg as z,dh as Q,di as l,bg as i,I as Y,dj as G,j as H,dk as Z,dl as X,c9 as E,aJ as $,by as ee,dm as te,dn as oe,dp as ne,r as se,aw as ae,dq as le,aS as x,dr as ie,ds as re,dt as ue,du as ce}from"./index-BRrm8IYN.js";import{u as me,c as pe}from"./useCan-BidbvPHp.js";import{u as de,U as _e,a as fe,c as ve,p as ge}from"./usePrefectApi-CPise1aa.js";import"./mapper-DJ53lQ_S.js";const we={class:"flex gap-x-2 items-center"},ye={key:0,class:"text-sm italic"},he="http://prefect.io/slack?utm_source=oss&utm_medium=oss&utm_campaign=oss_popup&utm_term=none&utm_content=none",T="join-the-community-modal",ke="https://getform.io/f/eapderva",be=B({__name:"JoinTheCommunityModal",props:{showModal:{type:Boolean},showModalModifiers:{}},emits:["update:showModal"],setup(a){const s=O(a,"showModal"),u=U(!1),r=U(),{validate:h,state:d}=R(r,[K("Email"),L("Email")]),v=U(!1),f=U("");async function k(){if(await h()){f.value="",v.value=!0;try{await fetch(ke,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:r.value}),redirect:"manual"}),s.value=!1,j("Successfully subscribed","success")}catch(b){f.value="An error occurred. Please try again.",console.error(b)}finally{v.value=!1}}}return(b,o)=>{const m=c("p-button"),g=c("p-divider"),_=c("p-text-input"),M=c("p-label"),P=c("p-form"),A=c("p-message"),I=c("p-modal");return p(),w(I,{"show-modal":s.value,"onUpdate:showModal":o[2]||(o[2]=C=>s.value=C),title:"Join the Prefect Community"},{header:n(()=>[...o[3]||(o[3]=[V("h2",null,"Join the Community",-1)])]),default:n(()=>[o[5]||(o[5]=V("p",null," Connect with 25k+ engineers scaling Python with Prefect. Show us your work and be the first to know about new Prefect features. ",-1)),V("div",we,[t(m,{primary:"",icon:"Slack",to:he,target:"_blank",onClick:o[0]||(o[0]=C=>u.value=!0)},{default:n(()=>[...o[4]||(o[4]=[S(" Join us on Slack ",-1)])]),_:1}),u.value?(p(),D("span",ye," Thanks for joining our community! ")):y("",!0)]),t(g,{class:"-my-3"}),t(P,{id:T,onSubmit:k},{default:n(()=>[t(M,{label:"Notify me about Prefect updates",state:e(d),message:e(d).error},{default:n(({id:C})=>[t(_,{id:C,modelValue:r.value,"onUpdate:modelValue":o[1]||(o[1]=N=>r.value=N),placeholder:"hello@prefect.io",state:e(d)},null,8,["id","modelValue","state"])]),_:1},8,["state","message"])]),_:1}),f.value?(p(),w(A,{key:0,error:""},{default:n(()=>[S(q(f.value),1)]),_:1})):y("",!0)]),cancel:n(C=>[t(m,{class:"sm:order-first",onClick:C.close},{default:n(()=>[...o[6]||(o[6]=[S(" Skip ",-1)])]),_:1},8,["onClick"])]),actions:n(()=>[t(m,{primary:"",type:"submit",form:T,loading:v.value},{default:n(()=>[...o[7]||(o[7]=[S(" Sign up ",-1)])]),_:1},8,["loading"])]),_:1},8,["show-modal"])}}}),Ce={key:0,href:"https://www.prefect.io/cloud-vs-oss?utm_source=oss&utm_medium=oss&utm_campaign=oss&utm_term=none&utm_content=none",target:"_blank"},Se=B({__name:"ContextSidebar",async setup(a){let s,u;const r=me(),h=de(),d=([s,u]=F(()=>h.admin.getSettings()),s=await s,u(),s),v=J(()=>d.server.ui.show_promotional_content);localStorage.setItem("prefect-show-promotional-content",String(v.value));const f=J(()=>r.read.work_pool),{showModal:k,open:b}=W(),{value:o}=z("local","join-the-community-modal-dismissed",!1);function m(g){k.value=g,g||(o.value=!0)}return(g,_)=>{const M=c("p-icon"),P=c("router-link"),A=c("p-button");return p(),w(e(Q),{class:"context-sidebar"},{header:n(()=>[t(P,{to:e(i).root(),class:"context-sidebar__logo-link"},{default:n(()=>[t(M,{icon:"Prefect",class:"context-sidebar__logo-icon"})]),_:1},8,["to"])]),footer:n(()=>[v.value?(p(),D("a",Ce,[t(e(l),null,{default:n(()=>[_[1]||(_[1]=V("div",null," Ready to scale? ",-1)),t(A,{primary:"",small:"",class:"context-sidebar__upgade-button"},{default:n(()=>[..._[0]||(_[0]=[S(" Upgrade ",-1)])]),_:1})]),_:1})])):y("",!0),t(e(l),{onClick:e(b)},{default:n(()=>[_[2]||(_[2]=S(" Join the Community ",-1)),t(be,{"show-modal":e(k)||!e(o),"onUpdate:showModal":m},null,8,["show-modal"])]),_:1},8,["onClick"]),t(e(l),{title:"Settings",to:e(i).settings()},null,8,["to"])]),default:n(()=>[t(e(l),{title:"Dashboard",to:e(i).dashboard()},null,8,["to"]),t(e(l),{title:"Runs",to:e(i).runs()},null,8,["to"]),t(e(l),{title:"Flows",to:e(i).flows()},null,8,["to"]),t(e(l),{title:"Deployments",to:e(i).deployments()},null,8,["to"]),f.value?(p(),w(e(l),{key:0,title:"Work Pools",to:e(i).workPools()},null,8,["to"])):y("",!0),f.value?y("",!0):(p(),w(e(l),{key:1,title:"Work Queues",to:e(i).workQueues()},null,8,["to"])),t(e(l),{title:"Blocks",to:e(i).blocks()},null,8,["to"]),t(e(l),{title:e(Y).info.variables,to:e(i).variables()},null,8,["title","to"]),t(e(l),{title:"Automations",to:e(i).automations()},null,8,["to"]),t(e(l),{title:"Event Feed",to:e(i).events()},null,8,["to"]),t(e(l),{title:"Concurrency",to:e(i).concurrencyLimits()},null,8,["to"])]),_:1})}}});async function Me(){const a=await _e.get("apiUrl"),s={baseUrl:a};return a.startsWith("/")&&G(),{config:s}}function Pe(){const a=H(fe.getFeatureFlags,[]),s=J(()=>[...Z,...a.response??[]]),u=X(s),r=J(()=>a.loading);return{can:u,pending:r}}function xe(){const a=U(!1);function s(){a.value=!a.value}function u(){a.value=!0}function r(){a.value=!1}return{mobileMenuOpen:a,open:u,close:r,toggle:s}}const Ue={class:"app-router-view"},$e=B({__name:"AppRouterView",async setup(a){let s,u;const{can:r}=Pe(),{config:h}=([s,u]=F(()=>Me()),s=await s,u(),s),d=ve(h),v=ue();x(pe,r),x(ie,r),x(ge,d),x(re,d),x(ce,v),d.admin.authCheck().then(m=>{m==401?E.currentRoute.value.name!=="login"&&(j("Authentication failed.","error",{timeout:!1}),E.push({name:"login",query:{redirect:E.currentRoute.value.fullPath}})):d.health.isHealthy().then(g=>{g||j(`Can't connect to Server API at ${h.baseUrl}. Check that it's accessible from your machine.`,"error",{timeout:!1})})});const{mobileMenuOpen:f,toggle:k,close:b}=xe(),o=J(()=>$.lg||f.value);return ee(()=>document.body.classList.toggle("body-scrolling-disabled",o.value&&!$.lg)),(m,g)=>{const _=c("router-link"),M=c("p-button");return p(),D("div",Ue,[!e($).lg&&!m.$route.meta.public?(p(),w(e(oe),{key:0,class:"app-router-view__mobile-menu"},{"upper-links":n(()=>[t(_,{to:e(i).root()},{default:n(()=>[t(e(te),{icon:"Prefect",class:"app-router-view__prefect-icon"})]),_:1},8,["to"])]),"bottom-links":n(()=>[t(M,{small:"",icon:"Bars3Icon",class:"app-router-view__menu-icon",onClick:e(k)},null,8,["onClick"])]),_:1})):y("",!0),o.value&&!m.$route.meta.public?(p(),w(Se,{key:1,class:"app-router-view__sidebar",onClick:e(b)},null,8,["onClick"])):y("",!0),t(e(le),{class:ae(["app-router-view__view",{"app-router-view__view--public":m.$route.meta.public}])},{default:n(({Component:P})=>[t(ne,{name:"app-router-view-fade",mode:"out-in"},{default:n(()=>[(p(),w(se(P)))]),_:2},1024)]),_:1},8,["class"])])}}});export{$e as default};
|
|
2
|
+
//# sourceMappingURL=AppRouterView-DnlTfFmZ.js.map
|