prefect-client 2.16.2__py3-none-any.whl → 2.16.3__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/_internal/concurrency/services.py +5 -0
- prefect/_internal/concurrency/threads.py +3 -0
- prefect/deployments/deployments.py +29 -6
- prefect/deployments/runner.py +15 -33
- prefect/deployments/schedules.py +37 -0
- prefect/engine.py +59 -22
- prefect/events/schemas.py +253 -43
- prefect/flows.py +26 -2
- prefect/runner/runner.py +2 -2
- prefect/server/api/collections_data/views/aggregate-worker-metadata.json +9 -2
- prefect/settings.py +34 -9
- prefect/task_engine.py +16 -8
- prefect/tasks.py +39 -4
- prefect/utilities/schema_tools/__init__.py +0 -0
- prefect/utilities/schema_tools/hydration.py +218 -0
- prefect/utilities/schema_tools/validation.py +240 -0
- {prefect_client-2.16.2.dist-info → prefect_client-2.16.3.dist-info}/METADATA +52 -49
- {prefect_client-2.16.2.dist-info → prefect_client-2.16.3.dist-info}/RECORD +21 -17
- {prefect_client-2.16.2.dist-info → prefect_client-2.16.3.dist-info}/LICENSE +0 -0
- {prefect_client-2.16.2.dist-info → prefect_client-2.16.3.dist-info}/WHEEL +0 -0
- {prefect_client-2.16.2.dist-info → prefect_client-2.16.3.dist-info}/top_level.txt +0 -0
prefect/events/schemas.py
CHANGED
@@ -1,8 +1,22 @@
|
|
1
|
+
import abc
|
1
2
|
from datetime import timedelta
|
2
|
-
from
|
3
|
+
from enum import Enum
|
4
|
+
from typing import (
|
5
|
+
Any,
|
6
|
+
Dict,
|
7
|
+
Iterable,
|
8
|
+
List,
|
9
|
+
Literal,
|
10
|
+
Optional,
|
11
|
+
Set,
|
12
|
+
Tuple,
|
13
|
+
Union,
|
14
|
+
cast,
|
15
|
+
)
|
3
16
|
from uuid import UUID, uuid4
|
4
17
|
|
5
18
|
import pendulum
|
19
|
+
from typing_extensions import TypeAlias
|
6
20
|
|
7
21
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
8
22
|
|
@@ -15,7 +29,6 @@ else:
|
|
15
29
|
|
16
30
|
from prefect._internal.schemas.bases import PrefectBaseModel
|
17
31
|
from prefect._internal.schemas.fields import DateTimeTZ
|
18
|
-
from prefect._internal.schemas.transformations import FieldFrom, copy_model_fields
|
19
32
|
from prefect.events.actions import ActionTypes, RunDeployment
|
20
33
|
from prefect.utilities.collections import AutoEnum
|
21
34
|
|
@@ -27,6 +40,7 @@ MAXIMUM_RELATED_RESOURCES = 500
|
|
27
40
|
class Posture(AutoEnum):
|
28
41
|
Reactive = "Reactive"
|
29
42
|
Proactive = "Proactive"
|
43
|
+
Metric = "Metric"
|
30
44
|
|
31
45
|
|
32
46
|
class ResourceSpecification(PrefectBaseModel):
|
@@ -164,32 +178,56 @@ class Event(PrefectBaseModel):
|
|
164
178
|
return value
|
165
179
|
|
166
180
|
|
167
|
-
class Trigger(PrefectBaseModel):
|
168
|
-
"""
|
169
|
-
|
181
|
+
class Trigger(PrefectBaseModel, abc.ABC):
|
182
|
+
"""
|
183
|
+
Base class describing a set of criteria that must be satisfied in order to trigger
|
184
|
+
an automation.
|
185
|
+
"""
|
186
|
+
|
187
|
+
class Config:
|
188
|
+
extra = Extra.ignore
|
189
|
+
|
190
|
+
type: str
|
191
|
+
|
192
|
+
|
193
|
+
class ResourceTrigger(Trigger, abc.ABC):
|
194
|
+
"""
|
195
|
+
Base class for triggers that may filter by the labels of resources.
|
196
|
+
"""
|
197
|
+
|
198
|
+
type: str
|
170
199
|
|
171
200
|
match: ResourceSpecification = Field(
|
172
201
|
default_factory=lambda: ResourceSpecification(__root__={}),
|
173
|
-
description="Labels for resources which this
|
202
|
+
description="Labels for resources which this trigger will match.",
|
174
203
|
)
|
175
204
|
match_related: ResourceSpecification = Field(
|
176
205
|
default_factory=lambda: ResourceSpecification(__root__={}),
|
177
|
-
description="Labels for related resources which this
|
206
|
+
description="Labels for related resources which this trigger will match.",
|
178
207
|
)
|
179
208
|
|
209
|
+
|
210
|
+
class EventTrigger(ResourceTrigger):
|
211
|
+
"""
|
212
|
+
A trigger that fires based on the presence or absence of events within a given
|
213
|
+
period of time.
|
214
|
+
"""
|
215
|
+
|
216
|
+
type: Literal["event"] = "event"
|
217
|
+
|
180
218
|
after: Set[str] = Field(
|
181
219
|
default_factory=set,
|
182
220
|
description=(
|
183
|
-
"The event(s) which must first been seen to
|
184
|
-
"empty, then
|
221
|
+
"The event(s) which must first been seen to fire this trigger. If "
|
222
|
+
"empty, then fire this trigger immediately. Events may include "
|
185
223
|
"trailing wildcards, like `prefect.flow-run.*`"
|
186
224
|
),
|
187
225
|
)
|
188
226
|
expect: Set[str] = Field(
|
189
227
|
default_factory=set,
|
190
228
|
description=(
|
191
|
-
"The event(s) this
|
192
|
-
"
|
229
|
+
"The event(s) this trigger is expecting to see. If empty, this "
|
230
|
+
"trigger will match any event. Events may include trailing wildcards, "
|
193
231
|
"like `prefect.flow-run.*`"
|
194
232
|
),
|
195
233
|
)
|
@@ -197,24 +235,29 @@ class Trigger(PrefectBaseModel):
|
|
197
235
|
for_each: Set[str] = Field(
|
198
236
|
default_factory=set,
|
199
237
|
description=(
|
200
|
-
"Evaluate the
|
201
|
-
"
|
238
|
+
"Evaluate the trigger separately for each distinct value of these labels "
|
239
|
+
"on the resource. By default, labels refer to the primary resource of the "
|
240
|
+
"triggering event. You may also refer to labels from related "
|
241
|
+
"resources by specifying `related:<role>:<label>`. This will use the "
|
242
|
+
"value of that label for the first related resource in that role. For "
|
243
|
+
'example, `"for_each": ["related:flow:prefect.resource.id"]` would '
|
244
|
+
"evaluate the trigger for each flow."
|
202
245
|
),
|
203
246
|
)
|
204
|
-
posture: Posture = Field(
|
205
|
-
|
247
|
+
posture: Literal[Posture.Reactive, Posture.Proactive] = Field( # type: ignore[valid-type]
|
248
|
+
...,
|
206
249
|
description=(
|
207
|
-
"The posture of this
|
208
|
-
"
|
209
|
-
"Proactive
|
250
|
+
"The posture of this trigger, either Reactive or Proactive. Reactive "
|
251
|
+
"triggers respond to the _presence_ of the expected events, while "
|
252
|
+
"Proactive triggers respond to the _absence_ of those expected events."
|
210
253
|
),
|
211
254
|
)
|
212
255
|
threshold: int = Field(
|
213
256
|
1,
|
214
257
|
description=(
|
215
|
-
"The number of events required for this
|
216
|
-
"Reactive
|
217
|
-
"
|
258
|
+
"The number of events required for this trigger to fire (for "
|
259
|
+
"Reactive triggers), or the number of events expected (for Proactive "
|
260
|
+
"triggers)"
|
218
261
|
),
|
219
262
|
)
|
220
263
|
within: timedelta = Field(
|
@@ -253,6 +296,86 @@ class Trigger(PrefectBaseModel):
|
|
253
296
|
return values
|
254
297
|
|
255
298
|
|
299
|
+
class MetricTriggerOperator(Enum):
|
300
|
+
LT = "<"
|
301
|
+
LTE = "<="
|
302
|
+
GT = ">"
|
303
|
+
GTE = ">="
|
304
|
+
|
305
|
+
|
306
|
+
class PrefectMetric(Enum):
|
307
|
+
lateness = "lateness"
|
308
|
+
duration = "duration"
|
309
|
+
successes = "successes"
|
310
|
+
|
311
|
+
|
312
|
+
class MetricTriggerQuery(PrefectBaseModel):
|
313
|
+
"""Defines a subset of the Trigger subclass, which is specific
|
314
|
+
to Metric automations, that specify the query configurations
|
315
|
+
and breaching conditions for the Automation"""
|
316
|
+
|
317
|
+
name: PrefectMetric = Field(
|
318
|
+
...,
|
319
|
+
description="The name of the metric to query.",
|
320
|
+
)
|
321
|
+
threshold: float = Field(
|
322
|
+
...,
|
323
|
+
description=(
|
324
|
+
"The threshold value against which we'll compare " "the query result."
|
325
|
+
),
|
326
|
+
)
|
327
|
+
operator: MetricTriggerOperator = Field(
|
328
|
+
...,
|
329
|
+
description=(
|
330
|
+
"The comparative operator (LT / LTE / GT / GTE) used to compare "
|
331
|
+
"the query result against the threshold value."
|
332
|
+
),
|
333
|
+
)
|
334
|
+
range: timedelta = Field(
|
335
|
+
timedelta(seconds=300), # defaults to 5 minutes
|
336
|
+
minimum=300.0,
|
337
|
+
exclusiveMinimum=False,
|
338
|
+
description=(
|
339
|
+
"The lookback duration (seconds) for a metric query. This duration is "
|
340
|
+
"used to determine the time range over which the query will be executed. "
|
341
|
+
"The minimum value is 300 seconds (5 minutes)."
|
342
|
+
),
|
343
|
+
)
|
344
|
+
firing_for: timedelta = Field(
|
345
|
+
timedelta(seconds=300), # defaults to 5 minutes
|
346
|
+
minimum=300.0,
|
347
|
+
exclusiveMinimum=False,
|
348
|
+
description=(
|
349
|
+
"The duration (seconds) for which the metric query must breach "
|
350
|
+
"or resolve continuously before the state is updated and the "
|
351
|
+
"automation is triggered. "
|
352
|
+
"The minimum value is 300 seconds (5 minutes)."
|
353
|
+
),
|
354
|
+
)
|
355
|
+
|
356
|
+
|
357
|
+
class MetricTrigger(ResourceTrigger):
|
358
|
+
"""
|
359
|
+
A trigger that fires based on the results of a metric query.
|
360
|
+
"""
|
361
|
+
|
362
|
+
type: Literal["metric"] = "metric"
|
363
|
+
|
364
|
+
posture: Literal[Posture.Metric] = Field( # type: ignore[valid-type]
|
365
|
+
Posture.Metric,
|
366
|
+
description="Periodically evaluate the configured metric query.",
|
367
|
+
)
|
368
|
+
|
369
|
+
metric: MetricTriggerQuery = Field(
|
370
|
+
...,
|
371
|
+
description="The metric query to evaluate for this trigger. ",
|
372
|
+
)
|
373
|
+
|
374
|
+
|
375
|
+
TriggerTypes: TypeAlias = Union[EventTrigger, MetricTrigger]
|
376
|
+
"""The union of all concrete trigger types that a user may actually create"""
|
377
|
+
|
378
|
+
|
256
379
|
class Automation(PrefectBaseModel):
|
257
380
|
"""Defines an action a user wants to take when a certain number of events
|
258
381
|
do or don't happen to the matching resources"""
|
@@ -265,7 +388,7 @@ class Automation(PrefectBaseModel):
|
|
265
388
|
|
266
389
|
enabled: bool = Field(True, description="Whether this automation will be evaluated")
|
267
390
|
|
268
|
-
trigger:
|
391
|
+
trigger: TriggerTypes = Field(
|
269
392
|
...,
|
270
393
|
description=(
|
271
394
|
"The criteria for which events this Automation covers and how it will "
|
@@ -286,30 +409,106 @@ class ExistingAutomation(Automation):
|
|
286
409
|
id: UUID = Field(..., description="The ID of this automation")
|
287
410
|
|
288
411
|
|
289
|
-
|
290
|
-
class ResourceTrigger(PrefectBaseModel):
|
412
|
+
class AutomationCreateFromTrigger(PrefectBaseModel):
|
291
413
|
name: Optional[str] = Field(
|
292
414
|
None, description="The name to give to the automation created for this trigger."
|
293
415
|
)
|
294
|
-
description: str =
|
295
|
-
enabled: bool =
|
416
|
+
description: str = Field("", description="A longer description of this automation")
|
417
|
+
enabled: bool = Field(True, description="Whether this automation will be evaluated")
|
418
|
+
|
419
|
+
# from ResourceTrigger
|
420
|
+
|
421
|
+
match: ResourceSpecification = Field(
|
422
|
+
default_factory=lambda: ResourceSpecification(__root__={}),
|
423
|
+
description="Labels for resources which this trigger will match.",
|
424
|
+
)
|
425
|
+
match_related: ResourceSpecification = Field(
|
426
|
+
default_factory=lambda: ResourceSpecification(__root__={}),
|
427
|
+
description="Labels for related resources which this trigger will match.",
|
428
|
+
)
|
429
|
+
|
430
|
+
# from both EventTrigger and MetricTrigger
|
431
|
+
|
432
|
+
posture: Posture = Field(
|
433
|
+
Posture.Reactive,
|
434
|
+
description=(
|
435
|
+
"The posture of this trigger, either Reactive, Proactive, or Metric. "
|
436
|
+
"Reactive triggers respond to the _presence_ of the expected events, while "
|
437
|
+
"Proactive triggers respond to the _absence_ of those expected events. "
|
438
|
+
"Metric triggers periodically evaluate the configured metric query."
|
439
|
+
),
|
440
|
+
)
|
296
441
|
|
297
|
-
|
298
|
-
|
299
|
-
after: Set[str] =
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
442
|
+
# from EventTrigger
|
443
|
+
|
444
|
+
after: Set[str] = Field(
|
445
|
+
default_factory=set,
|
446
|
+
description=(
|
447
|
+
"The event(s) which must first been seen to fire this trigger. If "
|
448
|
+
"empty, then fire this trigger immediately. Events may include "
|
449
|
+
"trailing wildcards, like `prefect.flow-run.*`"
|
450
|
+
),
|
451
|
+
)
|
452
|
+
expect: Set[str] = Field(
|
453
|
+
default_factory=set,
|
454
|
+
description=(
|
455
|
+
"The event(s) this trigger is expecting to see. If empty, this "
|
456
|
+
"trigger will match any event. Events may include trailing wildcards, "
|
457
|
+
"like `prefect.flow-run.*`"
|
458
|
+
),
|
459
|
+
)
|
460
|
+
|
461
|
+
for_each: Set[str] = Field(
|
462
|
+
default_factory=set,
|
463
|
+
description=(
|
464
|
+
"Evaluate the trigger separately for each distinct value of these labels "
|
465
|
+
"on the resource. By default, labels refer to the primary resource of the "
|
466
|
+
"triggering event. You may also refer to labels from related "
|
467
|
+
"resources by specifying `related:<role>:<label>`. This will use the "
|
468
|
+
"value of that label for the first related resource in that role. For "
|
469
|
+
'example, `"for_each": ["related:flow:prefect.resource.id"]` would '
|
470
|
+
"evaluate the trigger for each flow."
|
471
|
+
),
|
472
|
+
)
|
473
|
+
threshold: int = Field(
|
474
|
+
1,
|
475
|
+
description=(
|
476
|
+
"The number of events required for this trigger to fire (for "
|
477
|
+
"Reactive triggers), or the number of events expected (for Proactive "
|
478
|
+
"triggers)"
|
479
|
+
),
|
480
|
+
)
|
481
|
+
within: timedelta = Field(
|
482
|
+
timedelta(0),
|
483
|
+
minimum=0.0,
|
484
|
+
exclusiveMinimum=False,
|
485
|
+
description=(
|
486
|
+
"The time period over which the events must occur. For Reactive triggers, "
|
487
|
+
"this may be as low as 0 seconds, but must be at least 10 seconds for "
|
488
|
+
"Proactive triggers"
|
489
|
+
),
|
490
|
+
)
|
491
|
+
|
492
|
+
# from MetricTrigger
|
493
|
+
|
494
|
+
metric: Optional[MetricTriggerQuery] = Field(
|
495
|
+
None,
|
496
|
+
description="The metric query to evaluate for this trigger. ",
|
497
|
+
)
|
305
498
|
|
306
499
|
def as_automation(self) -> Automation:
|
307
500
|
assert self.name
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
501
|
+
|
502
|
+
if self.posture == Posture.Metric:
|
503
|
+
trigger = MetricTrigger(
|
504
|
+
type="metric",
|
505
|
+
match=self.match,
|
506
|
+
match_related=self.match_related,
|
507
|
+
posture=self.posture,
|
508
|
+
metric=self.metric,
|
509
|
+
)
|
510
|
+
else:
|
511
|
+
trigger = EventTrigger(
|
313
512
|
match=self.match,
|
314
513
|
match_related=self.match_related,
|
315
514
|
after=self.after,
|
@@ -318,7 +517,13 @@ class ResourceTrigger(PrefectBaseModel):
|
|
318
517
|
posture=self.posture,
|
319
518
|
threshold=self.threshold,
|
320
519
|
within=self.within,
|
321
|
-
)
|
520
|
+
)
|
521
|
+
|
522
|
+
return Automation(
|
523
|
+
name=self.name,
|
524
|
+
description=self.description,
|
525
|
+
enabled=self.enabled,
|
526
|
+
trigger=trigger,
|
322
527
|
actions=self.actions(),
|
323
528
|
owner_resource=self.owner_resource(),
|
324
529
|
)
|
@@ -330,10 +535,15 @@ class ResourceTrigger(PrefectBaseModel):
|
|
330
535
|
raise NotImplementedError
|
331
536
|
|
332
537
|
|
333
|
-
|
334
|
-
class DeploymentTrigger(ResourceTrigger):
|
538
|
+
class DeploymentTrigger(AutomationCreateFromTrigger):
|
335
539
|
_deployment_id: Optional[UUID] = PrivateAttr(default=None)
|
336
|
-
parameters: Optional[Dict[str, Any]] =
|
540
|
+
parameters: Optional[Dict[str, Any]] = Field(
|
541
|
+
None,
|
542
|
+
description=(
|
543
|
+
"The parameters to pass to the deployment, or None to use the "
|
544
|
+
"deployment's default parameters"
|
545
|
+
),
|
546
|
+
)
|
337
547
|
|
338
548
|
def set_deployment_id(self, deployment_id: UUID):
|
339
549
|
self._deployment_id = deployment_id
|
prefect/flows.py
CHANGED
@@ -183,6 +183,7 @@ class Flow(Generic[P, R]):
|
|
183
183
|
on_completion: An optional list of callables to run when the flow enters a completed state.
|
184
184
|
on_cancellation: An optional list of callables to run when the flow enters a cancelling state.
|
185
185
|
on_crashed: An optional list of callables to run when the flow enters a crashed state.
|
186
|
+
on_running: An optional list of callables to run when the flow enters a running state.
|
186
187
|
"""
|
187
188
|
|
188
189
|
# NOTE: These parameters (types, defaults, and docstrings) should be duplicated
|
@@ -212,6 +213,7 @@ class Flow(Generic[P, R]):
|
|
212
213
|
List[Callable[[FlowSchema, FlowRun, State], None]]
|
213
214
|
] = None,
|
214
215
|
on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
216
|
+
on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
215
217
|
):
|
216
218
|
if name is not None and not isinstance(name, str):
|
217
219
|
raise TypeError(
|
@@ -227,8 +229,20 @@ class Flow(Generic[P, R]):
|
|
227
229
|
)
|
228
230
|
|
229
231
|
# Validate if hook passed is list and contains callables
|
230
|
-
hook_categories = [
|
231
|
-
|
232
|
+
hook_categories = [
|
233
|
+
on_completion,
|
234
|
+
on_failure,
|
235
|
+
on_cancellation,
|
236
|
+
on_crashed,
|
237
|
+
on_running,
|
238
|
+
]
|
239
|
+
hook_names = [
|
240
|
+
"on_completion",
|
241
|
+
"on_failure",
|
242
|
+
"on_cancellation",
|
243
|
+
"on_crashed",
|
244
|
+
"on_running",
|
245
|
+
]
|
232
246
|
for hooks, hook_name in zip(hook_categories, hook_names):
|
233
247
|
if hooks is not None:
|
234
248
|
if not hooks:
|
@@ -350,6 +364,7 @@ class Flow(Generic[P, R]):
|
|
350
364
|
self.on_failure = on_failure
|
351
365
|
self.on_cancellation = on_cancellation
|
352
366
|
self.on_crashed = on_crashed
|
367
|
+
self.on_running = on_running
|
353
368
|
|
354
369
|
# Used for flows loaded from remote storage
|
355
370
|
self._storage: Optional[RunnerStorage] = None
|
@@ -387,6 +402,7 @@ class Flow(Generic[P, R]):
|
|
387
402
|
List[Callable[[FlowSchema, FlowRun, State], None]]
|
388
403
|
] = None,
|
389
404
|
on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
405
|
+
on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
390
406
|
) -> Self:
|
391
407
|
"""
|
392
408
|
Create a new flow from the current object, updating provided options.
|
@@ -415,6 +431,7 @@ class Flow(Generic[P, R]):
|
|
415
431
|
on_completion: A new list of callables to run when the flow enters a completed state.
|
416
432
|
on_cancellation: A new list of callables to run when the flow enters a cancelling state.
|
417
433
|
on_crashed: A new list of callables to run when the flow enters a crashed state.
|
434
|
+
on_running: A new list of callables to run when the flow enters a running state.
|
418
435
|
|
419
436
|
Returns:
|
420
437
|
A new `Flow` instance.
|
@@ -484,6 +501,7 @@ class Flow(Generic[P, R]):
|
|
484
501
|
on_failure=on_failure or self.on_failure,
|
485
502
|
on_cancellation=on_cancellation or self.on_cancellation,
|
486
503
|
on_crashed=on_crashed or self.on_crashed,
|
504
|
+
on_running=on_running or self.on_running,
|
487
505
|
)
|
488
506
|
new_flow._storage = self._storage
|
489
507
|
new_flow._entrypoint = self._entrypoint
|
@@ -1333,6 +1351,7 @@ def flow(
|
|
1333
1351
|
List[Callable[[FlowSchema, FlowRun, State], None]]
|
1334
1352
|
] = None,
|
1335
1353
|
on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
1354
|
+
on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
1336
1355
|
) -> Callable[[Callable[P, R]], Flow[P, R]]:
|
1337
1356
|
...
|
1338
1357
|
|
@@ -1360,6 +1379,7 @@ def flow(
|
|
1360
1379
|
List[Callable[[FlowSchema, FlowRun, State], None]]
|
1361
1380
|
] = None,
|
1362
1381
|
on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
1382
|
+
on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
|
1363
1383
|
):
|
1364
1384
|
"""
|
1365
1385
|
Decorator to designate a function as a Prefect workflow.
|
@@ -1423,6 +1443,8 @@ def flow(
|
|
1423
1443
|
on_crashed: An optional list of functions to call when the flow run crashes. Each
|
1424
1444
|
function should accept three arguments: the flow, the flow run, and the
|
1425
1445
|
final state of the flow run.
|
1446
|
+
on_running: An optional list of functions to call when the flow run is started. Each
|
1447
|
+
function should accept three arguments: the flow, the flow run, and the current state
|
1426
1448
|
|
1427
1449
|
Returns:
|
1428
1450
|
A callable `Flow` object which, when called, will run the flow and return its
|
@@ -1485,6 +1507,7 @@ def flow(
|
|
1485
1507
|
on_failure=on_failure,
|
1486
1508
|
on_cancellation=on_cancellation,
|
1487
1509
|
on_crashed=on_crashed,
|
1510
|
+
on_running=on_running,
|
1488
1511
|
),
|
1489
1512
|
)
|
1490
1513
|
else:
|
@@ -1510,6 +1533,7 @@ def flow(
|
|
1510
1533
|
on_failure=on_failure,
|
1511
1534
|
on_cancellation=on_cancellation,
|
1512
1535
|
on_crashed=on_crashed,
|
1536
|
+
on_running=on_running,
|
1513
1537
|
),
|
1514
1538
|
)
|
1515
1539
|
|
prefect/runner/runner.py
CHANGED
@@ -76,9 +76,9 @@ from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
|
76
76
|
from prefect.deployments.deployments import load_flow_from_flow_run
|
77
77
|
from prefect.deployments.runner import (
|
78
78
|
EntrypointType,
|
79
|
-
FlexibleScheduleList,
|
80
79
|
RunnerDeployment,
|
81
80
|
)
|
81
|
+
from prefect.deployments.schedules import FlexibleScheduleList
|
82
82
|
from prefect.engine import propose_state
|
83
83
|
from prefect.events.schemas import DeploymentTrigger
|
84
84
|
from prefect.exceptions import (
|
@@ -228,7 +228,7 @@ class Runner:
|
|
228
228
|
cron: Optional[Union[Iterable[str], str]] = None,
|
229
229
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
230
230
|
paused: Optional[bool] = None,
|
231
|
-
schedules: Optional[
|
231
|
+
schedules: Optional[FlexibleScheduleList] = None,
|
232
232
|
schedule: Optional[SCHEDULE_TYPES] = None,
|
233
233
|
is_schedule_active: Optional[bool] = None,
|
234
234
|
parameters: Optional[dict] = None,
|
@@ -122,7 +122,8 @@
|
|
122
122
|
"auto_deregister_task_definition": "{{ auto_deregister_task_definition }}",
|
123
123
|
"vpc_id": "{{ vpc_id }}",
|
124
124
|
"container_name": "{{ container_name }}",
|
125
|
-
"cluster": "{{ cluster }}"
|
125
|
+
"cluster": "{{ cluster }}",
|
126
|
+
"match_latest_revision_in_family": "{{ match_latest_revision_in_family }}"
|
126
127
|
},
|
127
128
|
"variables": {
|
128
129
|
"description": "Variables for templating an ECS job.",
|
@@ -265,6 +266,12 @@
|
|
265
266
|
"description": "If enabled, any task definitions that are created by this block will be deregistered. Existing task definitions linked by ARN will never be deregistered. Deregistering a task definition does not remove it from your AWS account, instead it will be marked as INACTIVE.",
|
266
267
|
"default": false,
|
267
268
|
"type": "boolean"
|
269
|
+
},
|
270
|
+
"match_latest_revision_in_family": {
|
271
|
+
"title": "Match Latest Revision In Family",
|
272
|
+
"description": "If enabled, the most recent active revision in the task definition family will be compared against the desired ECS task configuration. If they are equal, the existing task definition will be used instead of registering a new one. If no family is specified the default family \"prefect\" will be used.",
|
273
|
+
"default": false,
|
274
|
+
"type": "boolean"
|
268
275
|
}
|
269
276
|
},
|
270
277
|
"definitions": {
|
@@ -1628,4 +1635,4 @@
|
|
1628
1635
|
"type": "kubernetes"
|
1629
1636
|
}
|
1630
1637
|
}
|
1631
|
-
}
|
1638
|
+
}
|
prefect/settings.py
CHANGED
@@ -102,6 +102,8 @@ T = TypeVar("T")
|
|
102
102
|
|
103
103
|
DEFAULT_PROFILES_PATH = Path(__file__).parent.joinpath("profiles.toml")
|
104
104
|
|
105
|
+
REMOVED_EXPERIMENTAL_FLAGS = {"PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_SCHEDULING_UI"}
|
106
|
+
|
105
107
|
|
106
108
|
class Setting(Generic[T]):
|
107
109
|
"""
|
@@ -1295,6 +1297,11 @@ PREFECT_EXPERIMENTAL_ENABLE_ARTIFACTS_ON_FLOW_RUN_GRAPH = Setting(bool, default=
|
|
1295
1297
|
Whether or not to enable artifacts on the flow run graph.
|
1296
1298
|
"""
|
1297
1299
|
|
1300
|
+
PREFECT_EXPERIMENTAL_ENABLE_STATES_ON_FLOW_RUN_GRAPH = Setting(bool, default=False)
|
1301
|
+
"""
|
1302
|
+
Whether or not to enable flow run states on the flow run graph.
|
1303
|
+
"""
|
1304
|
+
|
1298
1305
|
PREFECT_EXPERIMENTAL_ENABLE_EVENTS_CLIENT = Setting(bool, default=True)
|
1299
1306
|
"""
|
1300
1307
|
Whether or not to enable experimental Prefect work pools.
|
@@ -1335,6 +1342,11 @@ PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_CANCELLATION = Setting(bool, default=True)
|
|
1335
1342
|
Whether or not to enable experimental enhanced flow run cancellation.
|
1336
1343
|
"""
|
1337
1344
|
|
1345
|
+
PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_DEPLOYMENT_PARAMETERS = Setting(bool, default=True)
|
1346
|
+
"""
|
1347
|
+
Whether or not to enable enhanced deployment parameters.
|
1348
|
+
"""
|
1349
|
+
|
1338
1350
|
PREFECT_EXPERIMENTAL_WARN_ENHANCED_CANCELLATION = Setting(bool, default=False)
|
1339
1351
|
"""
|
1340
1352
|
Whether or not to warn when experimental enhanced flow run cancellation is used.
|
@@ -1513,11 +1525,6 @@ PREFECT_EXPERIMENTAL_ENABLE_WORK_QUEUE_STATUS = Setting(bool, default=True)
|
|
1513
1525
|
Whether or not to enable experimental work queue status in-place of work queue health.
|
1514
1526
|
"""
|
1515
1527
|
|
1516
|
-
PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_SCHEDULING_UI = Setting(bool, default=True)
|
1517
|
-
"""
|
1518
|
-
Whether or not to enable the enhanced scheduling UI.
|
1519
|
-
"""
|
1520
|
-
|
1521
1528
|
|
1522
1529
|
# Defaults -----------------------------------------------------------------------------
|
1523
1530
|
|
@@ -2071,6 +2078,24 @@ class ProfilesCollection:
|
|
2071
2078
|
)
|
2072
2079
|
|
2073
2080
|
|
2081
|
+
def _handle_removed_flags(profile_name: str, settings: dict) -> dict:
|
2082
|
+
to_remove = [name for name in settings if name in REMOVED_EXPERIMENTAL_FLAGS]
|
2083
|
+
|
2084
|
+
for name in to_remove:
|
2085
|
+
warnings.warn(
|
2086
|
+
(
|
2087
|
+
f"Experimental flag {name!r} has been removed, please "
|
2088
|
+
f"update your {profile_name!r} profile."
|
2089
|
+
),
|
2090
|
+
UserWarning,
|
2091
|
+
stacklevel=3,
|
2092
|
+
)
|
2093
|
+
|
2094
|
+
settings.pop(name)
|
2095
|
+
|
2096
|
+
return settings
|
2097
|
+
|
2098
|
+
|
2074
2099
|
def _read_profiles_from(path: Path) -> ProfilesCollection:
|
2075
2100
|
"""
|
2076
2101
|
Read profiles from a path into a new `ProfilesCollection`.
|
@@ -2087,10 +2112,10 @@ def _read_profiles_from(path: Path) -> ProfilesCollection:
|
|
2087
2112
|
active_profile = contents.get("active")
|
2088
2113
|
raw_profiles = contents.get("profiles", {})
|
2089
2114
|
|
2090
|
-
profiles = [
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2115
|
+
profiles = []
|
2116
|
+
for name, settings in raw_profiles.items():
|
2117
|
+
settings = _handle_removed_flags(name, settings)
|
2118
|
+
profiles.append(Profile(name=name, settings=settings, source=path))
|
2094
2119
|
|
2095
2120
|
return ProfilesCollection(profiles, active=active_profile)
|
2096
2121
|
|