rappel 0.7.2__py3-none-macosx_15_0_arm64.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.
Potentially problematic release.
This version of rappel might be problematic. Click here for more details.
- proto/ast_pb2.py +121 -0
- proto/ast_pb2.pyi +1627 -0
- proto/ast_pb2_grpc.py +24 -0
- proto/ast_pb2_grpc.pyi +22 -0
- proto/messages_pb2.py +106 -0
- proto/messages_pb2.pyi +1231 -0
- proto/messages_pb2_grpc.py +406 -0
- proto/messages_pb2_grpc.pyi +380 -0
- rappel/__init__.py +61 -0
- rappel/actions.py +108 -0
- rappel/bin/boot-rappel-singleton +0 -0
- rappel/bin/rappel-bridge +0 -0
- rappel/bin/start-workers +0 -0
- rappel/bridge.py +228 -0
- rappel/dependencies.py +149 -0
- rappel/exceptions.py +18 -0
- rappel/formatter.py +110 -0
- rappel/ir_builder.py +3664 -0
- rappel/logger.py +39 -0
- rappel/registry.py +111 -0
- rappel/schedule.py +362 -0
- rappel/serialization.py +273 -0
- rappel/worker.py +191 -0
- rappel/workflow.py +251 -0
- rappel/workflow_runtime.py +287 -0
- rappel-0.7.2.data/scripts/boot-rappel-singleton +0 -0
- rappel-0.7.2.data/scripts/rappel-bridge +0 -0
- rappel-0.7.2.data/scripts/start-workers +0 -0
- rappel-0.7.2.dist-info/METADATA +308 -0
- rappel-0.7.2.dist-info/RECORD +32 -0
- rappel-0.7.2.dist-info/WHEEL +4 -0
- rappel-0.7.2.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@generated by mypy-protobuf. Do not edit manually!
|
|
3
|
+
isort:skip_file
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import abc
|
|
7
|
+
import collections.abc
|
|
8
|
+
import sys
|
|
9
|
+
import typing
|
|
10
|
+
|
|
11
|
+
import grpc
|
|
12
|
+
import grpc.aio
|
|
13
|
+
|
|
14
|
+
from proto import messages_pb2
|
|
15
|
+
|
|
16
|
+
if sys.version_info >= (3, 13):
|
|
17
|
+
import typing as typing_extensions
|
|
18
|
+
else:
|
|
19
|
+
import typing_extensions
|
|
20
|
+
|
|
21
|
+
_T = typing.TypeVar("_T")
|
|
22
|
+
|
|
23
|
+
class _MaybeAsyncIterator(
|
|
24
|
+
collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta
|
|
25
|
+
): ...
|
|
26
|
+
class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg]
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
GRPC_GENERATED_VERSION: str
|
|
30
|
+
GRPC_VERSION: str
|
|
31
|
+
_WorkerBridgeAttachType = typing_extensions.TypeVar(
|
|
32
|
+
"_WorkerBridgeAttachType",
|
|
33
|
+
grpc.StreamStreamMultiCallable[
|
|
34
|
+
messages_pb2.Envelope,
|
|
35
|
+
messages_pb2.Envelope,
|
|
36
|
+
],
|
|
37
|
+
grpc.aio.StreamStreamMultiCallable[
|
|
38
|
+
messages_pb2.Envelope,
|
|
39
|
+
messages_pb2.Envelope,
|
|
40
|
+
],
|
|
41
|
+
default=grpc.StreamStreamMultiCallable[
|
|
42
|
+
messages_pb2.Envelope,
|
|
43
|
+
messages_pb2.Envelope,
|
|
44
|
+
],
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
class WorkerBridgeStub(typing.Generic[_WorkerBridgeAttachType]):
|
|
48
|
+
"""=============================================================================
|
|
49
|
+
gRPC Service Definitions
|
|
50
|
+
=============================================================================
|
|
51
|
+
|
|
52
|
+
Bidirectional streaming service for worker communication.
|
|
53
|
+
Workers connect and maintain a persistent stream for action dispatch/results.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
@typing.overload
|
|
57
|
+
def __init__(
|
|
58
|
+
self: WorkerBridgeStub[
|
|
59
|
+
grpc.StreamStreamMultiCallable[
|
|
60
|
+
messages_pb2.Envelope,
|
|
61
|
+
messages_pb2.Envelope,
|
|
62
|
+
],
|
|
63
|
+
],
|
|
64
|
+
channel: grpc.Channel,
|
|
65
|
+
) -> None: ...
|
|
66
|
+
@typing.overload
|
|
67
|
+
def __init__(
|
|
68
|
+
self: WorkerBridgeStub[
|
|
69
|
+
grpc.aio.StreamStreamMultiCallable[
|
|
70
|
+
messages_pb2.Envelope,
|
|
71
|
+
messages_pb2.Envelope,
|
|
72
|
+
],
|
|
73
|
+
],
|
|
74
|
+
channel: grpc.aio.Channel,
|
|
75
|
+
) -> None: ...
|
|
76
|
+
|
|
77
|
+
Attach: _WorkerBridgeAttachType
|
|
78
|
+
|
|
79
|
+
WorkerBridgeAsyncStub: typing_extensions.TypeAlias = WorkerBridgeStub[
|
|
80
|
+
grpc.aio.StreamStreamMultiCallable[
|
|
81
|
+
messages_pb2.Envelope,
|
|
82
|
+
messages_pb2.Envelope,
|
|
83
|
+
],
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
class WorkerBridgeServicer(metaclass=abc.ABCMeta):
|
|
87
|
+
"""=============================================================================
|
|
88
|
+
gRPC Service Definitions
|
|
89
|
+
=============================================================================
|
|
90
|
+
|
|
91
|
+
Bidirectional streaming service for worker communication.
|
|
92
|
+
Workers connect and maintain a persistent stream for action dispatch/results.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
@abc.abstractmethod
|
|
96
|
+
def Attach(
|
|
97
|
+
self,
|
|
98
|
+
request_iterator: _MaybeAsyncIterator[messages_pb2.Envelope],
|
|
99
|
+
context: _ServicerContext,
|
|
100
|
+
) -> typing.Union[
|
|
101
|
+
collections.abc.Iterator[messages_pb2.Envelope],
|
|
102
|
+
collections.abc.AsyncIterator[messages_pb2.Envelope],
|
|
103
|
+
]: ...
|
|
104
|
+
|
|
105
|
+
def add_WorkerBridgeServicer_to_server(
|
|
106
|
+
servicer: WorkerBridgeServicer, server: typing.Union[grpc.Server, grpc.aio.Server]
|
|
107
|
+
) -> None: ...
|
|
108
|
+
|
|
109
|
+
_WorkflowServiceRegisterWorkflowType = typing_extensions.TypeVar(
|
|
110
|
+
"_WorkflowServiceRegisterWorkflowType",
|
|
111
|
+
grpc.UnaryUnaryMultiCallable[
|
|
112
|
+
messages_pb2.RegisterWorkflowRequest,
|
|
113
|
+
messages_pb2.RegisterWorkflowResponse,
|
|
114
|
+
],
|
|
115
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
116
|
+
messages_pb2.RegisterWorkflowRequest,
|
|
117
|
+
messages_pb2.RegisterWorkflowResponse,
|
|
118
|
+
],
|
|
119
|
+
default=grpc.UnaryUnaryMultiCallable[
|
|
120
|
+
messages_pb2.RegisterWorkflowRequest,
|
|
121
|
+
messages_pb2.RegisterWorkflowResponse,
|
|
122
|
+
],
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
_WorkflowServiceWaitForInstanceType = typing_extensions.TypeVar(
|
|
126
|
+
"_WorkflowServiceWaitForInstanceType",
|
|
127
|
+
grpc.UnaryUnaryMultiCallable[
|
|
128
|
+
messages_pb2.WaitForInstanceRequest,
|
|
129
|
+
messages_pb2.WaitForInstanceResponse,
|
|
130
|
+
],
|
|
131
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
132
|
+
messages_pb2.WaitForInstanceRequest,
|
|
133
|
+
messages_pb2.WaitForInstanceResponse,
|
|
134
|
+
],
|
|
135
|
+
default=grpc.UnaryUnaryMultiCallable[
|
|
136
|
+
messages_pb2.WaitForInstanceRequest,
|
|
137
|
+
messages_pb2.WaitForInstanceResponse,
|
|
138
|
+
],
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
_WorkflowServiceRegisterScheduleType = typing_extensions.TypeVar(
|
|
142
|
+
"_WorkflowServiceRegisterScheduleType",
|
|
143
|
+
grpc.UnaryUnaryMultiCallable[
|
|
144
|
+
messages_pb2.RegisterScheduleRequest,
|
|
145
|
+
messages_pb2.RegisterScheduleResponse,
|
|
146
|
+
],
|
|
147
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
148
|
+
messages_pb2.RegisterScheduleRequest,
|
|
149
|
+
messages_pb2.RegisterScheduleResponse,
|
|
150
|
+
],
|
|
151
|
+
default=grpc.UnaryUnaryMultiCallable[
|
|
152
|
+
messages_pb2.RegisterScheduleRequest,
|
|
153
|
+
messages_pb2.RegisterScheduleResponse,
|
|
154
|
+
],
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
_WorkflowServiceUpdateScheduleStatusType = typing_extensions.TypeVar(
|
|
158
|
+
"_WorkflowServiceUpdateScheduleStatusType",
|
|
159
|
+
grpc.UnaryUnaryMultiCallable[
|
|
160
|
+
messages_pb2.UpdateScheduleStatusRequest,
|
|
161
|
+
messages_pb2.UpdateScheduleStatusResponse,
|
|
162
|
+
],
|
|
163
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
164
|
+
messages_pb2.UpdateScheduleStatusRequest,
|
|
165
|
+
messages_pb2.UpdateScheduleStatusResponse,
|
|
166
|
+
],
|
|
167
|
+
default=grpc.UnaryUnaryMultiCallable[
|
|
168
|
+
messages_pb2.UpdateScheduleStatusRequest,
|
|
169
|
+
messages_pb2.UpdateScheduleStatusResponse,
|
|
170
|
+
],
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
_WorkflowServiceDeleteScheduleType = typing_extensions.TypeVar(
|
|
174
|
+
"_WorkflowServiceDeleteScheduleType",
|
|
175
|
+
grpc.UnaryUnaryMultiCallable[
|
|
176
|
+
messages_pb2.DeleteScheduleRequest,
|
|
177
|
+
messages_pb2.DeleteScheduleResponse,
|
|
178
|
+
],
|
|
179
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
180
|
+
messages_pb2.DeleteScheduleRequest,
|
|
181
|
+
messages_pb2.DeleteScheduleResponse,
|
|
182
|
+
],
|
|
183
|
+
default=grpc.UnaryUnaryMultiCallable[
|
|
184
|
+
messages_pb2.DeleteScheduleRequest,
|
|
185
|
+
messages_pb2.DeleteScheduleResponse,
|
|
186
|
+
],
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
_WorkflowServiceListSchedulesType = typing_extensions.TypeVar(
|
|
190
|
+
"_WorkflowServiceListSchedulesType",
|
|
191
|
+
grpc.UnaryUnaryMultiCallable[
|
|
192
|
+
messages_pb2.ListSchedulesRequest,
|
|
193
|
+
messages_pb2.ListSchedulesResponse,
|
|
194
|
+
],
|
|
195
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
196
|
+
messages_pb2.ListSchedulesRequest,
|
|
197
|
+
messages_pb2.ListSchedulesResponse,
|
|
198
|
+
],
|
|
199
|
+
default=grpc.UnaryUnaryMultiCallable[
|
|
200
|
+
messages_pb2.ListSchedulesRequest,
|
|
201
|
+
messages_pb2.ListSchedulesResponse,
|
|
202
|
+
],
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
class WorkflowServiceStub(
|
|
206
|
+
typing.Generic[
|
|
207
|
+
_WorkflowServiceRegisterWorkflowType,
|
|
208
|
+
_WorkflowServiceWaitForInstanceType,
|
|
209
|
+
_WorkflowServiceRegisterScheduleType,
|
|
210
|
+
_WorkflowServiceUpdateScheduleStatusType,
|
|
211
|
+
_WorkflowServiceDeleteScheduleType,
|
|
212
|
+
_WorkflowServiceListSchedulesType,
|
|
213
|
+
]
|
|
214
|
+
):
|
|
215
|
+
"""Workflow management service for client operations."""
|
|
216
|
+
|
|
217
|
+
@typing.overload
|
|
218
|
+
def __init__(
|
|
219
|
+
self: WorkflowServiceStub[
|
|
220
|
+
grpc.UnaryUnaryMultiCallable[
|
|
221
|
+
messages_pb2.RegisterWorkflowRequest,
|
|
222
|
+
messages_pb2.RegisterWorkflowResponse,
|
|
223
|
+
],
|
|
224
|
+
grpc.UnaryUnaryMultiCallable[
|
|
225
|
+
messages_pb2.WaitForInstanceRequest,
|
|
226
|
+
messages_pb2.WaitForInstanceResponse,
|
|
227
|
+
],
|
|
228
|
+
grpc.UnaryUnaryMultiCallable[
|
|
229
|
+
messages_pb2.RegisterScheduleRequest,
|
|
230
|
+
messages_pb2.RegisterScheduleResponse,
|
|
231
|
+
],
|
|
232
|
+
grpc.UnaryUnaryMultiCallable[
|
|
233
|
+
messages_pb2.UpdateScheduleStatusRequest,
|
|
234
|
+
messages_pb2.UpdateScheduleStatusResponse,
|
|
235
|
+
],
|
|
236
|
+
grpc.UnaryUnaryMultiCallable[
|
|
237
|
+
messages_pb2.DeleteScheduleRequest,
|
|
238
|
+
messages_pb2.DeleteScheduleResponse,
|
|
239
|
+
],
|
|
240
|
+
grpc.UnaryUnaryMultiCallable[
|
|
241
|
+
messages_pb2.ListSchedulesRequest,
|
|
242
|
+
messages_pb2.ListSchedulesResponse,
|
|
243
|
+
],
|
|
244
|
+
],
|
|
245
|
+
channel: grpc.Channel,
|
|
246
|
+
) -> None: ...
|
|
247
|
+
@typing.overload
|
|
248
|
+
def __init__(
|
|
249
|
+
self: WorkflowServiceStub[
|
|
250
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
251
|
+
messages_pb2.RegisterWorkflowRequest,
|
|
252
|
+
messages_pb2.RegisterWorkflowResponse,
|
|
253
|
+
],
|
|
254
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
255
|
+
messages_pb2.WaitForInstanceRequest,
|
|
256
|
+
messages_pb2.WaitForInstanceResponse,
|
|
257
|
+
],
|
|
258
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
259
|
+
messages_pb2.RegisterScheduleRequest,
|
|
260
|
+
messages_pb2.RegisterScheduleResponse,
|
|
261
|
+
],
|
|
262
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
263
|
+
messages_pb2.UpdateScheduleStatusRequest,
|
|
264
|
+
messages_pb2.UpdateScheduleStatusResponse,
|
|
265
|
+
],
|
|
266
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
267
|
+
messages_pb2.DeleteScheduleRequest,
|
|
268
|
+
messages_pb2.DeleteScheduleResponse,
|
|
269
|
+
],
|
|
270
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
271
|
+
messages_pb2.ListSchedulesRequest,
|
|
272
|
+
messages_pb2.ListSchedulesResponse,
|
|
273
|
+
],
|
|
274
|
+
],
|
|
275
|
+
channel: grpc.aio.Channel,
|
|
276
|
+
) -> None: ...
|
|
277
|
+
|
|
278
|
+
RegisterWorkflow: _WorkflowServiceRegisterWorkflowType
|
|
279
|
+
|
|
280
|
+
WaitForInstance: _WorkflowServiceWaitForInstanceType
|
|
281
|
+
|
|
282
|
+
RegisterSchedule: _WorkflowServiceRegisterScheduleType
|
|
283
|
+
"""Schedule management"""
|
|
284
|
+
|
|
285
|
+
UpdateScheduleStatus: _WorkflowServiceUpdateScheduleStatusType
|
|
286
|
+
|
|
287
|
+
DeleteSchedule: _WorkflowServiceDeleteScheduleType
|
|
288
|
+
|
|
289
|
+
ListSchedules: _WorkflowServiceListSchedulesType
|
|
290
|
+
|
|
291
|
+
WorkflowServiceAsyncStub: typing_extensions.TypeAlias = WorkflowServiceStub[
|
|
292
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
293
|
+
messages_pb2.RegisterWorkflowRequest,
|
|
294
|
+
messages_pb2.RegisterWorkflowResponse,
|
|
295
|
+
],
|
|
296
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
297
|
+
messages_pb2.WaitForInstanceRequest,
|
|
298
|
+
messages_pb2.WaitForInstanceResponse,
|
|
299
|
+
],
|
|
300
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
301
|
+
messages_pb2.RegisterScheduleRequest,
|
|
302
|
+
messages_pb2.RegisterScheduleResponse,
|
|
303
|
+
],
|
|
304
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
305
|
+
messages_pb2.UpdateScheduleStatusRequest,
|
|
306
|
+
messages_pb2.UpdateScheduleStatusResponse,
|
|
307
|
+
],
|
|
308
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
309
|
+
messages_pb2.DeleteScheduleRequest,
|
|
310
|
+
messages_pb2.DeleteScheduleResponse,
|
|
311
|
+
],
|
|
312
|
+
grpc.aio.UnaryUnaryMultiCallable[
|
|
313
|
+
messages_pb2.ListSchedulesRequest,
|
|
314
|
+
messages_pb2.ListSchedulesResponse,
|
|
315
|
+
],
|
|
316
|
+
]
|
|
317
|
+
|
|
318
|
+
class WorkflowServiceServicer(metaclass=abc.ABCMeta):
|
|
319
|
+
"""Workflow management service for client operations."""
|
|
320
|
+
|
|
321
|
+
@abc.abstractmethod
|
|
322
|
+
def RegisterWorkflow(
|
|
323
|
+
self,
|
|
324
|
+
request: messages_pb2.RegisterWorkflowRequest,
|
|
325
|
+
context: _ServicerContext,
|
|
326
|
+
) -> typing.Union[
|
|
327
|
+
messages_pb2.RegisterWorkflowResponse,
|
|
328
|
+
collections.abc.Awaitable[messages_pb2.RegisterWorkflowResponse],
|
|
329
|
+
]: ...
|
|
330
|
+
@abc.abstractmethod
|
|
331
|
+
def WaitForInstance(
|
|
332
|
+
self,
|
|
333
|
+
request: messages_pb2.WaitForInstanceRequest,
|
|
334
|
+
context: _ServicerContext,
|
|
335
|
+
) -> typing.Union[
|
|
336
|
+
messages_pb2.WaitForInstanceResponse,
|
|
337
|
+
collections.abc.Awaitable[messages_pb2.WaitForInstanceResponse],
|
|
338
|
+
]: ...
|
|
339
|
+
@abc.abstractmethod
|
|
340
|
+
def RegisterSchedule(
|
|
341
|
+
self,
|
|
342
|
+
request: messages_pb2.RegisterScheduleRequest,
|
|
343
|
+
context: _ServicerContext,
|
|
344
|
+
) -> typing.Union[
|
|
345
|
+
messages_pb2.RegisterScheduleResponse,
|
|
346
|
+
collections.abc.Awaitable[messages_pb2.RegisterScheduleResponse],
|
|
347
|
+
]:
|
|
348
|
+
"""Schedule management"""
|
|
349
|
+
|
|
350
|
+
@abc.abstractmethod
|
|
351
|
+
def UpdateScheduleStatus(
|
|
352
|
+
self,
|
|
353
|
+
request: messages_pb2.UpdateScheduleStatusRequest,
|
|
354
|
+
context: _ServicerContext,
|
|
355
|
+
) -> typing.Union[
|
|
356
|
+
messages_pb2.UpdateScheduleStatusResponse,
|
|
357
|
+
collections.abc.Awaitable[messages_pb2.UpdateScheduleStatusResponse],
|
|
358
|
+
]: ...
|
|
359
|
+
@abc.abstractmethod
|
|
360
|
+
def DeleteSchedule(
|
|
361
|
+
self,
|
|
362
|
+
request: messages_pb2.DeleteScheduleRequest,
|
|
363
|
+
context: _ServicerContext,
|
|
364
|
+
) -> typing.Union[
|
|
365
|
+
messages_pb2.DeleteScheduleResponse,
|
|
366
|
+
collections.abc.Awaitable[messages_pb2.DeleteScheduleResponse],
|
|
367
|
+
]: ...
|
|
368
|
+
@abc.abstractmethod
|
|
369
|
+
def ListSchedules(
|
|
370
|
+
self,
|
|
371
|
+
request: messages_pb2.ListSchedulesRequest,
|
|
372
|
+
context: _ServicerContext,
|
|
373
|
+
) -> typing.Union[
|
|
374
|
+
messages_pb2.ListSchedulesResponse,
|
|
375
|
+
collections.abc.Awaitable[messages_pb2.ListSchedulesResponse],
|
|
376
|
+
]: ...
|
|
377
|
+
|
|
378
|
+
def add_WorkflowServiceServicer_to_server(
|
|
379
|
+
servicer: WorkflowServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]
|
|
380
|
+
) -> None: ...
|
rappel/__init__.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Public API for user-defined rappel actions."""
|
|
2
|
+
|
|
3
|
+
from . import bridge # noqa: F401
|
|
4
|
+
from . import workflow_runtime as _workflow_runtime # noqa: F401
|
|
5
|
+
from .actions import (
|
|
6
|
+
ActionResultPayload,
|
|
7
|
+
action,
|
|
8
|
+
deserialize_result_payload,
|
|
9
|
+
serialize_error_payload,
|
|
10
|
+
serialize_result_payload,
|
|
11
|
+
)
|
|
12
|
+
from .dependencies import Depend, provide_dependencies
|
|
13
|
+
from .exceptions import (
|
|
14
|
+
ExhaustedRetries,
|
|
15
|
+
ExhaustedRetriesError,
|
|
16
|
+
ScheduleAlreadyExistsError,
|
|
17
|
+
)
|
|
18
|
+
from .ir_builder import UnsupportedPatternError, build_workflow_ir
|
|
19
|
+
from .registry import registry
|
|
20
|
+
from .schedule import (
|
|
21
|
+
ScheduleInfo,
|
|
22
|
+
delete_schedule,
|
|
23
|
+
list_schedules,
|
|
24
|
+
pause_schedule,
|
|
25
|
+
resume_schedule,
|
|
26
|
+
schedule_workflow,
|
|
27
|
+
)
|
|
28
|
+
from .workflow import (
|
|
29
|
+
RetryPolicy,
|
|
30
|
+
Workflow,
|
|
31
|
+
workflow,
|
|
32
|
+
workflow_registry,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"action",
|
|
37
|
+
"registry",
|
|
38
|
+
"ActionResultPayload",
|
|
39
|
+
"Workflow",
|
|
40
|
+
"workflow",
|
|
41
|
+
"workflow_registry",
|
|
42
|
+
"RetryPolicy",
|
|
43
|
+
"build_workflow_ir",
|
|
44
|
+
"serialize_result_payload",
|
|
45
|
+
"deserialize_result_payload",
|
|
46
|
+
"serialize_error_payload",
|
|
47
|
+
"Depend",
|
|
48
|
+
"provide_dependencies",
|
|
49
|
+
"bridge",
|
|
50
|
+
"ExhaustedRetries",
|
|
51
|
+
"ExhaustedRetriesError",
|
|
52
|
+
"ScheduleAlreadyExistsError",
|
|
53
|
+
"UnsupportedPatternError",
|
|
54
|
+
# Schedule functions
|
|
55
|
+
"schedule_workflow",
|
|
56
|
+
"pause_schedule",
|
|
57
|
+
"resume_schedule",
|
|
58
|
+
"delete_schedule",
|
|
59
|
+
"list_schedules",
|
|
60
|
+
"ScheduleInfo",
|
|
61
|
+
]
|
rappel/actions.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from typing import Any, Callable, Optional, TypeVar, overload
|
|
5
|
+
|
|
6
|
+
from proto import messages_pb2 as pb2
|
|
7
|
+
|
|
8
|
+
from .dependencies import provide_dependencies
|
|
9
|
+
from .registry import AsyncAction, registry
|
|
10
|
+
from .serialization import dumps, loads
|
|
11
|
+
|
|
12
|
+
TAsync = TypeVar("TAsync", bound=AsyncAction)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class ActionResultPayload:
|
|
17
|
+
result: Any | None
|
|
18
|
+
error: dict[str, Any] | None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def serialize_result_payload(value: Any) -> pb2.WorkflowArguments:
|
|
22
|
+
"""Serialize a successful action result."""
|
|
23
|
+
arguments = pb2.WorkflowArguments()
|
|
24
|
+
entry = arguments.arguments.add()
|
|
25
|
+
entry.key = "result"
|
|
26
|
+
entry.value.CopyFrom(dumps(value))
|
|
27
|
+
return arguments
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def serialize_error_payload(_action: str, exc: BaseException) -> pb2.WorkflowArguments:
|
|
31
|
+
"""Serialize an error raised during action execution."""
|
|
32
|
+
arguments = pb2.WorkflowArguments()
|
|
33
|
+
entry = arguments.arguments.add()
|
|
34
|
+
entry.key = "error"
|
|
35
|
+
entry.value.CopyFrom(dumps(exc))
|
|
36
|
+
return arguments
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def deserialize_result_payload(payload: pb2.WorkflowArguments | None) -> ActionResultPayload:
|
|
40
|
+
"""Deserialize WorkflowArguments produced by serialize_result_payload/error."""
|
|
41
|
+
if payload is None:
|
|
42
|
+
return ActionResultPayload(result=None, error=None)
|
|
43
|
+
values = {entry.key: entry.value for entry in payload.arguments}
|
|
44
|
+
if "error" in values:
|
|
45
|
+
error_value = values["error"]
|
|
46
|
+
data = loads(error_value)
|
|
47
|
+
if not isinstance(data, dict):
|
|
48
|
+
raise ValueError("error payload must deserialize to a mapping")
|
|
49
|
+
return ActionResultPayload(result=None, error=data)
|
|
50
|
+
result_value = values.get("result")
|
|
51
|
+
if result_value is None:
|
|
52
|
+
raise ValueError("result payload missing 'result' field")
|
|
53
|
+
return ActionResultPayload(result=loads(result_value), error=None)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@overload
|
|
57
|
+
def action(func: TAsync, /) -> TAsync: ...
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@overload
|
|
61
|
+
def action(*, name: Optional[str] = None) -> Callable[[TAsync], TAsync]: ...
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def action(
|
|
65
|
+
func: Optional[TAsync] = None,
|
|
66
|
+
*,
|
|
67
|
+
name: Optional[str] = None,
|
|
68
|
+
) -> Callable[[TAsync], TAsync] | TAsync:
|
|
69
|
+
"""Decorator for registering async actions.
|
|
70
|
+
|
|
71
|
+
Actions decorated with @action will automatically resolve Depend() markers
|
|
72
|
+
when called directly (e.g., during pytest runs where workflows bypass the
|
|
73
|
+
gRPC bridge).
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def decorator(target: TAsync) -> TAsync:
|
|
77
|
+
if not inspect.iscoroutinefunction(target):
|
|
78
|
+
raise TypeError(f"action '{target.__name__}' must be defined with 'async def'")
|
|
79
|
+
action_name = name or target.__name__
|
|
80
|
+
action_module = target.__module__
|
|
81
|
+
|
|
82
|
+
@wraps(target)
|
|
83
|
+
async def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
84
|
+
# Convert positional args to kwargs based on the signature
|
|
85
|
+
sig = inspect.signature(target)
|
|
86
|
+
params = list(sig.parameters.keys())
|
|
87
|
+
for i, arg in enumerate(args):
|
|
88
|
+
if i < len(params):
|
|
89
|
+
kwargs[params[i]] = arg
|
|
90
|
+
|
|
91
|
+
# Resolve dependencies using the same mechanism as execute_action
|
|
92
|
+
async with provide_dependencies(target, kwargs) as call_kwargs:
|
|
93
|
+
return await target(**call_kwargs)
|
|
94
|
+
|
|
95
|
+
# Copy over the original function's attributes for introspection
|
|
96
|
+
wrapper.__wrapped__ = target # type: ignore[attr-defined]
|
|
97
|
+
wrapper.__rappel_action_name__ = action_name # type: ignore[attr-defined]
|
|
98
|
+
wrapper.__rappel_action_module__ = action_module # type: ignore[attr-defined]
|
|
99
|
+
|
|
100
|
+
# Register the original function (not the wrapper) so execute_action
|
|
101
|
+
# doesn't double-resolve dependencies
|
|
102
|
+
registry.register(action_module, action_name, target)
|
|
103
|
+
|
|
104
|
+
return wrapper # type: ignore[return-value]
|
|
105
|
+
|
|
106
|
+
if func is not None:
|
|
107
|
+
return decorator(func)
|
|
108
|
+
return decorator
|
|
Binary file
|
rappel/bin/rappel-bridge
ADDED
|
Binary file
|
rappel/bin/start-workers
ADDED
|
Binary file
|