prefect-client 3.0.0rc18__py3-none-any.whl → 3.0.0rc20__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/__init__.py +0 -3
- prefect/_internal/concurrency/services.py +14 -0
- prefect/_internal/schemas/bases.py +1 -0
- prefect/blocks/core.py +41 -30
- prefect/blocks/system.py +48 -12
- prefect/client/cloud.py +56 -7
- prefect/client/collections.py +1 -1
- prefect/client/orchestration.py +111 -8
- prefect/client/schemas/objects.py +40 -2
- prefect/concurrency/asyncio.py +8 -2
- prefect/concurrency/services.py +16 -6
- prefect/concurrency/sync.py +4 -1
- prefect/concurrency/v1/__init__.py +0 -0
- prefect/concurrency/v1/asyncio.py +143 -0
- prefect/concurrency/v1/context.py +27 -0
- prefect/concurrency/v1/events.py +61 -0
- prefect/concurrency/v1/services.py +116 -0
- prefect/concurrency/v1/sync.py +92 -0
- prefect/context.py +2 -2
- prefect/deployments/flow_runs.py +0 -7
- prefect/deployments/runner.py +11 -0
- prefect/events/clients.py +41 -0
- prefect/events/related.py +72 -73
- prefect/events/utilities.py +2 -0
- prefect/events/worker.py +12 -3
- prefect/exceptions.py +6 -0
- prefect/flow_engine.py +5 -0
- prefect/flows.py +9 -2
- prefect/logging/handlers.py +4 -1
- prefect/main.py +8 -6
- prefect/records/base.py +74 -18
- prefect/records/filesystem.py +207 -0
- prefect/records/memory.py +16 -3
- prefect/records/result_store.py +19 -14
- prefect/results.py +232 -169
- prefect/runner/runner.py +7 -4
- prefect/settings.py +14 -15
- prefect/states.py +73 -18
- prefect/task_engine.py +127 -221
- prefect/task_worker.py +7 -39
- prefect/tasks.py +0 -7
- prefect/transactions.py +89 -27
- prefect/utilities/annotations.py +4 -3
- prefect/utilities/asyncutils.py +4 -4
- prefect/utilities/callables.py +1 -3
- prefect/utilities/dispatch.py +16 -11
- prefect/utilities/engine.py +1 -4
- prefect/utilities/schema_tools/hydration.py +13 -0
- prefect/workers/base.py +78 -18
- {prefect_client-3.0.0rc18.dist-info → prefect_client-3.0.0rc20.dist-info}/METADATA +3 -4
- {prefect_client-3.0.0rc18.dist-info → prefect_client-3.0.0rc20.dist-info}/RECORD +54 -48
- prefect/manifests.py +0 -21
- {prefect_client-3.0.0rc18.dist-info → prefect_client-3.0.0rc20.dist-info}/LICENSE +0 -0
- {prefect_client-3.0.0rc18.dist-info → prefect_client-3.0.0rc20.dist-info}/WHEEL +0 -0
- {prefect_client-3.0.0rc18.dist-info → prefect_client-3.0.0rc20.dist-info}/top_level.txt +0 -0
prefect/events/related.py
CHANGED
@@ -21,6 +21,7 @@ from .schemas.events import RelatedResource
|
|
21
21
|
|
22
22
|
if TYPE_CHECKING:
|
23
23
|
from prefect._internal.schemas.bases import ObjectBaseModel
|
24
|
+
from prefect.client.orchestration import PrefectClient
|
24
25
|
|
25
26
|
ResourceCacheEntry = Dict[str, Union[str, "ObjectBaseModel", None]]
|
26
27
|
RelatedResourceCache = Dict[str, Tuple[ResourceCacheEntry, DateTime]]
|
@@ -54,9 +55,9 @@ def object_as_related_resource(kind: str, role: str, object: Any) -> RelatedReso
|
|
54
55
|
|
55
56
|
|
56
57
|
async def related_resources_from_run_context(
|
58
|
+
client: "PrefectClient",
|
57
59
|
exclude: Optional[Set[str]] = None,
|
58
60
|
) -> List[RelatedResource]:
|
59
|
-
from prefect.client.orchestration import get_client
|
60
61
|
from prefect.client.schemas.objects import FlowRun
|
61
62
|
from prefect.context import FlowRunContext, TaskRunContext
|
62
63
|
|
@@ -77,86 +78,84 @@ async def related_resources_from_run_context(
|
|
77
78
|
|
78
79
|
related_objects: List[ResourceCacheEntry] = []
|
79
80
|
|
80
|
-
async
|
81
|
+
async def dummy_read():
|
82
|
+
return {}
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
client_method=client.read_flow_run,
|
99
|
-
obj_id=flow_run_id,
|
100
|
-
cache=RESOURCE_CACHE,
|
101
|
-
)
|
84
|
+
if flow_run_context:
|
85
|
+
related_objects.append(
|
86
|
+
{
|
87
|
+
"kind": "flow-run",
|
88
|
+
"role": "flow-run",
|
89
|
+
"object": flow_run_context.flow_run,
|
90
|
+
},
|
91
|
+
)
|
92
|
+
else:
|
93
|
+
related_objects.append(
|
94
|
+
await _get_and_cache_related_object(
|
95
|
+
kind="flow-run",
|
96
|
+
role="flow-run",
|
97
|
+
client_method=client.read_flow_run,
|
98
|
+
obj_id=flow_run_id,
|
99
|
+
cache=RESOURCE_CACHE,
|
102
100
|
)
|
101
|
+
)
|
103
102
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
103
|
+
if task_run_context:
|
104
|
+
related_objects.append(
|
105
|
+
{
|
106
|
+
"kind": "task-run",
|
107
|
+
"role": "task-run",
|
108
|
+
"object": task_run_context.task_run,
|
109
|
+
},
|
110
|
+
)
|
112
111
|
|
113
|
-
|
112
|
+
flow_run = related_objects[0]["object"]
|
114
113
|
|
115
|
-
|
116
|
-
|
117
|
-
|
114
|
+
if isinstance(flow_run, FlowRun):
|
115
|
+
related_objects += list(
|
116
|
+
await asyncio.gather(
|
117
|
+
_get_and_cache_related_object(
|
118
|
+
kind="flow",
|
119
|
+
role="flow",
|
120
|
+
client_method=client.read_flow,
|
121
|
+
obj_id=flow_run.flow_id,
|
122
|
+
cache=RESOURCE_CACHE,
|
123
|
+
),
|
124
|
+
(
|
125
|
+
_get_and_cache_related_object(
|
126
|
+
kind="deployment",
|
127
|
+
role="deployment",
|
128
|
+
client_method=client.read_deployment,
|
129
|
+
obj_id=flow_run.deployment_id,
|
130
|
+
cache=RESOURCE_CACHE,
|
131
|
+
)
|
132
|
+
if flow_run.deployment_id
|
133
|
+
else dummy_read()
|
134
|
+
),
|
135
|
+
(
|
136
|
+
_get_and_cache_related_object(
|
137
|
+
kind="work-queue",
|
138
|
+
role="work-queue",
|
139
|
+
client_method=client.read_work_queue,
|
140
|
+
obj_id=flow_run.work_queue_id,
|
141
|
+
cache=RESOURCE_CACHE,
|
142
|
+
)
|
143
|
+
if flow_run.work_queue_id
|
144
|
+
else dummy_read()
|
145
|
+
),
|
146
|
+
(
|
118
147
|
_get_and_cache_related_object(
|
119
|
-
kind="
|
120
|
-
role="
|
121
|
-
client_method=client.
|
122
|
-
obj_id=flow_run.
|
148
|
+
kind="work-pool",
|
149
|
+
role="work-pool",
|
150
|
+
client_method=client.read_work_pool,
|
151
|
+
obj_id=flow_run.work_pool_name,
|
123
152
|
cache=RESOURCE_CACHE,
|
124
|
-
)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
role="deployment",
|
129
|
-
client_method=client.read_deployment,
|
130
|
-
obj_id=flow_run.deployment_id,
|
131
|
-
cache=RESOURCE_CACHE,
|
132
|
-
)
|
133
|
-
if flow_run.deployment_id
|
134
|
-
else dummy_read()
|
135
|
-
),
|
136
|
-
(
|
137
|
-
_get_and_cache_related_object(
|
138
|
-
kind="work-queue",
|
139
|
-
role="work-queue",
|
140
|
-
client_method=client.read_work_queue,
|
141
|
-
obj_id=flow_run.work_queue_id,
|
142
|
-
cache=RESOURCE_CACHE,
|
143
|
-
)
|
144
|
-
if flow_run.work_queue_id
|
145
|
-
else dummy_read()
|
146
|
-
),
|
147
|
-
(
|
148
|
-
_get_and_cache_related_object(
|
149
|
-
kind="work-pool",
|
150
|
-
role="work-pool",
|
151
|
-
client_method=client.read_work_pool,
|
152
|
-
obj_id=flow_run.work_pool_name,
|
153
|
-
cache=RESOURCE_CACHE,
|
154
|
-
)
|
155
|
-
if flow_run.work_pool_name
|
156
|
-
else dummy_read()
|
157
|
-
),
|
158
|
-
)
|
153
|
+
)
|
154
|
+
if flow_run.work_pool_name
|
155
|
+
else dummy_read()
|
156
|
+
),
|
159
157
|
)
|
158
|
+
)
|
160
159
|
|
161
160
|
related = []
|
162
161
|
tags = set()
|
prefect/events/utilities.py
CHANGED
@@ -7,6 +7,7 @@ from pydantic_extra_types.pendulum_dt import DateTime
|
|
7
7
|
|
8
8
|
from .clients import (
|
9
9
|
AssertingEventsClient,
|
10
|
+
AssertingPassthroughEventsClient,
|
10
11
|
PrefectCloudEventsClient,
|
11
12
|
PrefectEventsClient,
|
12
13
|
)
|
@@ -49,6 +50,7 @@ def emit_event(
|
|
49
50
|
return None
|
50
51
|
|
51
52
|
operational_clients = [
|
53
|
+
AssertingPassthroughEventsClient,
|
52
54
|
AssertingEventsClient,
|
53
55
|
PrefectCloudEventsClient,
|
54
56
|
PrefectEventsClient,
|
prefect/events/worker.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from contextlib import asynccontextmanager
|
2
2
|
from contextvars import Context, copy_context
|
3
|
-
from typing import Any, Dict, Optional, Tuple, Type
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Type
|
4
4
|
from uuid import UUID
|
5
5
|
|
6
6
|
from typing_extensions import Self
|
@@ -22,6 +22,9 @@ from .clients import (
|
|
22
22
|
from .related import related_resources_from_run_context
|
23
23
|
from .schemas.events import Event
|
24
24
|
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from prefect.client.orchestration import PrefectClient
|
27
|
+
|
25
28
|
|
26
29
|
def should_emit_events() -> bool:
|
27
30
|
return (
|
@@ -55,14 +58,18 @@ class EventsWorker(QueueService[Event]):
|
|
55
58
|
self.client_type = client_type
|
56
59
|
self.client_options = client_options
|
57
60
|
self._client: EventsClient
|
61
|
+
self._orchestration_client: "PrefectClient"
|
58
62
|
self._context_cache: Dict[UUID, Context] = {}
|
59
63
|
|
60
64
|
@asynccontextmanager
|
61
65
|
async def _lifespan(self):
|
62
66
|
self._client = self.client_type(**{k: v for k, v in self.client_options})
|
67
|
+
from prefect.client.orchestration import get_client
|
63
68
|
|
69
|
+
self._orchestration_client = get_client()
|
64
70
|
async with self._client:
|
65
|
-
|
71
|
+
async with self._orchestration_client:
|
72
|
+
yield
|
66
73
|
|
67
74
|
def _prepare_item(self, event: Event) -> Event:
|
68
75
|
self._context_cache[event.id] = copy_context()
|
@@ -77,7 +84,9 @@ class EventsWorker(QueueService[Event]):
|
|
77
84
|
|
78
85
|
async def attach_related_resources_from_context(self, event: Event):
|
79
86
|
exclude = {resource.id for resource in event.involved_resources}
|
80
|
-
event.related += await related_resources_from_run_context(
|
87
|
+
event.related += await related_resources_from_run_context(
|
88
|
+
client=self._orchestration_client, exclude=exclude
|
89
|
+
)
|
81
90
|
|
82
91
|
@classmethod
|
83
92
|
def instance(
|
prefect/exceptions.py
CHANGED
prefect/flow_engine.py
CHANGED
@@ -30,6 +30,7 @@ from prefect.client.schemas import FlowRun, TaskRun
|
|
30
30
|
from prefect.client.schemas.filters import FlowRunFilter
|
31
31
|
from prefect.client.schemas.sorting import FlowRunSort
|
32
32
|
from prefect.concurrency.context import ConcurrencyContext
|
33
|
+
from prefect.concurrency.v1.context import ConcurrencyContext as ConcurrencyContextV1
|
33
34
|
from prefect.context import FlowRunContext, SyncClientContext, TagsContext
|
34
35
|
from prefect.exceptions import (
|
35
36
|
Abort,
|
@@ -204,6 +205,7 @@ class FlowRunEngine(Generic[P, R]):
|
|
204
205
|
result_factory=run_coro_as_sync(ResultFactory.from_flow(self.flow)),
|
205
206
|
)
|
206
207
|
self.short_circuit = True
|
208
|
+
self.call_hooks()
|
207
209
|
|
208
210
|
new_state = Running()
|
209
211
|
state = self.set_state(new_state)
|
@@ -267,6 +269,7 @@ class FlowRunEngine(Generic[P, R]):
|
|
267
269
|
return_value_to_state(
|
268
270
|
resolved_result,
|
269
271
|
result_factory=result_factory,
|
272
|
+
write_result=True,
|
270
273
|
)
|
271
274
|
)
|
272
275
|
self.set_state(terminal_state)
|
@@ -286,6 +289,7 @@ class FlowRunEngine(Generic[P, R]):
|
|
286
289
|
message=msg or "Flow run encountered an exception:",
|
287
290
|
result_factory=result_factory
|
288
291
|
or getattr(context, "result_factory", None),
|
292
|
+
write_result=True,
|
289
293
|
)
|
290
294
|
)
|
291
295
|
state = self.set_state(terminal_state)
|
@@ -506,6 +510,7 @@ class FlowRunEngine(Generic[P, R]):
|
|
506
510
|
task_runner=task_runner,
|
507
511
|
)
|
508
512
|
)
|
513
|
+
stack.enter_context(ConcurrencyContextV1())
|
509
514
|
stack.enter_context(ConcurrencyContext())
|
510
515
|
|
511
516
|
# set the logger to the flow run logger
|
prefect/flows.py
CHANGED
@@ -642,7 +642,8 @@ class Flow(Generic[P, R]):
|
|
642
642
|
cron: Optional[Union[Iterable[str], str]] = None,
|
643
643
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
644
644
|
paused: Optional[bool] = None,
|
645
|
-
schedules: Optional[
|
645
|
+
schedules: Optional["FlexibleScheduleList"] = None,
|
646
|
+
concurrency_limit: Optional[int] = None,
|
646
647
|
parameters: Optional[dict] = None,
|
647
648
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
648
649
|
description: Optional[str] = None,
|
@@ -666,6 +667,7 @@ class Flow(Generic[P, R]):
|
|
666
667
|
paused: Whether or not to set this deployment as paused.
|
667
668
|
schedules: A list of schedule objects defining when to execute runs of this deployment.
|
668
669
|
Used to define multiple schedules or additional scheduling options such as `timezone`.
|
670
|
+
concurrency_limit: The maximum number of runs of this deployment that can run at the same time.
|
669
671
|
parameters: A dictionary of default parameter values to pass to runs of this deployment.
|
670
672
|
triggers: A list of triggers that will kick off runs of this deployment.
|
671
673
|
description: A description for the created deployment. Defaults to the flow's
|
@@ -718,6 +720,7 @@ class Flow(Generic[P, R]):
|
|
718
720
|
rrule=rrule,
|
719
721
|
paused=paused,
|
720
722
|
schedules=schedules,
|
723
|
+
concurrency_limit=concurrency_limit,
|
721
724
|
tags=tags,
|
722
725
|
triggers=triggers,
|
723
726
|
parameters=parameters or {},
|
@@ -727,7 +730,7 @@ class Flow(Generic[P, R]):
|
|
727
730
|
work_pool_name=work_pool_name,
|
728
731
|
work_queue_name=work_queue_name,
|
729
732
|
job_variables=job_variables,
|
730
|
-
)
|
733
|
+
) # type: ignore # TODO: remove sync_compatible
|
731
734
|
else:
|
732
735
|
return RunnerDeployment.from_flow(
|
733
736
|
self,
|
@@ -737,6 +740,7 @@ class Flow(Generic[P, R]):
|
|
737
740
|
rrule=rrule,
|
738
741
|
paused=paused,
|
739
742
|
schedules=schedules,
|
743
|
+
concurrency_limit=concurrency_limit,
|
740
744
|
tags=tags,
|
741
745
|
triggers=triggers,
|
742
746
|
parameters=parameters or {},
|
@@ -1055,6 +1059,7 @@ class Flow(Generic[P, R]):
|
|
1055
1059
|
rrule: Optional[str] = None,
|
1056
1060
|
paused: Optional[bool] = None,
|
1057
1061
|
schedules: Optional[List[DeploymentScheduleCreate]] = None,
|
1062
|
+
concurrency_limit: Optional[int] = None,
|
1058
1063
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
1059
1064
|
parameters: Optional[dict] = None,
|
1060
1065
|
description: Optional[str] = None,
|
@@ -1101,6 +1106,7 @@ class Flow(Generic[P, R]):
|
|
1101
1106
|
paused: Whether or not to set this deployment as paused.
|
1102
1107
|
schedules: A list of schedule objects defining when to execute runs of this deployment.
|
1103
1108
|
Used to define multiple schedules or additional scheduling options like `timezone`.
|
1109
|
+
concurrency_limit: The maximum number of runs that can be executed concurrently.
|
1104
1110
|
parameters: A dictionary of default parameter values to pass to runs of this deployment.
|
1105
1111
|
description: A description for the created deployment. Defaults to the flow's
|
1106
1112
|
description if not provided.
|
@@ -1175,6 +1181,7 @@ class Flow(Generic[P, R]):
|
|
1175
1181
|
cron=cron,
|
1176
1182
|
rrule=rrule,
|
1177
1183
|
schedules=schedules,
|
1184
|
+
concurrency_limit=concurrency_limit,
|
1178
1185
|
paused=paused,
|
1179
1186
|
triggers=triggers,
|
1180
1187
|
parameters=parameters,
|
prefect/logging/handlers.py
CHANGED
@@ -157,7 +157,10 @@ class APILogHandler(logging.Handler):
|
|
157
157
|
if log_handling_when_missing_flow == "warn":
|
158
158
|
# Warn when a logger is used outside of a run context, the stack level here
|
159
159
|
# gets us to the user logging call
|
160
|
-
warnings.warn(
|
160
|
+
warnings.warn(
|
161
|
+
f"{exc} Set PREFECT_LOGGING_TO_API_WHEN_MISSING_FLOW=ignore to suppress this warning.",
|
162
|
+
stacklevel=8,
|
163
|
+
)
|
161
164
|
return
|
162
165
|
elif log_handling_when_missing_flow == "ignore":
|
163
166
|
return
|
prefect/main.py
CHANGED
@@ -6,7 +6,6 @@ from prefect.flows import flow, Flow, serve
|
|
6
6
|
from prefect.transactions import Transaction
|
7
7
|
from prefect.tasks import task, Task
|
8
8
|
from prefect.context import tags
|
9
|
-
from prefect.manifests import Manifest
|
10
9
|
from prefect.utilities.annotations import unmapped, allow_failure
|
11
10
|
from prefect.results import BaseResult
|
12
11
|
from prefect.flow_runs import pause_flow_run, resume_flow_run, suspend_flow_run
|
@@ -26,10 +25,14 @@ import prefect.context
|
|
26
25
|
# Perform any forward-ref updates needed for Pydantic models
|
27
26
|
import prefect.client.schemas
|
28
27
|
|
29
|
-
prefect.context.FlowRunContext.model_rebuild(
|
30
|
-
|
31
|
-
|
32
|
-
prefect.
|
28
|
+
prefect.context.FlowRunContext.model_rebuild(
|
29
|
+
_types_namespace={"Flow": Flow, "BaseResult": BaseResult}
|
30
|
+
)
|
31
|
+
prefect.context.TaskRunContext.model_rebuild(_types_namespace={"Task": Task})
|
32
|
+
prefect.client.schemas.State.model_rebuild(_types_namespace={"BaseResult": BaseResult})
|
33
|
+
prefect.client.schemas.StateCreate.model_rebuild(
|
34
|
+
_types_namespace={"BaseResult": BaseResult}
|
35
|
+
)
|
33
36
|
Transaction.model_rebuild()
|
34
37
|
|
35
38
|
# Configure logging
|
@@ -55,7 +58,6 @@ __all__ = [
|
|
55
58
|
"Flow",
|
56
59
|
"get_client",
|
57
60
|
"get_run_logger",
|
58
|
-
"Manifest",
|
59
61
|
"State",
|
60
62
|
"tags",
|
61
63
|
"task",
|
prefect/records/base.py
CHANGED
@@ -1,22 +1,88 @@
|
|
1
|
+
import abc
|
1
2
|
import os
|
2
3
|
import socket
|
3
4
|
import threading
|
4
5
|
from contextlib import contextmanager
|
5
6
|
from dataclasses import dataclass
|
6
|
-
from typing import Optional
|
7
|
+
from typing import TYPE_CHECKING, Optional
|
7
8
|
|
8
|
-
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from prefect.results import BaseResult
|
11
|
+
from prefect.transactions import IsolationLevel
|
9
12
|
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
@dataclass
|
15
|
+
class TransactionRecord:
|
16
|
+
"""
|
17
|
+
A dataclass representation of a transaction record.
|
18
|
+
"""
|
14
19
|
|
15
|
-
|
16
|
-
|
20
|
+
key: str
|
21
|
+
result: "BaseResult"
|
22
|
+
|
23
|
+
|
24
|
+
class RecordStore(abc.ABC):
|
25
|
+
@abc.abstractmethod
|
26
|
+
def read(
|
27
|
+
self, key: str, holder: Optional[str] = None
|
28
|
+
) -> Optional[TransactionRecord]:
|
29
|
+
"""
|
30
|
+
Read the transaction record with the given key.
|
31
|
+
|
32
|
+
Args:
|
33
|
+
key: Unique identifier for the transaction record.
|
34
|
+
holder: Unique identifier for the holder of the lock. If a lock exists on
|
35
|
+
the record being written, the read will be blocked until the lock is
|
36
|
+
released if the provided holder does not match the holder of the lock.
|
37
|
+
If not provided, a default holder based on the current host, process,
|
38
|
+
and thread will be used.
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
TransactionRecord: The transaction record with the given key.
|
42
|
+
"""
|
43
|
+
...
|
44
|
+
|
45
|
+
@abc.abstractmethod
|
46
|
+
def write(self, key: str, result: "BaseResult", holder: Optional[str] = None):
|
47
|
+
"""
|
48
|
+
Write the transaction record with the given key.
|
49
|
+
|
50
|
+
Args:
|
51
|
+
key: Unique identifier for the transaction record.
|
52
|
+
record: The transaction record to write.
|
53
|
+
holder: Unique identifier for the holder of the lock. If a lock exists on
|
54
|
+
the record being written, the write will be rejected if the provided
|
55
|
+
holder does not match the holder of the lock. If not provided,
|
56
|
+
a default holder based on the current host, process, and thread will
|
57
|
+
be used.
|
58
|
+
"""
|
59
|
+
...
|
17
60
|
|
61
|
+
@abc.abstractmethod
|
18
62
|
def exists(self, key: str) -> bool:
|
19
|
-
|
63
|
+
"""
|
64
|
+
Check if the transaction record with the given key exists.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
key: Unique identifier for the transaction record.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
bool: True if the record exists; False otherwise.
|
71
|
+
"""
|
72
|
+
...
|
73
|
+
|
74
|
+
@abc.abstractmethod
|
75
|
+
def supports_isolation_level(self, isolation_level: "IsolationLevel") -> bool:
|
76
|
+
"""
|
77
|
+
Check if the record store supports the given isolation level.
|
78
|
+
|
79
|
+
Args:
|
80
|
+
isolation_level: The isolation level to check.
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
bool: True if the record store supports the isolation level; False otherwise.
|
84
|
+
"""
|
85
|
+
...
|
20
86
|
|
21
87
|
def acquire_lock(
|
22
88
|
self,
|
@@ -155,13 +221,3 @@ class RecordStore:
|
|
155
221
|
yield
|
156
222
|
finally:
|
157
223
|
self.release_lock(key=key, holder=holder)
|
158
|
-
|
159
|
-
|
160
|
-
@dataclass
|
161
|
-
class TransactionRecord:
|
162
|
-
"""
|
163
|
-
A dataclass representation of a transaction record.
|
164
|
-
"""
|
165
|
-
|
166
|
-
key: str
|
167
|
-
result: Optional[BaseResult] = None
|