plexspaces 0.1.1__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.
- plexspaces/__init__.py +80 -0
- plexspaces/actor_id.py +114 -0
- plexspaces/decorators.py +691 -0
- plexspaces/generated/__init__.py +0 -0
- plexspaces/generated/buf/__init__.py +0 -0
- plexspaces/generated/buf/validate/__init__.py +3799 -0
- plexspaces/generated/google/__init__.py +0 -0
- plexspaces/generated/google/api/__init__.py +379 -0
- plexspaces/generated/grpc/__init__.py +0 -0
- plexspaces/generated/grpc/gateway/__init__.py +0 -0
- plexspaces/generated/grpc/gateway/protoc_gen_openapiv2/__init__.py +0 -0
- plexspaces/generated/grpc/gateway/protoc_gen_openapiv2/options/__init__.py +1022 -0
- plexspaces/generated/plexspaces/__init__.py +0 -0
- plexspaces/generated/plexspaces/actor/__init__.py +0 -0
- plexspaces/generated/plexspaces/actor/v1/__init__.py +3538 -0
- plexspaces/generated/plexspaces/application/__init__.py +0 -0
- plexspaces/generated/plexspaces/application/v1/__init__.py +827 -0
- plexspaces/generated/plexspaces/behaviors/__init__.py +0 -0
- plexspaces/generated/plexspaces/behaviors/v1/__init__.py +63 -0
- plexspaces/generated/plexspaces/channel/__init__.py +0 -0
- plexspaces/generated/plexspaces/channel/v1/__init__.py +915 -0
- plexspaces/generated/plexspaces/circuitbreaker/__init__.py +0 -0
- plexspaces/generated/plexspaces/circuitbreaker/prv/__init__.py +398 -0
- plexspaces/generated/plexspaces/common/__init__.py +0 -0
- plexspaces/generated/plexspaces/common/v1/__init__.py +691 -0
- plexspaces/generated/plexspaces/config/__init__.py +0 -0
- plexspaces/generated/plexspaces/config/v1/__init__.py +109 -0
- plexspaces/generated/plexspaces/dashboard/__init__.py +0 -0
- plexspaces/generated/plexspaces/dashboard/v1/__init__.py +647 -0
- plexspaces/generated/plexspaces/facets/__init__.py +0 -0
- plexspaces/generated/plexspaces/facets/v1/__init__.py +333 -0
- plexspaces/generated/plexspaces/firecracker/__init__.py +0 -0
- plexspaces/generated/plexspaces/firecracker/v1/__init__.py +890 -0
- plexspaces/generated/plexspaces/grpc/__init__.py +0 -0
- plexspaces/generated/plexspaces/grpc/v1/__init__.py +679 -0
- plexspaces/generated/plexspaces/journaling/__init__.py +0 -0
- plexspaces/generated/plexspaces/journaling/v1/__init__.py +1006 -0
- plexspaces/generated/plexspaces/keyvalue/__init__.py +0 -0
- plexspaces/generated/plexspaces/keyvalue/v1/__init__.py +1007 -0
- plexspaces/generated/plexspaces/locks/__init__.py +0 -0
- plexspaces/generated/plexspaces/locks/prv/__init__.py +122 -0
- plexspaces/generated/plexspaces/mailbox/__init__.py +0 -0
- plexspaces/generated/plexspaces/mailbox/v1/__init__.py +246 -0
- plexspaces/generated/plexspaces/metrics/__init__.py +0 -0
- plexspaces/generated/plexspaces/metrics/v1/__init__.py +878 -0
- plexspaces/generated/plexspaces/node/__init__.py +0 -0
- plexspaces/generated/plexspaces/node/v1/__init__.py +2564 -0
- plexspaces/generated/plexspaces/object_registry/__init__.py +0 -0
- plexspaces/generated/plexspaces/object_registry/v1/__init__.py +759 -0
- plexspaces/generated/plexspaces/persistence/__init__.py +0 -0
- plexspaces/generated/plexspaces/persistence/prv/__init__.py +539 -0
- plexspaces/generated/plexspaces/pool/__init__.py +0 -0
- plexspaces/generated/plexspaces/pool/v1/__init__.py +791 -0
- plexspaces/generated/plexspaces/processgroups/__init__.py +0 -0
- plexspaces/generated/plexspaces/processgroups/v1/__init__.py +622 -0
- plexspaces/generated/plexspaces/scheduling/__init__.py +0 -0
- plexspaces/generated/plexspaces/scheduling/v1/__init__.py +364 -0
- plexspaces/generated/plexspaces/security/__init__.py +0 -0
- plexspaces/generated/plexspaces/security/v1/__init__.py +254 -0
- plexspaces/generated/plexspaces/services/__init__.py +0 -0
- plexspaces/generated/plexspaces/services/prv/__init__.py +112 -0
- plexspaces/generated/plexspaces/storage/__init__.py +0 -0
- plexspaces/generated/plexspaces/storage/v1/__init__.py +747 -0
- plexspaces/generated/plexspaces/supervision/__init__.py +0 -0
- plexspaces/generated/plexspaces/supervision/v1/__init__.py +536 -0
- plexspaces/generated/plexspaces/system/__init__.py +0 -0
- plexspaces/generated/plexspaces/system/v1/__init__.py +1602 -0
- plexspaces/generated/plexspaces/timer/__init__.py +0 -0
- plexspaces/generated/plexspaces/timer/v1/__init__.py +402 -0
- plexspaces/generated/plexspaces/tuplespace/__init__.py +0 -0
- plexspaces/generated/plexspaces/tuplespace/v1/__init__.py +869 -0
- plexspaces/generated/plexspaces/wasm/__init__.py +0 -0
- plexspaces/generated/plexspaces/wasm/v1/__init__.py +920 -0
- plexspaces/generated/plexspaces/workflow/__init__.py +0 -0
- plexspaces/generated/plexspaces/workflow/v1/__init__.py +870 -0
- plexspaces/host.py +2093 -0
- plexspaces/leader_worker.py +148 -0
- plexspaces/proto_wire.py +1357 -0
- plexspaces/runtime.py +284 -0
- plexspaces/workflow.py +105 -0
- plexspaces-0.1.1.dist-info/METADATA +505 -0
- plexspaces-0.1.1.dist-info/RECORD +87 -0
- plexspaces-0.1.1.dist-info/WHEEL +5 -0
- plexspaces-0.1.1.dist-info/entry_points.txt +2 -0
- plexspaces-0.1.1.dist-info/top_level.txt +2 -0
- plexspaces_cli/__init__.py +8 -0
- plexspaces_cli/build.py +374 -0
|
@@ -0,0 +1,3538 @@
|
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
2
|
+
# sources: plexspaces/v1/actors/actor_runtime.proto, plexspaces/v1/actors/types.proto
|
|
3
|
+
# plugin: python-betterproto
|
|
4
|
+
# This file has been @generated
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from datetime import (
|
|
8
|
+
datetime,
|
|
9
|
+
timedelta,
|
|
10
|
+
)
|
|
11
|
+
from typing import (
|
|
12
|
+
TYPE_CHECKING,
|
|
13
|
+
AsyncIterable,
|
|
14
|
+
AsyncIterator,
|
|
15
|
+
Dict,
|
|
16
|
+
Iterable,
|
|
17
|
+
List,
|
|
18
|
+
Optional,
|
|
19
|
+
Union,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
import betterproto
|
|
23
|
+
import betterproto.lib.google.protobuf as betterproto_lib_google_protobuf
|
|
24
|
+
import grpclib
|
|
25
|
+
from betterproto.grpc.grpclib_server import ServiceBase
|
|
26
|
+
|
|
27
|
+
from ...common import v1 as __common_v1__
|
|
28
|
+
from ...supervision import v1 as __supervision_v1__
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
import grpclib.server
|
|
32
|
+
from betterproto.grpc.grpclib_client import MetadataLike
|
|
33
|
+
from grpclib.metadata import Deadline
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ActorState(betterproto.Enum):
|
|
37
|
+
"""
|
|
38
|
+
Actor lifecycle states.
|
|
39
|
+
|
|
40
|
+
## Purpose
|
|
41
|
+
Defines the state machine for actor lifecycle management and supervision.
|
|
42
|
+
|
|
43
|
+
## Why This Exists
|
|
44
|
+
- Enables supervision to track actor health and make restart decisions
|
|
45
|
+
- Supports graceful activation/deactivation (Orbit-inspired auto-activation)
|
|
46
|
+
- Allows migration state tracking for mobile agents
|
|
47
|
+
- Provides clear state transitions for debugging and monitoring
|
|
48
|
+
|
|
49
|
+
## State Transitions
|
|
50
|
+
```
|
|
51
|
+
CREATING -> ACTIVATING -> ACTIVE -> DEACTIVATING -> INACTIVE
|
|
52
|
+
\-> MIGRATING -> ACTIVE (on new node)
|
|
53
|
+
\-> FAILED -> (supervisor restarts)
|
|
54
|
+
\-> TERMINATED (permanent stop)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Design Notes
|
|
58
|
+
- UNSPECIFIED should never occur in valid states (indicates error)
|
|
59
|
+
- ACTIVATING/DEACTIVATING enable graceful lifecycle management
|
|
60
|
+
- MIGRATING supports actor mobility between nodes
|
|
61
|
+
- FAILED triggers supervisor restart policies
|
|
62
|
+
- FAILED state includes error message for debugging (see Actor message for error details)
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
UNSPECIFIED = 0
|
|
66
|
+
CREATING = 1
|
|
67
|
+
ACTIVE = 2
|
|
68
|
+
INACTIVE = 3
|
|
69
|
+
ACTIVATING = 4
|
|
70
|
+
DEACTIVATING = 5
|
|
71
|
+
STOPPING = 6
|
|
72
|
+
MIGRATING = 7
|
|
73
|
+
FAILED = 8
|
|
74
|
+
TERMINATED = 9
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ExitReason(betterproto.Enum):
|
|
78
|
+
"""
|
|
79
|
+
Exit reason for actor termination (Erlang/OTP-style)
|
|
80
|
+
|
|
81
|
+
## Purpose
|
|
82
|
+
Defines why an actor terminated, enabling proper supervision decisions
|
|
83
|
+
and link/monitor propagation semantics.
|
|
84
|
+
|
|
85
|
+
## Erlang Equivalent
|
|
86
|
+
Maps to Erlang's exit reasons:
|
|
87
|
+
- normal: Normal termination (not an error)
|
|
88
|
+
- shutdown: Graceful shutdown requested
|
|
89
|
+
- kill: Forcefully killed
|
|
90
|
+
- {error, Reason}: Error with message
|
|
91
|
+
- {linked, Pid, Reason}: Linked actor died
|
|
92
|
+
|
|
93
|
+
## Usage
|
|
94
|
+
- Used in Actor::terminate() and Actor::handle_exit() lifecycle hooks
|
|
95
|
+
- Propagated to linked actors (if trap_exit=false, causes cascading crash)
|
|
96
|
+
- Used by supervisors to decide restart policies
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
UNSPECIFIED = 0
|
|
100
|
+
NORMAL = 1
|
|
101
|
+
SHUTDOWN = 2
|
|
102
|
+
KILLED = 3
|
|
103
|
+
ERROR = 4
|
|
104
|
+
LINKED = 5
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ExitAction(betterproto.Enum):
|
|
108
|
+
"""
|
|
109
|
+
Exit action when handling EXIT from linked actor
|
|
110
|
+
|
|
111
|
+
## Purpose
|
|
112
|
+
Determines how an actor responds to EXIT signal from a linked actor.
|
|
113
|
+
Only relevant when ActorContext.trap_exit = true.
|
|
114
|
+
|
|
115
|
+
## Erlang Equivalent
|
|
116
|
+
Maps to Erlang's handle_exit behavior:
|
|
117
|
+
- Propagate: Actor will also terminate (default link behavior)
|
|
118
|
+
- Handle: Actor continues running (traps the exit)
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
UNSPECIFIED = 0
|
|
122
|
+
PROPAGATE = 1
|
|
123
|
+
HANDLE = 2
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class ActorErrorCode(betterproto.Enum):
|
|
127
|
+
ACTOR_ERROR_UNSPECIFIED = 0
|
|
128
|
+
ACTOR_ERROR_NOT_FOUND = 1
|
|
129
|
+
ACTOR_ERROR_ALREADY_EXISTS = 2
|
|
130
|
+
ACTOR_ERROR_INVALID_STATE = 3
|
|
131
|
+
ACTOR_ERROR_TIMEOUT = 4
|
|
132
|
+
ACTOR_ERROR_TERMINATED = 5
|
|
133
|
+
ACTOR_ERROR_FACET_ERROR = 6
|
|
134
|
+
ACTOR_ERROR_MAILBOX_ERROR = 7
|
|
135
|
+
ACTOR_ERROR_BEHAVIOR_ERROR = 8
|
|
136
|
+
ACTOR_ERROR_JOURNAL_ERROR = 9
|
|
137
|
+
ACTOR_ERROR_PLACEMENT_CONFLICT = 10
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class BehaviorErrorCode(betterproto.Enum):
|
|
141
|
+
BEHAVIOR_ERROR_UNSPECIFIED = 0
|
|
142
|
+
BEHAVIOR_ERROR_HANDLER_NOT_FOUND = 1
|
|
143
|
+
BEHAVIOR_ERROR_UNSUPPORTED_MESSAGE = 2
|
|
144
|
+
BEHAVIOR_ERROR_TRANSITION_FAILED = 3
|
|
145
|
+
BEHAVIOR_ERROR_PROCESSING_ERROR = 4
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class ActorIdErrorCode(betterproto.Enum):
|
|
149
|
+
ACTOR_ID_ERROR_UNSPECIFIED = 0
|
|
150
|
+
ACTOR_ID_ERROR_INVALID_NAME = 1
|
|
151
|
+
ACTOR_ID_ERROR_INVALID_ACTOR_TYPE = 2
|
|
152
|
+
ACTOR_ID_ERROR_MISSING_FIELD = 3
|
|
153
|
+
ACTOR_ID_ERROR_INVALID_FORMAT = 4
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class SupervisorErrorCode(betterproto.Enum):
|
|
157
|
+
SUPERVISOR_ERROR_UNSPECIFIED = 0
|
|
158
|
+
SUPERVISOR_ERROR_CHILD_START_FAILED = 1
|
|
159
|
+
SUPERVISOR_ERROR_MAX_RESTARTS_EXCEEDED = 2
|
|
160
|
+
SUPERVISOR_ERROR_CHILD_NOT_FOUND = 3
|
|
161
|
+
SUPERVISOR_ERROR_SHUTDOWN_TIMEOUT = 4
|
|
162
|
+
SUPERVISOR_ERROR_CONFIG_ERROR = 5
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class GenServerErrorCode(betterproto.Enum):
|
|
166
|
+
GEN_SERVER_ERROR_UNSPECIFIED = 0
|
|
167
|
+
GEN_SERVER_ERROR_SERIALIZATION = 1
|
|
168
|
+
GEN_SERVER_ERROR_CALL = 2
|
|
169
|
+
GEN_SERVER_ERROR_CAST = 3
|
|
170
|
+
GEN_SERVER_ERROR_SPAWN = 4
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class FsmErrorCode(betterproto.Enum):
|
|
174
|
+
FSM_ERROR_UNSPECIFIED = 0
|
|
175
|
+
FSM_ERROR_SERIALIZATION = 1
|
|
176
|
+
FSM_ERROR_TRANSITION = 2
|
|
177
|
+
FSM_ERROR_QUERY = 3
|
|
178
|
+
FSM_ERROR_SPAWN = 4
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class EventErrorCode(betterproto.Enum):
|
|
182
|
+
EVENT_ERROR_UNSPECIFIED = 0
|
|
183
|
+
EVENT_ERROR_SERIALIZATION = 1
|
|
184
|
+
EVENT_ERROR_EMIT = 2
|
|
185
|
+
EVENT_ERROR_SPAWN = 3
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class WorkflowRefErrorCode(betterproto.Enum):
|
|
189
|
+
WORKFLOW_REF_ERROR_UNSPECIFIED = 0
|
|
190
|
+
WORKFLOW_REF_ERROR_SERIALIZATION = 1
|
|
191
|
+
WORKFLOW_REF_ERROR_EXECUTION = 2
|
|
192
|
+
WORKFLOW_REF_ERROR_SPAWN = 3
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class VirtualActorErrorCode(betterproto.Enum):
|
|
196
|
+
VIRTUAL_ACTOR_ERROR_UNSPECIFIED = 0
|
|
197
|
+
VIRTUAL_ACTOR_ERROR_NOT_FOUND = 1
|
|
198
|
+
VIRTUAL_ACTOR_ERROR_ACTIVATION_FAILED = 2
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class PoolServiceErrorCode(betterproto.Enum):
|
|
202
|
+
POOL_SERVICE_ERROR_UNSPECIFIED = 0
|
|
203
|
+
POOL_SERVICE_ERROR_POOL_NOT_FOUND = 1
|
|
204
|
+
POOL_SERVICE_ERROR_CHECKOUT_TIMEOUT = 2
|
|
205
|
+
POOL_SERVICE_ERROR_POOL_EXHAUSTED = 3
|
|
206
|
+
POOL_SERVICE_ERROR_CIRCUIT_OPEN = 4
|
|
207
|
+
POOL_SERVICE_ERROR_POOL_DRAINING = 5
|
|
208
|
+
POOL_SERVICE_ERROR_INVALID_CONFIG = 6
|
|
209
|
+
POOL_SERVICE_ERROR_ACTOR_ERROR = 7
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class PlacementStrategy(betterproto.Enum):
|
|
213
|
+
"""Placement strategy for actor activation (Orleans-inspired)"""
|
|
214
|
+
|
|
215
|
+
UNSPECIFIED = 0
|
|
216
|
+
RANDOM = 1
|
|
217
|
+
PREFER_LOCAL = 2
|
|
218
|
+
LOAD_BASED = 3
|
|
219
|
+
RESOURCE_BASED = 4
|
|
220
|
+
AFFINITY = 5
|
|
221
|
+
CUSTOM = 99
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class LoadBalancingStrategy(betterproto.Enum):
|
|
225
|
+
LOAD_BALANCING_UNSPECIFIED = 0
|
|
226
|
+
LOAD_BALANCING_ROUND_ROBIN = 1
|
|
227
|
+
LOAD_BALANCING_LEAST_LOADED = 2
|
|
228
|
+
LOAD_BALANCING_RANDOM = 3
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class PartitionStrategy(betterproto.Enum):
|
|
232
|
+
"""Partition strategy for data-parallel actors"""
|
|
233
|
+
|
|
234
|
+
UNSPECIFIED = 0
|
|
235
|
+
HASH = 1
|
|
236
|
+
RANGE = 2
|
|
237
|
+
CONSISTENT_HASH = 3
|
|
238
|
+
CUSTOM = 99
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class RebalancePolicy(betterproto.Enum):
|
|
242
|
+
"""Rebalancing policy for data-parallel actors"""
|
|
243
|
+
|
|
244
|
+
UNSPECIFIED = 0
|
|
245
|
+
NONE = 1
|
|
246
|
+
ON_SCALE = 2
|
|
247
|
+
LOAD_BASED = 3
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class ShardGroupState(betterproto.Enum):
|
|
251
|
+
UNSPECIFIED = 0
|
|
252
|
+
CREATING = 1
|
|
253
|
+
ACTIVE = 2
|
|
254
|
+
REBALANCING = 3
|
|
255
|
+
DRAINING = 4
|
|
256
|
+
STOPPING = 5
|
|
257
|
+
STOPPED = 6
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class NodePlacementStrategy(betterproto.Enum):
|
|
261
|
+
"""
|
|
262
|
+
Node placement strategy for ShardGroup creation (leader-worker multi-node).
|
|
263
|
+
When absent or SAME_NODE, all shards are created on the node that receives the RPC.
|
|
264
|
+
FROM_REGISTRY uses NodeRegistry.list_nodes (optional cluster filter); NODE_IDS uses explicit list.
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
UNSPECIFIED = 0
|
|
268
|
+
SAME_NODE = 1
|
|
269
|
+
FROM_REGISTRY = 2
|
|
270
|
+
NODE_IDS = 3
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class ShardGroupAggregationStrategy(betterproto.Enum):
|
|
274
|
+
"""Aggregation strategy for scatter-gather results"""
|
|
275
|
+
|
|
276
|
+
SHARD_GROUP_AGGREGATION_UNSPECIFIED = 0
|
|
277
|
+
SHARD_GROUP_AGGREGATION_CONCAT = 1
|
|
278
|
+
SHARD_GROUP_AGGREGATION_MERGE = 2
|
|
279
|
+
SHARD_GROUP_AGGREGATION_FIRST = 3
|
|
280
|
+
SHARD_GROUP_AGGREGATION_MAJORITY = 4
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class CollectiveReduction(betterproto.Enum):
|
|
284
|
+
UNSPECIFIED = 0
|
|
285
|
+
SUM = 1
|
|
286
|
+
MIN = 2
|
|
287
|
+
MAX = 3
|
|
288
|
+
PRODUCT = 4
|
|
289
|
+
CONCAT = 5
|
|
290
|
+
BOOL_AND = 6
|
|
291
|
+
BOOL_OR = 7
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class StateMgmtMode(betterproto.Enum):
|
|
295
|
+
"""State management mode (lattice-based data-parallel actors)"""
|
|
296
|
+
|
|
297
|
+
UNSPECIFIED = 0
|
|
298
|
+
TRADITIONAL = 1
|
|
299
|
+
LATTICE = 2
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
class ConsistencyLevel(betterproto.Enum):
|
|
303
|
+
"""Consistency level for lattice-based actors"""
|
|
304
|
+
|
|
305
|
+
UNSPECIFIED = 0
|
|
306
|
+
EVENTUAL = 1
|
|
307
|
+
CAUSAL = 2
|
|
308
|
+
READ_COMMITTED = 3
|
|
309
|
+
LINEARIZABLE = 4
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class ActorVisibility(betterproto.Enum):
|
|
313
|
+
"""
|
|
314
|
+
Request to spawn an actor on a specific remote node (Erlang spawn/4 equivalent)
|
|
315
|
+
|
|
316
|
+
## Purpose
|
|
317
|
+
Spawns an actor on a specified remote node using pre-deployed actor type.
|
|
318
|
+
Returns an ActorRef for location-transparent messaging.
|
|
319
|
+
|
|
320
|
+
## Erlang Philosophy
|
|
321
|
+
In Erlang:
|
|
322
|
+
```erlang
|
|
323
|
+
% Local spawn (current node)
|
|
324
|
+
Pid = spawn(Module, Function, Args)
|
|
325
|
+
|
|
326
|
+
% Remote spawn (specific node)
|
|
327
|
+
Pid = spawn(Node, Module, Function, Args)
|
|
328
|
+
```
|
|
329
|
+
- Node: Target node (atom, e.g., 'worker@host1')
|
|
330
|
+
- Module: Pre-compiled module on remote node (e.g., 'gen_server')
|
|
331
|
+
- Function: Exported function to run (e.g., 'start_link')
|
|
332
|
+
- Args: Arguments to function (e.g., [initial_state])
|
|
333
|
+
- Returns: Pid that works for local and remote sends (location transparent)
|
|
334
|
+
|
|
335
|
+
## PlexSpaces Approach
|
|
336
|
+
```rust
|
|
337
|
+
// Local spawn (current node)
|
|
338
|
+
let actor = node.spawn_actor("worker", state, config).await?;
|
|
339
|
+
|
|
340
|
+
// Remote spawn (specific node)
|
|
341
|
+
let actor_ref = node.spawn_remote("node2", "worker", state, config).await?;
|
|
342
|
+
```
|
|
343
|
+
- target_node_id: Target node (string, e.g., "node2")
|
|
344
|
+
- actor_type: Pre-deployed actor type on remote node (string, e.g., "worker")
|
|
345
|
+
- initial_state: Serialized initial state (bytes)
|
|
346
|
+
- config: Actor configuration
|
|
347
|
+
- Returns: ActorRef in format "actor_id@node_id" for location-transparent messaging
|
|
348
|
+
|
|
349
|
+
## Key Assumptions (Erlang-Compatible)
|
|
350
|
+
1. **Code Pre-Deployed**: The actor_type must already exist on the target node
|
|
351
|
+
- Like Erlang: Module must be loaded on remote node
|
|
352
|
+
- Use CreateActor first to deploy actor type, or ensure it's in node's registry
|
|
353
|
+
2. **Location Transparency**: Returned ActorRef works the same for local and remote sends
|
|
354
|
+
- Like Erlang: Pid works for both local send (Pid ! Msg) and remote send
|
|
355
|
+
- ActorRef.tell() / ActorRef.ask() automatically routes to correct node
|
|
356
|
+
|
|
357
|
+
## Extensibility for WASM (Future - Week 11-12)
|
|
358
|
+
Phase 6 will add dynamic WASM deployment support via reserved fields:
|
|
359
|
+
```protobuf
|
|
360
|
+
oneof code_source {
|
|
361
|
+
string actor_type = 2; // Pre-deployed type (current)
|
|
362
|
+
WasmModule wasm_module = 10; // Deploy WASM on-the-fly (future)
|
|
363
|
+
string wasm_url = 11; // Fetch WASM from URL (future)
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
This enables:
|
|
367
|
+
- **Pre-deployed**: spawn_remote("node2", "worker", ...) - code already on node2
|
|
368
|
+
- **Dynamic WASM**: spawn_remote_wasm("node2", wasm_bytes, ...) - deploy code + spawn
|
|
369
|
+
- **URL-based**: spawn_remote_url("node2", "https://cdn/worker.wasm", ...) - fetch + deploy + spawn
|
|
370
|
+
|
|
371
|
+
## Use Cases
|
|
372
|
+
1. **Distributed Testing**: Spawn Byzantine generals on specific nodes
|
|
373
|
+
```rust
|
|
374
|
+
for (i, node) in nodes.iter().enumerate() {
|
|
375
|
+
node.spawn_remote(&node.id, "general", state, config).await?;
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
2. **Load Distribution**: Explicitly place workers across cluster
|
|
379
|
+
```rust
|
|
380
|
+
let worker_node = pick_least_loaded_node();
|
|
381
|
+
worker_node.spawn_remote(&worker_node.id, "worker", state, config).await?;
|
|
382
|
+
```
|
|
383
|
+
3. **Data Locality**: Spawn actor near data source
|
|
384
|
+
```rust
|
|
385
|
+
let db_node = find_node_with_shard(shard_id);
|
|
386
|
+
db_node.spawn_remote(&db_node.id, "processor", state, config).await?;
|
|
387
|
+
```
|
|
388
|
+
4. **Affinity**: Co-locate related actors on same node
|
|
389
|
+
```rust
|
|
390
|
+
let parent_node = get_actor_node(&parent_id);
|
|
391
|
+
parent_node.spawn_remote(&parent_node.id, "child", state, config).await?;
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Comparison to CreateActor
|
|
395
|
+
| Feature | CreateActor | SpawnActor |
|
|
396
|
+
|---------|-------------|------------------|
|
|
397
|
+
| Node selection | Placement strategy / current node | Explicit target node |
|
|
398
|
+
| Use case | General actor creation | Explicit remote placement |
|
|
399
|
+
| Fallback | Can fall back to other nodes | Fails if target unavailable |
|
|
400
|
+
| Erlang equivalent | spawn/3 (local) | spawn/4 (remote) |
|
|
401
|
+
| Code deployment | Any node can have code | Target node must have code |
|
|
402
|
+
|
|
403
|
+
## Implementation Flow
|
|
404
|
+
When node1 calls SpawnRemoteActor targeting node2:
|
|
405
|
+
1. node1 validates target_node_id exists in registry
|
|
406
|
+
2. node1 sends gRPC SpawnRemoteActor request to node2
|
|
407
|
+
3. node2 validates actor_type exists in local registry
|
|
408
|
+
4. node2 spawns actor locally: Actor::spawn(actor_type, state, config)
|
|
409
|
+
5. node2 returns ActorRef with format "actor-123@node2"
|
|
410
|
+
6. node1 caches remote ActorRef for future messaging
|
|
411
|
+
7. Subsequent tell/ask automatically routes via gRPC to node2
|
|
412
|
+
|
|
413
|
+
Who may invoke tell/ask on the spawned actor (enforced in ActorRef).
|
|
414
|
+
UNSPECIFIED is treated as PUBLIC by the runtime.
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
UNSPECIFIED = 0
|
|
418
|
+
PUBLIC = 1
|
|
419
|
+
"""Any tenant and namespace may message this actor."""
|
|
420
|
+
|
|
421
|
+
PROTECTED = 2
|
|
422
|
+
"""
|
|
423
|
+
Only callers in the same tenant_id may message; namespace may differ within the tenant.
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
PRIVATE = 3
|
|
427
|
+
"""Only callers matching both tenant_id and namespace may message."""
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
class MonitorType(betterproto.Enum):
|
|
431
|
+
"""
|
|
432
|
+
/ Monitor type (distinguishes Monitor from Link)
|
|
433
|
+
/
|
|
434
|
+
/ ## Purpose
|
|
435
|
+
/ Distinguishes between one-way monitoring (Monitor) and two-way death propagation (Link).
|
|
436
|
+
/ This enables clear API separation and proper handling of each type.
|
|
437
|
+
/
|
|
438
|
+
/ ## Erlang Philosophy
|
|
439
|
+
/ - **MONITOR**: One-way notification (Erlang `monitor/2`)
|
|
440
|
+
/ - Supervisor gets notified when actor dies
|
|
441
|
+
/ - Supervisor does NOT die when actor dies
|
|
442
|
+
/ - Used for observability, health checks
|
|
443
|
+
/
|
|
444
|
+
/ - **LINK**: Two-way death propagation (Erlang `link/1`)
|
|
445
|
+
/ - If actor1 dies, actor2 automatically dies (cascading)
|
|
446
|
+
/ - If actor2 dies, actor1 automatically dies (cascading)
|
|
447
|
+
/ - Used for tight coupling, supervision trees
|
|
448
|
+
/
|
|
449
|
+
/ ## Design Notes
|
|
450
|
+
/ - Monitors remain separate (existing functionality)
|
|
451
|
+
/ - Links enable cascading failures (new functionality)
|
|
452
|
+
/ - Supervision uses links internally (cohesive design)
|
|
453
|
+
"""
|
|
454
|
+
|
|
455
|
+
UNSPECIFIED = 0
|
|
456
|
+
MONITOR = 1
|
|
457
|
+
"""/ One-way monitoring (get notified, don't die)"""
|
|
458
|
+
|
|
459
|
+
LINK = 2
|
|
460
|
+
"""/ Two-way link (die together, cascading failures)"""
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class LifecycleEventType(betterproto.Enum):
|
|
464
|
+
"""Lifecycle event types for filtering"""
|
|
465
|
+
|
|
466
|
+
UNSPECIFIED = 0
|
|
467
|
+
CREATED = 1
|
|
468
|
+
STARTING = 2
|
|
469
|
+
ACTIVATED = 3
|
|
470
|
+
DEACTIVATING = 4
|
|
471
|
+
DEACTIVATED = 5
|
|
472
|
+
TERMINATED = 6
|
|
473
|
+
FAILED = 7
|
|
474
|
+
MIGRATING = 8
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class DropPolicy(betterproto.Enum):
|
|
478
|
+
"""Drop policy for buffer overflow (JavaNOW-inspired backpressure)"""
|
|
479
|
+
|
|
480
|
+
UNSPECIFIED = 0
|
|
481
|
+
DROP_OLDEST = 1
|
|
482
|
+
DROP_NEWEST = 2
|
|
483
|
+
BLOCK = 3
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class ActorRefErrorCode(betterproto.Enum):
|
|
487
|
+
"""ActorRef error codes"""
|
|
488
|
+
|
|
489
|
+
UNSPECIFIED = 0
|
|
490
|
+
ACTOR_NOT_FOUND = 1
|
|
491
|
+
SEND_FAILED = 2
|
|
492
|
+
MAILBOX_FULL = 3
|
|
493
|
+
ACTOR_TERMINATED = 4
|
|
494
|
+
TIMEOUT = 5
|
|
495
|
+
REMOTE_NOT_IMPLEMENTED = 6
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
class ResourceProfile(betterproto.Enum):
|
|
499
|
+
"""
|
|
500
|
+
Resource profile for an actor
|
|
501
|
+
Indicates what type of resources the actor primarily consumes
|
|
502
|
+
"""
|
|
503
|
+
|
|
504
|
+
UNSPECIFIED = 0
|
|
505
|
+
CPU_INTENSIVE = 1
|
|
506
|
+
MEMORY_INTENSIVE = 2
|
|
507
|
+
IO_INTENSIVE = 3
|
|
508
|
+
NETWORK_INTENSIVE = 4
|
|
509
|
+
BALANCED = 5
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
class ResourceViolationCode(betterproto.Enum):
|
|
513
|
+
"""Resource violation error codes"""
|
|
514
|
+
|
|
515
|
+
UNSPECIFIED = 0
|
|
516
|
+
CPU_EXCEEDED = 1
|
|
517
|
+
MEMORY_EXCEEDED = 2
|
|
518
|
+
IO_EXCEEDED = 3
|
|
519
|
+
NETWORK_EXCEEDED = 4
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
class ActorHealthStatus(betterproto.Enum):
|
|
523
|
+
"""Actor health status"""
|
|
524
|
+
|
|
525
|
+
UNSPECIFIED = 0
|
|
526
|
+
HEALTHY = 1
|
|
527
|
+
DEGRADED = 2
|
|
528
|
+
STUCK = 3
|
|
529
|
+
FAILED = 4
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
@dataclass(eq=False, repr=False)
|
|
533
|
+
class ExitReasonDetails(betterproto.Message):
|
|
534
|
+
"""Exit reason details (for EXIT_REASON_ERROR and EXIT_REASON_LINKED)"""
|
|
535
|
+
|
|
536
|
+
error_message: str = betterproto.string_field(1)
|
|
537
|
+
"""Error message (for EXIT_REASON_ERROR)"""
|
|
538
|
+
|
|
539
|
+
linked_actor_id: str = betterproto.string_field(2)
|
|
540
|
+
"""Linked actor ID (for EXIT_REASON_LINKED)"""
|
|
541
|
+
|
|
542
|
+
linked_reason: "ExitReason" = betterproto.enum_field(3)
|
|
543
|
+
"""Linked actor's exit reason (for EXIT_REASON_LINKED)"""
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
@dataclass(eq=False, repr=False)
|
|
547
|
+
class Actor(betterproto.Message):
|
|
548
|
+
"""
|
|
549
|
+
Actor instance representation.
|
|
550
|
+
|
|
551
|
+
## Purpose
|
|
552
|
+
Defines the complete state of a durable actor instance including its
|
|
553
|
+
identity, lifecycle state, configuration, resource usage, and attached capabilities.
|
|
554
|
+
|
|
555
|
+
## Why This Exists
|
|
556
|
+
- Actors are the fundamental unit of computation in PlexSpaces (Pillar 2: Erlang/OTP)
|
|
557
|
+
- Supports durable actors that survive restarts (Pillar 3: Restate durability)
|
|
558
|
+
- Enables resource-aware scheduling (Quickwit-inspired resource contracts)
|
|
559
|
+
- Provides facet extensibility (Static vs Dynamic principle)
|
|
560
|
+
- Tracks metrics for monitoring and health checks
|
|
561
|
+
|
|
562
|
+
## Design Notes
|
|
563
|
+
- actor_id uses ActorId from common.proto for consistency across services
|
|
564
|
+
- state tracks lifecycle for supervision and recovery logic
|
|
565
|
+
- node_id and vm_id support distributed placement and Firecracker isolation
|
|
566
|
+
- facets enable dynamic capability composition without changing core proto
|
|
567
|
+
- metrics enable health monitoring and auto-scaling decisions
|
|
568
|
+
"""
|
|
569
|
+
|
|
570
|
+
actor_id: str = betterproto.string_field(1)
|
|
571
|
+
actor_type: str = betterproto.string_field(2)
|
|
572
|
+
state: "ActorState" = betterproto.enum_field(3)
|
|
573
|
+
node_id: str = betterproto.string_field(4)
|
|
574
|
+
vm_id: str = betterproto.string_field(5)
|
|
575
|
+
actor_state: bytes = betterproto.bytes_field(6)
|
|
576
|
+
metadata: "__common_v1__.Metadata" = betterproto.message_field(7)
|
|
577
|
+
config: "ActorConfig" = betterproto.message_field(8)
|
|
578
|
+
metrics: "ActorMetrics" = betterproto.message_field(9)
|
|
579
|
+
facets: List["__common_v1__.Facet"] = betterproto.message_field(10)
|
|
580
|
+
"""
|
|
581
|
+
FACET EXTENSIBILITY: Attached facets provide additional capabilities
|
|
582
|
+
Examples: virtual_actor, otp_genserver, otp_supervisor, durable_execution, workflow
|
|
583
|
+
"""
|
|
584
|
+
|
|
585
|
+
actor_state_schema_version: int = betterproto.uint32_field(12)
|
|
586
|
+
"""
|
|
587
|
+
Schema version of actor_state serialization for format evolution
|
|
588
|
+
|
|
589
|
+
## Purpose
|
|
590
|
+
Enables safe actor state evolution across deployments and restarts.
|
|
591
|
+
Actors may be inactive for extended periods (days/weeks/months) and must
|
|
592
|
+
safely load old state when reactivated with newer actor code.
|
|
593
|
+
|
|
594
|
+
## Why This Exists
|
|
595
|
+
- Actor state schemas evolve over time (new fields, removed fields, type changes)
|
|
596
|
+
- Actors persist state to disk via checkpoints (see journaling.proto)
|
|
597
|
+
- Actors may migrate between nodes with different code versions
|
|
598
|
+
- Loading incompatible state causes corruption or panics
|
|
599
|
+
- Prevents data loss during rolling upgrades
|
|
600
|
+
|
|
601
|
+
## Version Rules
|
|
602
|
+
- **Version 0** = unversioned (assume version 1, best-effort deserialization)
|
|
603
|
+
- **Version >= 1** = explicit schema version tracked with actor state
|
|
604
|
+
- **Same version** (e.g., both v2) → Load directly, no migration needed
|
|
605
|
+
- **Older version** (state v1, actor v2) → Attempt migration if migration exists, else reject
|
|
606
|
+
- **Newer version** (state v3, actor v2) → **REJECT** with error (upgrade actor code first)
|
|
607
|
+
|
|
608
|
+
## Migration Strategy
|
|
609
|
+
```
|
|
610
|
+
Version 1 → 2: Add new field with default value (backward compatible, no migration)
|
|
611
|
+
Version 2 → 3: Remove deprecated field (backward compatible, no migration)
|
|
612
|
+
Version 3 → 4: Change field type (BREAKING - requires explicit migration function)
|
|
613
|
+
Version 4 → 5: Restructure nested fields (BREAKING - requires migration)
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
## Example Usage
|
|
617
|
+
```rust
|
|
618
|
+
// Actor implementation defines current schema version
|
|
619
|
+
impl CounterActor {
|
|
620
|
+
const SCHEMA_VERSION: u32 = 2;
|
|
621
|
+
|
|
622
|
+
fn save_state(&self) -> Result<Actor, PersistenceError> {
|
|
623
|
+
Ok(Actor {
|
|
624
|
+
actor_id: self.id.clone(),
|
|
625
|
+
actor_state: serialize(&self.internal_state)?,
|
|
626
|
+
actor_state_schema_version: Self::SCHEMA_VERSION,
|
|
627
|
+
// ... other fields ...
|
|
628
|
+
})
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
fn load_state(actor: &Actor) -> Result<Self, PersistenceError> {
|
|
632
|
+
// Version compatibility check
|
|
633
|
+
match actor.actor_state_schema_version {
|
|
634
|
+
// Same version - direct load
|
|
635
|
+
v if v == Self::SCHEMA_VERSION => {
|
|
636
|
+
let state: CounterState = deserialize(&actor.actor_state)?;
|
|
637
|
+
Ok(Self::from_state(state))
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Older version - migrate forward
|
|
641
|
+
v if v < Self::SCHEMA_VERSION => {
|
|
642
|
+
let migrated = migrate_counter_state(
|
|
643
|
+
&actor.actor_state,
|
|
644
|
+
v,
|
|
645
|
+
Self::SCHEMA_VERSION,
|
|
646
|
+
)?;
|
|
647
|
+
let state: CounterState = deserialize(&migrated)?;
|
|
648
|
+
Ok(Self::from_state(state))
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Newer version - reject (cannot load future state)
|
|
652
|
+
v => Err(PersistenceError::IncompatibleSchemaVersion {
|
|
653
|
+
actor_version: Self::SCHEMA_VERSION,
|
|
654
|
+
state_version: v,
|
|
655
|
+
message: format!(
|
|
656
|
+
"Actor state v{} is newer than actor code v{}. Upgrade actor first.",
|
|
657
|
+
v, Self::SCHEMA_VERSION
|
|
658
|
+
),
|
|
659
|
+
}),
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
## Integration with Checkpointing
|
|
666
|
+
This field works in conjunction with `Checkpoint.state_schema_version` from journaling.proto:
|
|
667
|
+
- **Actor.actor_state_schema_version**: Version of in-memory actor state (current)
|
|
668
|
+
- **Checkpoint.state_schema_version**: Version of checkpointed actor state (persistent)
|
|
669
|
+
|
|
670
|
+
When creating checkpoint:
|
|
671
|
+
```rust
|
|
672
|
+
let checkpoint = Checkpoint {
|
|
673
|
+
actor_id: actor.actor_id.clone(),
|
|
674
|
+
state_data: actor.actor_state.clone(),
|
|
675
|
+
state_schema_version: actor.actor_state_schema_version, // Copy version
|
|
676
|
+
// ...
|
|
677
|
+
};
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
## See Also
|
|
681
|
+
- `proto/plexspaces/v1/journaling.proto` - Checkpoint.state_schema_version (lines 241-321)
|
|
682
|
+
- `docs/SCHEMA_VERSIONING_REVIEW.md` - Complete versioning strategy
|
|
683
|
+
- Migration registry pattern for centralized v1→v2→v3 transitions
|
|
684
|
+
"""
|
|
685
|
+
|
|
686
|
+
error_message: str = betterproto.string_field(13)
|
|
687
|
+
"""
|
|
688
|
+
Error message when actor is in FAILED state
|
|
689
|
+
|
|
690
|
+
## Purpose
|
|
691
|
+
Provides error details when actor.state == ACTOR_STATE_FAILED.
|
|
692
|
+
Used for debugging, logging, and supervisor restart decisions.
|
|
693
|
+
|
|
694
|
+
## Usage
|
|
695
|
+
- Only populated when state == ACTOR_STATE_FAILED
|
|
696
|
+
- Empty string when state != ACTOR_STATE_FAILED
|
|
697
|
+
- Contains error message from actor crash or failure
|
|
698
|
+
"""
|
|
699
|
+
|
|
700
|
+
namespace: str = betterproto.string_field(14)
|
|
701
|
+
"""
|
|
702
|
+
Namespace for this actor's data isolation.
|
|
703
|
+
When actor is part of an application deployment, namespace must match application namespace.
|
|
704
|
+
Source of truth for namespace is the application (when deploying) or actor creation request.
|
|
705
|
+
"""
|
|
706
|
+
|
|
707
|
+
name: str = betterproto.string_field(15)
|
|
708
|
+
"""
|
|
709
|
+
User-specified actor name. Together with actor_type, namespace, and node_id
|
|
710
|
+
this forms the structured ActorId.
|
|
711
|
+
"""
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
@dataclass(eq=False, repr=False)
|
|
715
|
+
class ActorConfig(betterproto.Message):
|
|
716
|
+
"""Actor configuration"""
|
|
717
|
+
|
|
718
|
+
mailbox_timeout: timedelta = betterproto.message_field(1)
|
|
719
|
+
max_mailbox_size: int = betterproto.uint32_field(2)
|
|
720
|
+
enable_persistence: bool = betterproto.bool_field(3)
|
|
721
|
+
checkpoint_interval: timedelta = betterproto.message_field(4)
|
|
722
|
+
restart_policy: "__common_v1__.RetryPolicy" = betterproto.message_field(5)
|
|
723
|
+
supervision_strategy: "__supervision_v1__.SupervisionStrategy" = (
|
|
724
|
+
betterproto.enum_field(6)
|
|
725
|
+
)
|
|
726
|
+
properties: Dict[str, "betterproto_lib_google_protobuf.Any"] = (
|
|
727
|
+
betterproto.map_field(7, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE)
|
|
728
|
+
)
|
|
729
|
+
stateless_worker_config: "StatelessWorkerConfig" = betterproto.message_field(11)
|
|
730
|
+
"""Orleans-inspired stateless worker configuration"""
|
|
731
|
+
|
|
732
|
+
data_parallel_config: "DataParallelConfig" = betterproto.message_field(12)
|
|
733
|
+
"""Data-parallel configuration (if part of a shard group)"""
|
|
734
|
+
|
|
735
|
+
state_management_mode: "StateMgmtMode" = betterproto.enum_field(13)
|
|
736
|
+
"""State management mode (traditional vs lattice-based)"""
|
|
737
|
+
|
|
738
|
+
consistency_level: "ConsistencyLevel" = betterproto.enum_field(14)
|
|
739
|
+
"""Consistency level for lattice-based actors"""
|
|
740
|
+
|
|
741
|
+
resource_requirements: "ActorResourceRequirements" = betterproto.message_field(16)
|
|
742
|
+
"""Resource-aware scheduling: Actor resource requirements"""
|
|
743
|
+
|
|
744
|
+
actor_groups: List[str] = betterproto.string_field(17)
|
|
745
|
+
"""Shard group IDs (for task routing and co-scheduling)"""
|
|
746
|
+
|
|
747
|
+
config_schema_version: int = betterproto.uint32_field(15)
|
|
748
|
+
"""
|
|
749
|
+
Schema version of properties map for configuration evolution
|
|
750
|
+
|
|
751
|
+
## Purpose
|
|
752
|
+
Enables safe evolution of actor configuration across deployments.
|
|
753
|
+
The `properties` map (field 7) contains opaque configuration that may
|
|
754
|
+
change as actor types evolve, requiring versioning for compatibility.
|
|
755
|
+
|
|
756
|
+
## Why This Exists
|
|
757
|
+
- Actor configuration schemas evolve (new config options, deprecated settings)
|
|
758
|
+
- Actors may be created with old config and reactivated with new code
|
|
759
|
+
- Configuration migration needed during rolling upgrades
|
|
760
|
+
- Prevents invalid configuration causing actor startup failures
|
|
761
|
+
|
|
762
|
+
## Version Rules
|
|
763
|
+
- **Version 0** = unversioned (assume version 1)
|
|
764
|
+
- **Version >= 1** = explicit config schema version
|
|
765
|
+
- **Same version** → Use config directly
|
|
766
|
+
- **Older version** → Migrate config forward (e.g., add new defaults, remove deprecated)
|
|
767
|
+
- **Newer version** → REJECT (upgrade actor code first)
|
|
768
|
+
|
|
769
|
+
## Example Migration
|
|
770
|
+
```rust
|
|
771
|
+
// Version 1: Simple timeout config
|
|
772
|
+
properties: {"timeout_ms": 5000}
|
|
773
|
+
|
|
774
|
+
// Version 2: Added retry config (backward compatible)
|
|
775
|
+
properties: {
|
|
776
|
+
"timeout_ms": 5000,
|
|
777
|
+
"max_retries": 3, // NEW: defaults to 3
|
|
778
|
+
"retry_backoff_ms": 100 // NEW: defaults to 100ms
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Migration v1→v2: Add defaults for new fields
|
|
782
|
+
fn migrate_config_v1_to_v2(config: &mut ActorConfig) {
|
|
783
|
+
config.properties.entry("max_retries").or_insert(Any::from(3u32));
|
|
784
|
+
config.properties.entry("retry_backoff_ms").or_insert(Any::from(100u32));
|
|
785
|
+
config.config_schema_version = 2;
|
|
786
|
+
}
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
## See Also
|
|
790
|
+
- `Actor.actor_state_schema_version` - For actor state versioning
|
|
791
|
+
- `docs/SCHEMA_VERSIONING_REVIEW.md` - Complete versioning strategy
|
|
792
|
+
"""
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
@dataclass(eq=False, repr=False)
|
|
796
|
+
class ResourceRequirements(betterproto.Message):
|
|
797
|
+
"""Resource requirements for placement"""
|
|
798
|
+
|
|
799
|
+
min_memory_mb: int = betterproto.uint64_field(1)
|
|
800
|
+
min_cpu_cores: float = betterproto.double_field(2)
|
|
801
|
+
required_capabilities: List[str] = betterproto.string_field(3)
|
|
802
|
+
custom_requirements: Dict[str, str] = betterproto.map_field(
|
|
803
|
+
4, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
804
|
+
)
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
@dataclass(eq=False, repr=False)
|
|
808
|
+
class ActorResourceRequirements(betterproto.Message):
|
|
809
|
+
"""
|
|
810
|
+
Actor placement for resource-aware scheduling. Single source for labels, affinity, and resources.
|
|
811
|
+
Scheduler (crates/scheduler) uses placement.required_labels and placement.resource_requirements to select nodes.
|
|
812
|
+
"""
|
|
813
|
+
|
|
814
|
+
placement: "NodePlacement" = betterproto.message_field(1)
|
|
815
|
+
"""
|
|
816
|
+
Unified placement (strategy, required_labels, resource_requirements, preferred/avoid node IDs)
|
|
817
|
+
"""
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
@dataclass(eq=False, repr=False)
|
|
821
|
+
class StatelessWorkerConfig(betterproto.Message):
|
|
822
|
+
"""Stateless worker configuration (Orleans-inspired)"""
|
|
823
|
+
|
|
824
|
+
max_instances: int = betterproto.uint32_field(1)
|
|
825
|
+
"""Maximum number of concurrent instances"""
|
|
826
|
+
|
|
827
|
+
min_instances: int = betterproto.uint32_field(2)
|
|
828
|
+
"""Minimum number of instances to keep warm"""
|
|
829
|
+
|
|
830
|
+
strategy: "LoadBalancingStrategy" = betterproto.enum_field(3)
|
|
831
|
+
"""Load balancing strategy"""
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
@dataclass(eq=False, repr=False)
|
|
835
|
+
class DataParallelConfig(betterproto.Message):
|
|
836
|
+
"""
|
|
837
|
+
Data-parallel (shard group) strategy; same for all shards in the group.
|
|
838
|
+
Shard identity is implicit (index in ShardGroup.shard_actor_ids), not stored per-actor.
|
|
839
|
+
"""
|
|
840
|
+
|
|
841
|
+
group_id: str = betterproto.string_field(1)
|
|
842
|
+
"""Shard group ID"""
|
|
843
|
+
|
|
844
|
+
shard_count: int = betterproto.uint32_field(2)
|
|
845
|
+
"""Number of shards in the group (1 to 1 billion)"""
|
|
846
|
+
|
|
847
|
+
partition_strategy: "PartitionStrategy" = betterproto.enum_field(4)
|
|
848
|
+
"""Partitioning strategy"""
|
|
849
|
+
|
|
850
|
+
rebalance_policy: "RebalancePolicy" = betterproto.enum_field(5)
|
|
851
|
+
"""Rebalancing policy"""
|
|
852
|
+
|
|
853
|
+
placement: "NodePlacement" = betterproto.message_field(6)
|
|
854
|
+
"""
|
|
855
|
+
Node placement for multi-node leader-worker (same_node, from_registry, node_ids)
|
|
856
|
+
"""
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
@dataclass(eq=False, repr=False)
|
|
860
|
+
class ShardGroup(betterproto.Message):
|
|
861
|
+
"""
|
|
862
|
+
Shard group: unified config (DataParallelConfig) plus actor refs and state.
|
|
863
|
+
"""
|
|
864
|
+
|
|
865
|
+
config: "DataParallelConfig" = betterproto.message_field(1)
|
|
866
|
+
"""
|
|
867
|
+
Strategy for the group (group_id, shard_count, partition_strategy, rebalance_policy, placement)
|
|
868
|
+
"""
|
|
869
|
+
|
|
870
|
+
actor_type: str = betterproto.string_field(2)
|
|
871
|
+
shard_actor_ids: List[str] = betterproto.string_field(3)
|
|
872
|
+
state: "ShardGroupState" = betterproto.enum_field(4)
|
|
873
|
+
created_at: datetime = betterproto.message_field(5)
|
|
874
|
+
metadata: Dict[str, str] = betterproto.map_field(
|
|
875
|
+
6, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
876
|
+
)
|
|
877
|
+
rebalance_status: "RebalanceStatus" = betterproto.message_field(7)
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
@dataclass(eq=False, repr=False)
|
|
881
|
+
class RebalanceStatus(betterproto.Message):
|
|
882
|
+
"""Rebalancing status for shard groups"""
|
|
883
|
+
|
|
884
|
+
is_rebalancing: bool = betterproto.bool_field(1)
|
|
885
|
+
"""Is currently rebalancing"""
|
|
886
|
+
|
|
887
|
+
old_shard_count: int = betterproto.uint32_field(2)
|
|
888
|
+
"""Old shard count (before rebalancing)"""
|
|
889
|
+
|
|
890
|
+
new_shard_count: int = betterproto.uint32_field(3)
|
|
891
|
+
"""New shard count (after rebalancing)"""
|
|
892
|
+
|
|
893
|
+
progress_percent: float = betterproto.double_field(4)
|
|
894
|
+
"""Progress (0.0 to 100.0)"""
|
|
895
|
+
|
|
896
|
+
started_at: datetime = betterproto.message_field(5)
|
|
897
|
+
"""When rebalancing started"""
|
|
898
|
+
|
|
899
|
+
estimated_completion: datetime = betterproto.message_field(6)
|
|
900
|
+
"""Estimated completion time"""
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
@dataclass(eq=False, repr=False)
|
|
904
|
+
class NodePlacement(betterproto.Message):
|
|
905
|
+
"""
|
|
906
|
+
Unified node placement: strategy, affinity, and resource requirements.
|
|
907
|
+
Replaces PlacementHint, PlacementPreferences, and label/placement fields on ActorResourceRequirements.
|
|
908
|
+
Scheduler (crates/scheduler) matches nodes using required_labels and resource_requirements.
|
|
909
|
+
"""
|
|
910
|
+
|
|
911
|
+
strategy: "NodePlacementStrategy" = betterproto.enum_field(1)
|
|
912
|
+
cluster: str = betterproto.string_field(2)
|
|
913
|
+
"""
|
|
914
|
+
For FROM_REGISTRY: optional cluster name filter (empty = all connected nodes)
|
|
915
|
+
"""
|
|
916
|
+
|
|
917
|
+
node_ids: List[str] = betterproto.string_field(3)
|
|
918
|
+
"""For NODE_IDS: explicit node IDs to place shards on (round-robin)"""
|
|
919
|
+
|
|
920
|
+
required_labels: Dict[str, str] = betterproto.map_field(
|
|
921
|
+
4, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
922
|
+
)
|
|
923
|
+
"""
|
|
924
|
+
Node must match all labels (Kubernetes-inspired). Used by scheduler for node selection.
|
|
925
|
+
"""
|
|
926
|
+
|
|
927
|
+
avoid_node_ids: List[str] = betterproto.string_field(5)
|
|
928
|
+
"""Avoid node IDs (anti-affinity; scheduler excludes these)"""
|
|
929
|
+
|
|
930
|
+
resource_requirements: "__common_v1__.ResourceSpec" = betterproto.message_field(6)
|
|
931
|
+
"""
|
|
932
|
+
CPU, memory, disk, GPU requirements. Scheduler filters by NodeCapacity.available.
|
|
933
|
+
"""
|
|
934
|
+
|
|
935
|
+
affinity_labels: Dict[str, str] = betterproto.map_field(
|
|
936
|
+
7, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
937
|
+
)
|
|
938
|
+
"""
|
|
939
|
+
Affinity labels (co-location hint; scheduler may prefer nodes with matching labels)
|
|
940
|
+
"""
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
@dataclass(eq=False, repr=False)
|
|
944
|
+
class CreateShardGroupRequest(betterproto.Message):
|
|
945
|
+
config: "DataParallelConfig" = betterproto.message_field(1)
|
|
946
|
+
"""
|
|
947
|
+
Group strategy (group_id, shard_count, partition_strategy, rebalance_policy, placement)
|
|
948
|
+
Use config.placement.required_labels for node placement; scheduler matches nodes by placement.
|
|
949
|
+
"""
|
|
950
|
+
|
|
951
|
+
actor_type: str = betterproto.string_field(2)
|
|
952
|
+
shard_config: "ActorConfig" = betterproto.message_field(3)
|
|
953
|
+
"""
|
|
954
|
+
Per-shard ActorConfig (optional data_parallel_config here is ignored; use config above)
|
|
955
|
+
"""
|
|
956
|
+
|
|
957
|
+
initial_state: bytes = betterproto.bytes_field(4)
|
|
958
|
+
metadata: Dict[str, str] = betterproto.map_field(
|
|
959
|
+
5, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
960
|
+
)
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
@dataclass(eq=False, repr=False)
|
|
964
|
+
class CreateShardGroupResponse(betterproto.Message):
|
|
965
|
+
group: "ShardGroup" = betterproto.message_field(1)
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
@dataclass(eq=False, repr=False)
|
|
969
|
+
class DeleteShardGroupRequest(betterproto.Message):
|
|
970
|
+
group_id: str = betterproto.string_field(1)
|
|
971
|
+
force: bool = betterproto.bool_field(2)
|
|
972
|
+
shutdown_timeout: timedelta = betterproto.message_field(3)
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
@dataclass(eq=False, repr=False)
|
|
976
|
+
class GetShardGroupRequest(betterproto.Message):
|
|
977
|
+
group_id: str = betterproto.string_field(1)
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
@dataclass(eq=False, repr=False)
|
|
981
|
+
class GetShardGroupResponse(betterproto.Message):
|
|
982
|
+
group: "ShardGroup" = betterproto.message_field(1)
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
@dataclass(eq=False, repr=False)
|
|
986
|
+
class ListShardGroupsRequest(betterproto.Message):
|
|
987
|
+
actor_type: str = betterproto.string_field(1)
|
|
988
|
+
state: "ShardGroupState" = betterproto.enum_field(2)
|
|
989
|
+
page: "__common_v1__.PageRequest" = betterproto.message_field(3)
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
@dataclass(eq=False, repr=False)
|
|
993
|
+
class ListShardGroupsResponse(betterproto.Message):
|
|
994
|
+
groups: List["ShardGroup"] = betterproto.message_field(1)
|
|
995
|
+
page: "__common_v1__.PageResponse" = betterproto.message_field(2)
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
@dataclass(eq=False, repr=False)
|
|
999
|
+
class SendToShardRequest(betterproto.Message):
|
|
1000
|
+
group_id: str = betterproto.string_field(1)
|
|
1001
|
+
partition_key: bytes = betterproto.bytes_field(2)
|
|
1002
|
+
message: "__common_v1__.Message" = betterproto.message_field(3)
|
|
1003
|
+
wait_for_response: bool = betterproto.bool_field(4)
|
|
1004
|
+
timeout: timedelta = betterproto.message_field(5)
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
@dataclass(eq=False, repr=False)
|
|
1008
|
+
class SendToShardResponse(betterproto.Message):
|
|
1009
|
+
shard_id: int = betterproto.uint32_field(1)
|
|
1010
|
+
shard_actor_id: str = betterproto.string_field(2)
|
|
1011
|
+
response: "__common_v1__.Message" = betterproto.message_field(3)
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
@dataclass(eq=False, repr=False)
|
|
1015
|
+
class ScatterGatherRequest(betterproto.Message):
|
|
1016
|
+
group_id: str = betterproto.string_field(1)
|
|
1017
|
+
query: "__common_v1__.Message" = betterproto.message_field(2)
|
|
1018
|
+
timeout: timedelta = betterproto.message_field(3)
|
|
1019
|
+
aggregation: "ShardGroupAggregationStrategy" = betterproto.enum_field(4)
|
|
1020
|
+
min_responses: int = betterproto.uint32_field(5)
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
@dataclass(eq=False, repr=False)
|
|
1024
|
+
class ShardQueryResponse(betterproto.Message):
|
|
1025
|
+
shard_id: int = betterproto.uint32_field(1)
|
|
1026
|
+
shard_actor_id: str = betterproto.string_field(2)
|
|
1027
|
+
response: "__common_v1__.Message" = betterproto.message_field(3)
|
|
1028
|
+
latency: timedelta = betterproto.message_field(4)
|
|
1029
|
+
success: bool = betterproto.bool_field(5)
|
|
1030
|
+
error: str = betterproto.string_field(6)
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
@dataclass(eq=False, repr=False)
|
|
1034
|
+
class ScatterGatherStats(betterproto.Message):
|
|
1035
|
+
shards_queried: int = betterproto.uint32_field(1)
|
|
1036
|
+
shards_responded: int = betterproto.uint32_field(2)
|
|
1037
|
+
shards_failed: int = betterproto.uint32_field(3)
|
|
1038
|
+
max_latency: timedelta = betterproto.message_field(4)
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
@dataclass(eq=False, repr=False)
|
|
1042
|
+
class ScatterGatherResponse(betterproto.Message):
|
|
1043
|
+
result: "__common_v1__.Message" = betterproto.message_field(1)
|
|
1044
|
+
shard_responses: List["ShardQueryResponse"] = betterproto.message_field(2)
|
|
1045
|
+
stats: "ScatterGatherStats" = betterproto.message_field(3)
|
|
1046
|
+
|
|
1047
|
+
|
|
1048
|
+
@dataclass(eq=False, repr=False)
|
|
1049
|
+
class BulkUpdateShardGroupRequest(betterproto.Message):
|
|
1050
|
+
"""
|
|
1051
|
+
Bulk update: send update messages to multiple shards (DPA UpdateFunction)
|
|
1052
|
+
Inspired by NSDI'22 Data-Parallel Actors paper
|
|
1053
|
+
"""
|
|
1054
|
+
|
|
1055
|
+
group_id: str = betterproto.string_field(1)
|
|
1056
|
+
"""Group to update"""
|
|
1057
|
+
|
|
1058
|
+
updates: Dict[str, "__common_v1__.Message"] = betterproto.map_field(
|
|
1059
|
+
2, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
|
|
1060
|
+
)
|
|
1061
|
+
"""
|
|
1062
|
+
Update messages: partition_key -> message
|
|
1063
|
+
Messages will be routed to appropriate shards based on partition_key
|
|
1064
|
+
"""
|
|
1065
|
+
|
|
1066
|
+
consistency_level: "ConsistencyLevel" = betterproto.enum_field(3)
|
|
1067
|
+
"""Consistency level for updates"""
|
|
1068
|
+
|
|
1069
|
+
timeout: timedelta = betterproto.message_field(4)
|
|
1070
|
+
"""Timeout for updates"""
|
|
1071
|
+
|
|
1072
|
+
wait_for_responses: bool = betterproto.bool_field(5)
|
|
1073
|
+
"""Wait for responses (true = wait for all, false = fire-and-forget)"""
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
@dataclass(eq=False, repr=False)
|
|
1077
|
+
class BulkUpdateShardGroupResponse(betterproto.Message):
|
|
1078
|
+
updates_sent: int = betterproto.uint32_field(1)
|
|
1079
|
+
"""Number of updates sent"""
|
|
1080
|
+
|
|
1081
|
+
updates_succeeded: int = betterproto.uint32_field(2)
|
|
1082
|
+
"""Number of successful updates"""
|
|
1083
|
+
|
|
1084
|
+
updates_failed: int = betterproto.uint32_field(3)
|
|
1085
|
+
"""Number of failed updates"""
|
|
1086
|
+
|
|
1087
|
+
shard_stats: List["ShardUpdateStats"] = betterproto.message_field(4)
|
|
1088
|
+
"""Per-shard statistics"""
|
|
1089
|
+
|
|
1090
|
+
errors: List[str] = betterproto.string_field(5)
|
|
1091
|
+
"""Errors (if any)"""
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
@dataclass(eq=False, repr=False)
|
|
1095
|
+
class ShardUpdateStats(betterproto.Message):
|
|
1096
|
+
shard_id: int = betterproto.uint32_field(1)
|
|
1097
|
+
shard_actor_id: str = betterproto.string_field(2)
|
|
1098
|
+
updates_sent: int = betterproto.uint32_field(3)
|
|
1099
|
+
updates_succeeded: int = betterproto.uint32_field(4)
|
|
1100
|
+
updates_failed: int = betterproto.uint32_field(5)
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
@dataclass(eq=False, repr=False)
|
|
1104
|
+
class MapShardGroupRequest(betterproto.Message):
|
|
1105
|
+
"""
|
|
1106
|
+
Map: apply function to all shards in parallel (DPA Map operator)
|
|
1107
|
+
Inspired by NSDI'22 Data-Parallel Actors paper
|
|
1108
|
+
"""
|
|
1109
|
+
|
|
1110
|
+
group_id: str = betterproto.string_field(1)
|
|
1111
|
+
"""Group to map over"""
|
|
1112
|
+
|
|
1113
|
+
map_function: "__common_v1__.Message" = betterproto.message_field(2)
|
|
1114
|
+
"""Map function message (sent to each shard)"""
|
|
1115
|
+
|
|
1116
|
+
timeout: timedelta = betterproto.message_field(3)
|
|
1117
|
+
"""Timeout for map operation"""
|
|
1118
|
+
|
|
1119
|
+
min_responses: int = betterproto.uint32_field(4)
|
|
1120
|
+
"""Minimum number of shards that must respond (0 = all required)"""
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
@dataclass(eq=False, repr=False)
|
|
1124
|
+
class MapShardGroupResponse(betterproto.Message):
|
|
1125
|
+
shard_results: List["ShardQueryResponse"] = betterproto.message_field(1)
|
|
1126
|
+
"""Mapped results from each shard"""
|
|
1127
|
+
|
|
1128
|
+
stats: "ScatterGatherStats" = betterproto.message_field(2)
|
|
1129
|
+
"""Statistics"""
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
@dataclass(eq=False, repr=False)
|
|
1133
|
+
class CollectiveTargetField(betterproto.Message):
|
|
1134
|
+
value_path: str = betterproto.string_field(1)
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
@dataclass(eq=False, repr=False)
|
|
1138
|
+
class BroadcastShardGroupRequest(betterproto.Message):
|
|
1139
|
+
group_id: str = betterproto.string_field(1)
|
|
1140
|
+
message: "__common_v1__.Message" = betterproto.message_field(2)
|
|
1141
|
+
timeout: timedelta = betterproto.message_field(3)
|
|
1142
|
+
min_acks: int = betterproto.uint32_field(4)
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
@dataclass(eq=False, repr=False)
|
|
1146
|
+
class BroadcastShardGroupResponse(betterproto.Message):
|
|
1147
|
+
shard_responses: List["ShardQueryResponse"] = betterproto.message_field(1)
|
|
1148
|
+
stats: "ScatterGatherStats" = betterproto.message_field(2)
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
@dataclass(eq=False, repr=False)
|
|
1152
|
+
class ReduceShardGroupRequest(betterproto.Message):
|
|
1153
|
+
group_id: str = betterproto.string_field(1)
|
|
1154
|
+
map_function: "__common_v1__.Message" = betterproto.message_field(2)
|
|
1155
|
+
timeout: timedelta = betterproto.message_field(3)
|
|
1156
|
+
min_responses: int = betterproto.uint32_field(4)
|
|
1157
|
+
reduction: "CollectiveReduction" = betterproto.enum_field(5)
|
|
1158
|
+
target: "CollectiveTargetField" = betterproto.message_field(6)
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
@dataclass(eq=False, repr=False)
|
|
1162
|
+
class ReduceShardGroupResponse(betterproto.Message):
|
|
1163
|
+
result: "__common_v1__.Message" = betterproto.message_field(1)
|
|
1164
|
+
shard_responses: List["ShardQueryResponse"] = betterproto.message_field(2)
|
|
1165
|
+
stats: "ScatterGatherStats" = betterproto.message_field(3)
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
@dataclass(eq=False, repr=False)
|
|
1169
|
+
class AllReduceShardGroupRequest(betterproto.Message):
|
|
1170
|
+
group_id: str = betterproto.string_field(1)
|
|
1171
|
+
map_function: "__common_v1__.Message" = betterproto.message_field(2)
|
|
1172
|
+
timeout: timedelta = betterproto.message_field(3)
|
|
1173
|
+
min_responses: int = betterproto.uint32_field(4)
|
|
1174
|
+
reduction: "CollectiveReduction" = betterproto.enum_field(5)
|
|
1175
|
+
target: "CollectiveTargetField" = betterproto.message_field(6)
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
@dataclass(eq=False, repr=False)
|
|
1179
|
+
class AllReduceShardGroupResponse(betterproto.Message):
|
|
1180
|
+
result: "__common_v1__.Message" = betterproto.message_field(1)
|
|
1181
|
+
shard_responses: List["ShardQueryResponse"] = betterproto.message_field(2)
|
|
1182
|
+
stats: "ScatterGatherStats" = betterproto.message_field(3)
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
@dataclass(eq=False, repr=False)
|
|
1186
|
+
class BarrierShardGroupRequest(betterproto.Message):
|
|
1187
|
+
group_id: str = betterproto.string_field(1)
|
|
1188
|
+
barrier_id: str = betterproto.string_field(2)
|
|
1189
|
+
round: int = betterproto.uint64_field(3)
|
|
1190
|
+
timeout: timedelta = betterproto.message_field(4)
|
|
1191
|
+
min_acks: int = betterproto.uint32_field(5)
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
@dataclass(eq=False, repr=False)
|
|
1195
|
+
class BarrierShardGroupResponse(betterproto.Message):
|
|
1196
|
+
shard_responses: List["ShardQueryResponse"] = betterproto.message_field(1)
|
|
1197
|
+
stats: "ScatterGatherStats" = betterproto.message_field(2)
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
@dataclass(eq=False, repr=False)
|
|
1201
|
+
class ScaleShardGroupRequest(betterproto.Message):
|
|
1202
|
+
"""Scale shard group (add/remove shards with rebalancing)"""
|
|
1203
|
+
|
|
1204
|
+
group_id: str = betterproto.string_field(1)
|
|
1205
|
+
"""Group to scale"""
|
|
1206
|
+
|
|
1207
|
+
new_shard_count: int = betterproto.uint32_field(2)
|
|
1208
|
+
"""New shard count"""
|
|
1209
|
+
|
|
1210
|
+
rebalance_policy: "RebalancePolicy" = betterproto.enum_field(3)
|
|
1211
|
+
"""Rebalancing policy"""
|
|
1212
|
+
|
|
1213
|
+
new_shard_config: "ActorConfig" = betterproto.message_field(4)
|
|
1214
|
+
"""Configuration for new shards (if scaling up)"""
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
@dataclass(eq=False, repr=False)
|
|
1218
|
+
class ScaleShardGroupResponse(betterproto.Message):
|
|
1219
|
+
group: "ShardGroup" = betterproto.message_field(1)
|
|
1220
|
+
"""Updated shard group"""
|
|
1221
|
+
|
|
1222
|
+
rebalance_status: "RebalanceStatus" = betterproto.message_field(2)
|
|
1223
|
+
"""Rebalancing status"""
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
@dataclass(eq=False, repr=False)
|
|
1227
|
+
class ActorMetrics(betterproto.Message):
|
|
1228
|
+
"""Actor performance metrics"""
|
|
1229
|
+
|
|
1230
|
+
messages_processed: int = betterproto.uint64_field(1)
|
|
1231
|
+
messages_failed: int = betterproto.uint64_field(2)
|
|
1232
|
+
average_processing_time: timedelta = betterproto.message_field(3)
|
|
1233
|
+
restarts: int = betterproto.uint64_field(4)
|
|
1234
|
+
last_activity: datetime = betterproto.message_field(5)
|
|
1235
|
+
memory_usage_bytes: int = betterproto.uint64_field(6)
|
|
1236
|
+
cpu_usage_percent: float = betterproto.double_field(7)
|
|
1237
|
+
|
|
1238
|
+
|
|
1239
|
+
@dataclass(eq=False, repr=False)
|
|
1240
|
+
class SpawnActorRequest(betterproto.Message):
|
|
1241
|
+
spec: "ActorSpawnSpec" = betterproto.message_field(1)
|
|
1242
|
+
"""
|
|
1243
|
+
Full spawn contract: identity, role, namespace, tenant_id, behavior_kind, args, facets, labels, config, visibility.
|
|
1244
|
+
"""
|
|
1245
|
+
|
|
1246
|
+
namespace: str = betterproto.string_field(2)
|
|
1247
|
+
"""
|
|
1248
|
+
Optional namespace override for this RPC only.
|
|
1249
|
+
If non-empty, the server merges this into spec.namespace for the spawn operation; if empty, spec.namespace is used.
|
|
1250
|
+
"""
|
|
1251
|
+
|
|
1252
|
+
instances_count: int = betterproto.uint32_field(3)
|
|
1253
|
+
"""
|
|
1254
|
+
Number of identical replicas to spawn (default: 1 when 0).
|
|
1255
|
+
When > 1, spawns N actors with auto-generated instance names derived from spec.identity.name (prefix pattern).
|
|
1256
|
+
"""
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
@dataclass(eq=False, repr=False)
|
|
1260
|
+
class SpawnActorResponse(betterproto.Message):
|
|
1261
|
+
"""
|
|
1262
|
+
Response from SpawnActor
|
|
1263
|
+
|
|
1264
|
+
## Purpose
|
|
1265
|
+
Returns reference to newly spawned actor on the node receiving the request.
|
|
1266
|
+
|
|
1267
|
+
## Design Notes
|
|
1268
|
+
- actor_ref: String in format "actor_id@target_node_id"
|
|
1269
|
+
- Can be used immediately for tell/ask operations
|
|
1270
|
+
- Location transparent - same API as local actors
|
|
1271
|
+
- Example: "actor-abc123@node2"
|
|
1272
|
+
- actor: Full Actor details for inspection
|
|
1273
|
+
- Contains state, config, metrics, etc.
|
|
1274
|
+
- Useful for monitoring and debugging
|
|
1275
|
+
"""
|
|
1276
|
+
|
|
1277
|
+
actor_ref: str = betterproto.string_field(1)
|
|
1278
|
+
"""
|
|
1279
|
+
Reference to spawned actor (format: "actor_id@node_id")
|
|
1280
|
+
Example: "general-1@node2", "worker-abc@prod-7"
|
|
1281
|
+
Use this for messaging: actor_ref.tell(msg), actor_ref.ask(msg)
|
|
1282
|
+
"""
|
|
1283
|
+
|
|
1284
|
+
actor: "Actor" = betterproto.message_field(2)
|
|
1285
|
+
"""
|
|
1286
|
+
Full actor details (state, config, metrics)
|
|
1287
|
+
Useful for inspection and monitoring
|
|
1288
|
+
"""
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
@dataclass(eq=False, repr=False)
|
|
1292
|
+
class SpawnActorsRequest(betterproto.Message):
|
|
1293
|
+
requests: List["SpawnActorRequest"] = betterproto.message_field(1)
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
@dataclass(eq=False, repr=False)
|
|
1297
|
+
class SpawnActorResult(betterproto.Message):
|
|
1298
|
+
success: bool = betterproto.bool_field(1)
|
|
1299
|
+
error: str = betterproto.string_field(2)
|
|
1300
|
+
response: "SpawnActorResponse" = betterproto.message_field(3)
|
|
1301
|
+
|
|
1302
|
+
|
|
1303
|
+
@dataclass(eq=False, repr=False)
|
|
1304
|
+
class SpawnActorsResponse(betterproto.Message):
|
|
1305
|
+
results: List["SpawnActorResult"] = betterproto.message_field(1)
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
@dataclass(eq=False, repr=False)
|
|
1309
|
+
class GetActorRequest(betterproto.Message):
|
|
1310
|
+
"""Request to get an actor"""
|
|
1311
|
+
|
|
1312
|
+
actor_id: str = betterproto.string_field(1)
|
|
1313
|
+
namespace: str = betterproto.string_field(2)
|
|
1314
|
+
"""Namespace for tenant isolation (tenant_id from JWT)"""
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
@dataclass(eq=False, repr=False)
|
|
1318
|
+
class GetActorResponse(betterproto.Message):
|
|
1319
|
+
actor: "Actor" = betterproto.message_field(1)
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
@dataclass(eq=False, repr=False)
|
|
1323
|
+
class ListActorsRequest(betterproto.Message):
|
|
1324
|
+
"""Request to list actors"""
|
|
1325
|
+
|
|
1326
|
+
page_request: "__common_v1__.PageRequest" = betterproto.message_field(1)
|
|
1327
|
+
actor_type: str = betterproto.string_field(2)
|
|
1328
|
+
state: "ActorState" = betterproto.enum_field(3)
|
|
1329
|
+
node_id: str = betterproto.string_field(4)
|
|
1330
|
+
namespace: str = betterproto.string_field(5)
|
|
1331
|
+
"""
|
|
1332
|
+
Namespace for tenant isolation (tenant_id from JWT)
|
|
1333
|
+
Only actors in this namespace will be returned
|
|
1334
|
+
"""
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
@dataclass(eq=False, repr=False)
|
|
1338
|
+
class ListActorsResponse(betterproto.Message):
|
|
1339
|
+
actors: List["Actor"] = betterproto.message_field(1)
|
|
1340
|
+
page_response: "__common_v1__.PageResponse" = betterproto.message_field(2)
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
@dataclass(eq=False, repr=False)
|
|
1344
|
+
class SendMessageRequest(betterproto.Message):
|
|
1345
|
+
"""Request to send a message via tell semantics"""
|
|
1346
|
+
|
|
1347
|
+
namespace: str = betterproto.string_field(1)
|
|
1348
|
+
"""
|
|
1349
|
+
Namespace (extracted from path: /api/v1/actors/{namespace}/{actor_type})
|
|
1350
|
+
"""
|
|
1351
|
+
|
|
1352
|
+
actor_type: str = betterproto.string_field(2)
|
|
1353
|
+
"""
|
|
1354
|
+
Actor type or actor id to target.
|
|
1355
|
+
If this value contains '@', it is treated as a direct actor id first.
|
|
1356
|
+
"""
|
|
1357
|
+
|
|
1358
|
+
http_method: str = betterproto.string_field(3)
|
|
1359
|
+
"""Optional HTTP method metadata for gateway-originated requests."""
|
|
1360
|
+
|
|
1361
|
+
payload: bytes = betterproto.bytes_field(4)
|
|
1362
|
+
"""Request payload bytes."""
|
|
1363
|
+
|
|
1364
|
+
headers: Dict[str, str] = betterproto.map_field(
|
|
1365
|
+
5, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
1366
|
+
)
|
|
1367
|
+
"""Request headers or message metadata."""
|
|
1368
|
+
|
|
1369
|
+
query_params: Dict[str, str] = betterproto.map_field(
|
|
1370
|
+
6, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
1371
|
+
)
|
|
1372
|
+
"""Query parameters from HTTP requests."""
|
|
1373
|
+
|
|
1374
|
+
path: str = betterproto.string_field(7)
|
|
1375
|
+
"""Full request path for gateway-originated requests."""
|
|
1376
|
+
|
|
1377
|
+
subpath: str = betterproto.string_field(8)
|
|
1378
|
+
"""Remaining path segment after actor_type."""
|
|
1379
|
+
|
|
1380
|
+
sender_id: str = betterproto.string_field(9)
|
|
1381
|
+
"""Optional sender actor id for remoting and tracing."""
|
|
1382
|
+
|
|
1383
|
+
message_type: str = betterproto.string_field(10)
|
|
1384
|
+
"""Optional application or transport message type."""
|
|
1385
|
+
|
|
1386
|
+
correlation_id: str = betterproto.string_field(11)
|
|
1387
|
+
"""Optional correlation id preserved for remoting."""
|
|
1388
|
+
|
|
1389
|
+
reply_to: str = betterproto.string_field(12)
|
|
1390
|
+
"""Optional reply_to preserved for remoting."""
|
|
1391
|
+
|
|
1392
|
+
message_id: str = betterproto.string_field(13)
|
|
1393
|
+
"""Optional client-provided message id."""
|
|
1394
|
+
|
|
1395
|
+
actor_name: str = betterproto.string_field(20)
|
|
1396
|
+
"""
|
|
1397
|
+
Optional actor instance name. When set together with actor_type and namespace,
|
|
1398
|
+
the handler constructs the canonical actor ID directly:
|
|
1399
|
+
actor_name//actor_type::namespace@node_id
|
|
1400
|
+
This avoids ambiguous lookups and makes addressing explicit.
|
|
1401
|
+
If empty, falls back to registry lookup by actor_type within the namespace.
|
|
1402
|
+
"""
|
|
1403
|
+
|
|
1404
|
+
|
|
1405
|
+
@dataclass(eq=False, repr=False)
|
|
1406
|
+
class SendMessageResponse(betterproto.Message):
|
|
1407
|
+
success: bool = betterproto.bool_field(1)
|
|
1408
|
+
message_id: str = betterproto.string_field(2)
|
|
1409
|
+
actor_id: str = betterproto.string_field(3)
|
|
1410
|
+
error_message: str = betterproto.string_field(4)
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
@dataclass(eq=False, repr=False)
|
|
1414
|
+
class StreamMessageRequest(betterproto.Message):
|
|
1415
|
+
"""Request for streaming messages (high-throughput)"""
|
|
1416
|
+
|
|
1417
|
+
message: "__common_v1__.Message" = betterproto.message_field(1)
|
|
1418
|
+
sequence: int = betterproto.uint64_field(2)
|
|
1419
|
+
"""Sequence number for ordering (client-generated)"""
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
@dataclass(eq=False, repr=False)
|
|
1423
|
+
class StreamMessageResponse(betterproto.Message):
|
|
1424
|
+
"""Response for streaming messages"""
|
|
1425
|
+
|
|
1426
|
+
message_id: str = betterproto.string_field(1)
|
|
1427
|
+
sequence: int = betterproto.uint64_field(2)
|
|
1428
|
+
"""Acknowledgement of sequence number"""
|
|
1429
|
+
|
|
1430
|
+
status: str = betterproto.string_field(3)
|
|
1431
|
+
"""Status: "delivered", "failed", "queued"""
|
|
1432
|
+
|
|
1433
|
+
error: str = betterproto.string_field(4)
|
|
1434
|
+
"""Optional error message"""
|
|
1435
|
+
|
|
1436
|
+
|
|
1437
|
+
@dataclass(eq=False, repr=False)
|
|
1438
|
+
class DeleteActorRequest(betterproto.Message):
|
|
1439
|
+
"""Request to delete actor"""
|
|
1440
|
+
|
|
1441
|
+
actor_id: str = betterproto.string_field(1)
|
|
1442
|
+
force: bool = betterproto.bool_field(2)
|
|
1443
|
+
namespace: str = betterproto.string_field(3)
|
|
1444
|
+
"""Namespace for tenant isolation (tenant_id from JWT)"""
|
|
1445
|
+
|
|
1446
|
+
|
|
1447
|
+
@dataclass(eq=False, repr=False)
|
|
1448
|
+
class ActorLifecycleEvent(betterproto.Message):
|
|
1449
|
+
"""
|
|
1450
|
+
Actor lifecycle event
|
|
1451
|
+
|
|
1452
|
+
## Purpose
|
|
1453
|
+
Represents a state transition in an actor's lifecycle. Used for monitoring,
|
|
1454
|
+
observability, and triggering supervision actions.
|
|
1455
|
+
|
|
1456
|
+
## Architecture Context
|
|
1457
|
+
- Emitted by Actor implementation when state changes occur
|
|
1458
|
+
- Consumed by Node for monitoring callbacks
|
|
1459
|
+
- Consumed by observability systems (metrics, tracing, logging)
|
|
1460
|
+
- Enables location-transparent monitoring (Erlang-style)
|
|
1461
|
+
|
|
1462
|
+
## Design Decisions
|
|
1463
|
+
- Proto-based for distributed type safety across nodes
|
|
1464
|
+
- event_type as oneof for type-safe event variants
|
|
1465
|
+
- Timestamp for event ordering and time-travel debugging
|
|
1466
|
+
- Extensible for future event types without breaking changes
|
|
1467
|
+
|
|
1468
|
+
## Usage
|
|
1469
|
+
```rust
|
|
1470
|
+
// Actor emits event
|
|
1471
|
+
let event = ActorLifecycleEvent {
|
|
1472
|
+
actor_id: "worker@node1".to_string(),
|
|
1473
|
+
timestamp: Some(Timestamp::now()),
|
|
1474
|
+
event_type: Some(actor_lifecycle_event::EventType::Terminated(
|
|
1475
|
+
ActorTerminated { reason: "normal".to_string() }
|
|
1476
|
+
)),
|
|
1477
|
+
};
|
|
1478
|
+
node.handle_lifecycle_event(event).await?;
|
|
1479
|
+
```
|
|
1480
|
+
"""
|
|
1481
|
+
|
|
1482
|
+
actor_id: str = betterproto.string_field(1)
|
|
1483
|
+
"""Actor that emitted this event"""
|
|
1484
|
+
|
|
1485
|
+
timestamp: datetime = betterproto.message_field(2)
|
|
1486
|
+
"""When event occurred"""
|
|
1487
|
+
|
|
1488
|
+
created: "ActorCreated" = betterproto.message_field(10, group="event_type")
|
|
1489
|
+
starting: "ActorStarting" = betterproto.message_field(11, group="event_type")
|
|
1490
|
+
activated: "ActorActivated" = betterproto.message_field(12, group="event_type")
|
|
1491
|
+
deactivating: "ActorDeactivating" = betterproto.message_field(
|
|
1492
|
+
13, group="event_type"
|
|
1493
|
+
)
|
|
1494
|
+
deactivated: "ActorDeactivated" = betterproto.message_field(14, group="event_type")
|
|
1495
|
+
terminated: "ActorTerminated" = betterproto.message_field(15, group="event_type")
|
|
1496
|
+
failed: "ActorFailed" = betterproto.message_field(16, group="event_type")
|
|
1497
|
+
migrating: "ActorMigrating" = betterproto.message_field(17, group="event_type")
|
|
1498
|
+
|
|
1499
|
+
|
|
1500
|
+
@dataclass(eq=False, repr=False)
|
|
1501
|
+
class ActorCreated(betterproto.Message):
|
|
1502
|
+
"""
|
|
1503
|
+
Actor created (construction complete, not yet started)
|
|
1504
|
+
|
|
1505
|
+
## Purpose
|
|
1506
|
+
Emitted after Actor::new() completes successfully.
|
|
1507
|
+
|
|
1508
|
+
## State Transition
|
|
1509
|
+
[none] -> Created
|
|
1510
|
+
|
|
1511
|
+
## Supervisor Action
|
|
1512
|
+
None (waiting for activation)
|
|
1513
|
+
"""
|
|
1514
|
+
|
|
1515
|
+
pass
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
@dataclass(eq=False, repr=False)
|
|
1519
|
+
class ActorStarting(betterproto.Message):
|
|
1520
|
+
"""
|
|
1521
|
+
Actor starting (spawning message processing task)
|
|
1522
|
+
|
|
1523
|
+
## Purpose
|
|
1524
|
+
Emitted when Actor::start() is called, before tokio::spawn().
|
|
1525
|
+
|
|
1526
|
+
## State Transition
|
|
1527
|
+
Created -> Starting
|
|
1528
|
+
|
|
1529
|
+
## Supervisor Action
|
|
1530
|
+
None (normal startup)
|
|
1531
|
+
"""
|
|
1532
|
+
|
|
1533
|
+
pass
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
@dataclass(eq=False, repr=False)
|
|
1537
|
+
class ActorActivated(betterproto.Message):
|
|
1538
|
+
"""
|
|
1539
|
+
Actor activated (ready to process messages)
|
|
1540
|
+
|
|
1541
|
+
## Purpose
|
|
1542
|
+
Emitted after actor's message loop starts and on_activate() hook completes.
|
|
1543
|
+
|
|
1544
|
+
## State Transition
|
|
1545
|
+
Starting -> Activated
|
|
1546
|
+
|
|
1547
|
+
## Supervisor Action
|
|
1548
|
+
None (actor running normally)
|
|
1549
|
+
"""
|
|
1550
|
+
|
|
1551
|
+
pass
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
@dataclass(eq=False, repr=False)
|
|
1555
|
+
class ActorDeactivating(betterproto.Message):
|
|
1556
|
+
"""
|
|
1557
|
+
Actor deactivating (graceful shutdown initiated)
|
|
1558
|
+
|
|
1559
|
+
## Purpose
|
|
1560
|
+
Emitted when actor receives shutdown signal or supervisor requests stop.
|
|
1561
|
+
|
|
1562
|
+
## State Transition
|
|
1563
|
+
Activated -> Deactivating
|
|
1564
|
+
|
|
1565
|
+
## Supervisor Action
|
|
1566
|
+
None (expected shutdown)
|
|
1567
|
+
"""
|
|
1568
|
+
|
|
1569
|
+
reason: str = betterproto.string_field(1)
|
|
1570
|
+
"""
|
|
1571
|
+
Why deactivation was initiated
|
|
1572
|
+
Examples: "supervisor_shutdown", "manual_stop", "timeout_idle"
|
|
1573
|
+
"""
|
|
1574
|
+
|
|
1575
|
+
|
|
1576
|
+
@dataclass(eq=False, repr=False)
|
|
1577
|
+
class ActorDeactivated(betterproto.Message):
|
|
1578
|
+
"""
|
|
1579
|
+
Actor deactivated (shutdown complete, but not destroyed)
|
|
1580
|
+
|
|
1581
|
+
## Purpose
|
|
1582
|
+
Emitted after on_deactivate() hook completes. Actor can be reactivated.
|
|
1583
|
+
|
|
1584
|
+
## State Transition
|
|
1585
|
+
Deactivating -> Deactivated
|
|
1586
|
+
|
|
1587
|
+
## Supervisor Action
|
|
1588
|
+
None (actor cleanly stopped, can be restarted if needed)
|
|
1589
|
+
"""
|
|
1590
|
+
|
|
1591
|
+
reason: str = betterproto.string_field(1)
|
|
1592
|
+
"""Why deactivation occurred"""
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
@dataclass(eq=False, repr=False)
|
|
1596
|
+
class ActorTerminated(betterproto.Message):
|
|
1597
|
+
"""
|
|
1598
|
+
Actor terminated (permanently stopped, not restartable)
|
|
1599
|
+
|
|
1600
|
+
## Purpose
|
|
1601
|
+
Emitted when actor's task completes normally (loop exits without error).
|
|
1602
|
+
Triggers monitoring callbacks (NotifyActorDown).
|
|
1603
|
+
|
|
1604
|
+
## State Transition
|
|
1605
|
+
Activated|Deactivating -> Terminated
|
|
1606
|
+
|
|
1607
|
+
## Supervisor Action
|
|
1608
|
+
- If restart strategy allows, restart actor
|
|
1609
|
+
- Notify all monitors (local + remote via NotifyActorDown RPC)
|
|
1610
|
+
|
|
1611
|
+
## Design Notes
|
|
1612
|
+
- reason="normal": Graceful shutdown completed
|
|
1613
|
+
- reason="shutdown": Supervisor-initiated shutdown
|
|
1614
|
+
- reason="killed": Forcefully terminated
|
|
1615
|
+
"""
|
|
1616
|
+
|
|
1617
|
+
reason: str = betterproto.string_field(1)
|
|
1618
|
+
"""
|
|
1619
|
+
Termination reason
|
|
1620
|
+
"normal": Graceful shutdown
|
|
1621
|
+
"shutdown": Supervisor-initiated
|
|
1622
|
+
"killed": Forcefully terminated
|
|
1623
|
+
"""
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
@dataclass(eq=False, repr=False)
|
|
1627
|
+
class ActorFailed(betterproto.Message):
|
|
1628
|
+
"""
|
|
1629
|
+
Actor failed (crashed, needs supervision action)
|
|
1630
|
+
|
|
1631
|
+
## Purpose
|
|
1632
|
+
Emitted when actor's task panics or returns error. Triggers supervision
|
|
1633
|
+
restart logic and monitoring callbacks.
|
|
1634
|
+
|
|
1635
|
+
## State Transition
|
|
1636
|
+
Activated -> Failed
|
|
1637
|
+
|
|
1638
|
+
## Supervisor Action
|
|
1639
|
+
- Apply restart strategy (OneForOne, OneForAll, RestForOne)
|
|
1640
|
+
- Notify all monitors with error details
|
|
1641
|
+
- Increment failure counter for escalation
|
|
1642
|
+
|
|
1643
|
+
## Design Notes
|
|
1644
|
+
- error: Full panic/error message for debugging
|
|
1645
|
+
- Supervision tree decides whether to restart based on restart strategy
|
|
1646
|
+
"""
|
|
1647
|
+
|
|
1648
|
+
error: str = betterproto.string_field(1)
|
|
1649
|
+
"""
|
|
1650
|
+
Error/panic message
|
|
1651
|
+
Examples:
|
|
1652
|
+
- "panic: index out of bounds"
|
|
1653
|
+
- "error: timeout waiting for response"
|
|
1654
|
+
- "error: connection refused"
|
|
1655
|
+
"""
|
|
1656
|
+
|
|
1657
|
+
stack_trace: str = betterproto.string_field(2)
|
|
1658
|
+
"""Optional: Stack trace for debugging"""
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
@dataclass(eq=False, repr=False)
|
|
1662
|
+
class ActorMigrating(betterproto.Message):
|
|
1663
|
+
"""
|
|
1664
|
+
Actor migrating (moving to different node)
|
|
1665
|
+
|
|
1666
|
+
## Purpose
|
|
1667
|
+
Emitted when mobile agent starts migration to another node.
|
|
1668
|
+
|
|
1669
|
+
## State Transition
|
|
1670
|
+
Activated -> Migrating
|
|
1671
|
+
|
|
1672
|
+
## Supervisor Action
|
|
1673
|
+
- Update actor location in registry
|
|
1674
|
+
- If migration fails, restart on original node
|
|
1675
|
+
|
|
1676
|
+
## Design Notes
|
|
1677
|
+
- target_node: Destination node address (e.g., "node2")
|
|
1678
|
+
- Future: Add migration_id for tracking migration progress
|
|
1679
|
+
"""
|
|
1680
|
+
|
|
1681
|
+
target_node: str = betterproto.string_field(1)
|
|
1682
|
+
"""Target node where actor is migrating"""
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
@dataclass(eq=False, repr=False)
|
|
1686
|
+
class MonitorActorRequest(betterproto.Message):
|
|
1687
|
+
"""
|
|
1688
|
+
Request to monitor an actor (Erlang-style)
|
|
1689
|
+
|
|
1690
|
+
## Purpose
|
|
1691
|
+
Establishes a monitor from `supervisor_id` to `actor_id` on the **node that hosts
|
|
1692
|
+
`actor_id`**. When that actor terminates, that node runs termination handling and
|
|
1693
|
+
delivers a `__DOWN__` **mailbox message** to `supervisor_id` (same Erlang semantics
|
|
1694
|
+
as `{'DOWN', Ref, process, Pid, Reason}`), routing remotely via `ActorService` when
|
|
1695
|
+
the supervisor lives on another node.
|
|
1696
|
+
|
|
1697
|
+
## Erlang Philosophy
|
|
1698
|
+
Equivalent to: Ref = erlang:monitor(process, Pid)
|
|
1699
|
+
Works the same for local and remote processes (location transparent).
|
|
1700
|
+
|
|
1701
|
+
## Design Notes
|
|
1702
|
+
- actor_id: Canonical actor ID for the actor to monitor
|
|
1703
|
+
- supervisor_id: Canonical actor ID of the process that receives `__DOWN__` in its mailbox
|
|
1704
|
+
- supervisor_callback: **Reserved / wire compatibility.** The Rust server implementation
|
|
1705
|
+
does not use this field today; DOWN is sent with `ActorRegistry::tell` to `supervisor_id`.
|
|
1706
|
+
Clients should still populate it per validation (e.g. supervisor node's ActorService URL)
|
|
1707
|
+
for forward compatibility with a possible push-style callback path.
|
|
1708
|
+
"""
|
|
1709
|
+
|
|
1710
|
+
actor_id: str = betterproto.string_field(1)
|
|
1711
|
+
supervisor_id: str = betterproto.string_field(2)
|
|
1712
|
+
supervisor_callback: str = betterproto.string_field(3)
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
@dataclass(eq=False, repr=False)
|
|
1716
|
+
class MonitorActorResponse(betterproto.Message):
|
|
1717
|
+
"""
|
|
1718
|
+
Response to MonitorActor request
|
|
1719
|
+
|
|
1720
|
+
## Purpose
|
|
1721
|
+
Returns a monitor reference that can be used to demonitor in future.
|
|
1722
|
+
|
|
1723
|
+
## Erlang Philosophy
|
|
1724
|
+
Equivalent to the Ref returned by erlang:monitor(process, Pid).
|
|
1725
|
+
|
|
1726
|
+
## Design Notes
|
|
1727
|
+
- monitor_ref: Unique ID for this monitoring link (ULID)
|
|
1728
|
+
- Can be used for future demonitor() operation
|
|
1729
|
+
"""
|
|
1730
|
+
|
|
1731
|
+
monitor_ref: str = betterproto.string_field(1)
|
|
1732
|
+
|
|
1733
|
+
|
|
1734
|
+
@dataclass(eq=False, repr=False)
|
|
1735
|
+
class DemonitorActorRequest(betterproto.Message):
|
|
1736
|
+
"""
|
|
1737
|
+
Request to remove a monitor (Erlang demonitor/1 equivalent)
|
|
1738
|
+
|
|
1739
|
+
## Purpose
|
|
1740
|
+
Cancels a monitor previously established via MonitorActor on the node that hosts
|
|
1741
|
+
the **monitored** actor (`actor_id`). The caller must supply the same `monitor_ref`
|
|
1742
|
+
returned by MonitorActor.
|
|
1743
|
+
"""
|
|
1744
|
+
|
|
1745
|
+
actor_id: str = betterproto.string_field(1)
|
|
1746
|
+
supervisor_id: str = betterproto.string_field(2)
|
|
1747
|
+
monitor_ref: str = betterproto.string_field(3)
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
@dataclass(eq=False, repr=False)
|
|
1751
|
+
class ActorDownNotification(betterproto.Message):
|
|
1752
|
+
"""
|
|
1753
|
+
Notification that a monitored actor has terminated
|
|
1754
|
+
|
|
1755
|
+
## Purpose
|
|
1756
|
+
Sent by the node hosting the actor to the supervisor when actor terminates.
|
|
1757
|
+
This is an internal message, not typically sent by user code.
|
|
1758
|
+
|
|
1759
|
+
## Erlang Philosophy
|
|
1760
|
+
Equivalent to receiving: {'DOWN', Ref, process, Pid, Reason}
|
|
1761
|
+
Supervisor receives this asynchronously when monitored actor exits.
|
|
1762
|
+
|
|
1763
|
+
## Design Notes
|
|
1764
|
+
- actor_id: The actor that terminated
|
|
1765
|
+
- supervisor_id: The supervisor that was monitoring (for routing)
|
|
1766
|
+
- reason: Why actor terminated:
|
|
1767
|
+
- "normal": Graceful shutdown
|
|
1768
|
+
- "shutdown": Supervisor-initiated shutdown
|
|
1769
|
+
- "killed": Forcefully terminated
|
|
1770
|
+
- Error message: Crash reason (e.g., "panic: index out of bounds")
|
|
1771
|
+
"""
|
|
1772
|
+
|
|
1773
|
+
actor_id: str = betterproto.string_field(1)
|
|
1774
|
+
supervisor_id: str = betterproto.string_field(2)
|
|
1775
|
+
reason: str = betterproto.string_field(3)
|
|
1776
|
+
monitor_ref: str = betterproto.string_field(4)
|
|
1777
|
+
"""
|
|
1778
|
+
Monitor reference ULID correlating with the original monitor() call.
|
|
1779
|
+
Allows the monitoring actor to identify which monitor fired when monitoring multiple actors.
|
|
1780
|
+
"""
|
|
1781
|
+
|
|
1782
|
+
is_link_signal: bool = betterproto.bool_field(5)
|
|
1783
|
+
"""
|
|
1784
|
+
When true, this notification is a Link EXIT signal (bidirectional death propagation).
|
|
1785
|
+
The receiving node should kill the supervisor_id actor with a Linked exit reason.
|
|
1786
|
+
When false (default), this is a Monitor DOWN notification delivered to the mailbox.
|
|
1787
|
+
"""
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
@dataclass(eq=False, repr=False)
|
|
1791
|
+
class GetActorStatesRequest(betterproto.Message):
|
|
1792
|
+
"""
|
|
1793
|
+
Request to batch-check actor states — used by stale-monitor GC task
|
|
1794
|
+
|
|
1795
|
+
## Purpose
|
|
1796
|
+
Efficiently checks the lifecycle state of multiple actors in a single RPC call.
|
|
1797
|
+
Used by the background monitor GC task to detect stale monitor entries for actors
|
|
1798
|
+
that no longer exist on their hosting node.
|
|
1799
|
+
"""
|
|
1800
|
+
|
|
1801
|
+
actor_ids: List[str] = betterproto.string_field(1)
|
|
1802
|
+
"""List of canonical actor IDs to check"""
|
|
1803
|
+
|
|
1804
|
+
|
|
1805
|
+
@dataclass(eq=False, repr=False)
|
|
1806
|
+
class GetActorStatesResponse(betterproto.Message):
|
|
1807
|
+
"""Response for batch actor state check — uses existing ActorState enum"""
|
|
1808
|
+
|
|
1809
|
+
states: Dict[str, "ActorState"] = betterproto.map_field(
|
|
1810
|
+
1, betterproto.TYPE_STRING, betterproto.TYPE_ENUM
|
|
1811
|
+
)
|
|
1812
|
+
"""
|
|
1813
|
+
Map of canonical actor_id -> ActorState (uses existing ActorState enum)
|
|
1814
|
+
ACTOR_STATE_UNSPECIFIED / ACTOR_STATE_TERMINATED / not present = actor not found on this node
|
|
1815
|
+
"""
|
|
1816
|
+
|
|
1817
|
+
|
|
1818
|
+
@dataclass(eq=False, repr=False)
|
|
1819
|
+
class ActorLink(betterproto.Message):
|
|
1820
|
+
"""
|
|
1821
|
+
/ Actor link for two-way death propagation
|
|
1822
|
+
/
|
|
1823
|
+
/ ## Purpose
|
|
1824
|
+
/ Represents a link between two actors. When one actor dies, the linked actor
|
|
1825
|
+
/ automatically dies (cascading failure). This is the foundation for supervision trees.
|
|
1826
|
+
/
|
|
1827
|
+
/ ## Erlang Philosophy
|
|
1828
|
+
/ Equivalent to Erlang's `link/1` - creates a bidirectional link between processes.
|
|
1829
|
+
/ If either process dies abnormally, the other dies too.
|
|
1830
|
+
/
|
|
1831
|
+
/ ## Design Notes
|
|
1832
|
+
/ - Links are bidirectional (if A links to B, B is linked to A)
|
|
1833
|
+
/ - Links propagate death (if A dies, B dies; if B dies, A dies)
|
|
1834
|
+
/ - Links are used internally by supervision (parent-child relationships)
|
|
1835
|
+
/ - Links can also be created explicitly via API
|
|
1836
|
+
/
|
|
1837
|
+
/ ## Example
|
|
1838
|
+
/ ```rust
|
|
1839
|
+
/ // Link two actors
|
|
1840
|
+
/ node.link("actor-1", "actor-2").await?;
|
|
1841
|
+
/
|
|
1842
|
+
/ // If actor-1 dies abnormally, actor-2 automatically dies
|
|
1843
|
+
/ // If actor-2 dies abnormally, actor-1 automatically dies
|
|
1844
|
+
/ ```
|
|
1845
|
+
"""
|
|
1846
|
+
|
|
1847
|
+
actor_id: str = betterproto.string_field(1)
|
|
1848
|
+
"""/ First actor in the link"""
|
|
1849
|
+
|
|
1850
|
+
linked_actor_id: str = betterproto.string_field(2)
|
|
1851
|
+
"""/ Second actor in the link (bidirectional)"""
|
|
1852
|
+
|
|
1853
|
+
created_at: datetime = betterproto.message_field(3)
|
|
1854
|
+
"""/ Link creation timestamp (for observability)"""
|
|
1855
|
+
|
|
1856
|
+
metadata: Dict[str, str] = betterproto.map_field(
|
|
1857
|
+
4, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
1858
|
+
)
|
|
1859
|
+
"""/ Metadata (optional, for debugging)"""
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
@dataclass(eq=False, repr=False)
|
|
1863
|
+
class LinkActorRequest(betterproto.Message):
|
|
1864
|
+
"""
|
|
1865
|
+
/ Link two actors (Erlang link/1 equivalent)
|
|
1866
|
+
/
|
|
1867
|
+
/ ## Purpose
|
|
1868
|
+
/ Creates a bidirectional link between two actors. When one actor dies abnormally,
|
|
1869
|
+
/ the linked actor automatically dies (cascading failure).
|
|
1870
|
+
/
|
|
1871
|
+
/ ## Erlang Philosophy
|
|
1872
|
+
/ Equivalent to Erlang's `link(Pid)` - creates bidirectional link.
|
|
1873
|
+
/ If either process dies abnormally, the other dies too.
|
|
1874
|
+
/
|
|
1875
|
+
/ ## Design Notes
|
|
1876
|
+
/ - Links are bidirectional (if A links to B, B is linked to A)
|
|
1877
|
+
/ - Links only propagate abnormal deaths (not "normal" shutdowns)
|
|
1878
|
+
/ - Links are used internally by supervision (parent-child relationships)
|
|
1879
|
+
/ - Links can be created explicitly via this API
|
|
1880
|
+
/
|
|
1881
|
+
/ ## Example
|
|
1882
|
+
/ ```rust
|
|
1883
|
+
/ // Link two actors
|
|
1884
|
+
/ node.link("actor-1", "actor-2").await?;
|
|
1885
|
+
/
|
|
1886
|
+
/ // If actor-1 dies abnormally, actor-2 automatically dies
|
|
1887
|
+
/ // If actor-2 dies abnormally, actor-1 automatically dies
|
|
1888
|
+
/ ```
|
|
1889
|
+
"""
|
|
1890
|
+
|
|
1891
|
+
actor_id: str = betterproto.string_field(1)
|
|
1892
|
+
linked_actor_id: str = betterproto.string_field(2)
|
|
1893
|
+
|
|
1894
|
+
|
|
1895
|
+
@dataclass(eq=False, repr=False)
|
|
1896
|
+
class LinkActorResponse(betterproto.Message):
|
|
1897
|
+
"""/ Response to LinkActor request"""
|
|
1898
|
+
|
|
1899
|
+
success: bool = betterproto.bool_field(1)
|
|
1900
|
+
|
|
1901
|
+
|
|
1902
|
+
@dataclass(eq=False, repr=False)
|
|
1903
|
+
class UnlinkActorRequest(betterproto.Message):
|
|
1904
|
+
"""
|
|
1905
|
+
/ Unlink two actors (Erlang unlink/1 equivalent)
|
|
1906
|
+
/
|
|
1907
|
+
/ ## Purpose
|
|
1908
|
+
/ Removes the bidirectional link between two actors. After unlinking,
|
|
1909
|
+
/ actors can die independently without cascading failures.
|
|
1910
|
+
/
|
|
1911
|
+
/ ## Erlang Philosophy
|
|
1912
|
+
/ Equivalent to Erlang's `unlink(Pid)` - removes bidirectional link.
|
|
1913
|
+
"""
|
|
1914
|
+
|
|
1915
|
+
actor_id: str = betterproto.string_field(1)
|
|
1916
|
+
linked_actor_id: str = betterproto.string_field(2)
|
|
1917
|
+
|
|
1918
|
+
|
|
1919
|
+
@dataclass(eq=False, repr=False)
|
|
1920
|
+
class UnlinkActorResponse(betterproto.Message):
|
|
1921
|
+
"""/ Response to UnlinkActor request"""
|
|
1922
|
+
|
|
1923
|
+
success: bool = betterproto.bool_field(1)
|
|
1924
|
+
|
|
1925
|
+
|
|
1926
|
+
@dataclass(eq=False, repr=False)
|
|
1927
|
+
class CheckActorExistsRequest(betterproto.Message):
|
|
1928
|
+
"""Request to check if actor exists"""
|
|
1929
|
+
|
|
1930
|
+
actor_id: str = betterproto.string_field(1)
|
|
1931
|
+
"""Actor ID to check"""
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
@dataclass(eq=False, repr=False)
|
|
1935
|
+
class CheckActorExistsResponse(betterproto.Message):
|
|
1936
|
+
"""Response to check actor exists request"""
|
|
1937
|
+
|
|
1938
|
+
exists: bool = betterproto.bool_field(1)
|
|
1939
|
+
"""Actor exists (virtual or active)"""
|
|
1940
|
+
|
|
1941
|
+
is_active: bool = betterproto.bool_field(2)
|
|
1942
|
+
"""Actor is currently active (in memory)"""
|
|
1943
|
+
|
|
1944
|
+
is_virtual: bool = betterproto.bool_field(3)
|
|
1945
|
+
"""Actor has VirtualActorFacet (is virtual)"""
|
|
1946
|
+
|
|
1947
|
+
|
|
1948
|
+
@dataclass(eq=False, repr=False)
|
|
1949
|
+
class AskReplyRequest(betterproto.Message):
|
|
1950
|
+
"""
|
|
1951
|
+
Request to ask an actor via HTTP-like interface (FaaS-style)
|
|
1952
|
+
|
|
1953
|
+
## Purpose
|
|
1954
|
+
Enables ask-style requests to actors via HTTP GET/POST/PUT routes.
|
|
1955
|
+
The tenant_id, namespace, and actor_type are extracted from the HTTP path.
|
|
1956
|
+
|
|
1957
|
+
## HTTP Method Handling
|
|
1958
|
+
- GET: Query parameters are converted to JSON and stored in payload as string
|
|
1959
|
+
- POST: Request body becomes payload, HTTP headers become headers map
|
|
1960
|
+
"""
|
|
1961
|
+
|
|
1962
|
+
namespace: str = betterproto.string_field(1)
|
|
1963
|
+
"""
|
|
1964
|
+
Namespace (extracted from path: /api/v1/actors/{namespace}/{actor_type})
|
|
1965
|
+
Can be empty - defaults to empty string if not provided
|
|
1966
|
+
Tenant ID comes from gRPC auth (JWT middleware) or default config, not from request
|
|
1967
|
+
"""
|
|
1968
|
+
|
|
1969
|
+
actor_type: str = betterproto.string_field(2)
|
|
1970
|
+
"""
|
|
1971
|
+
Actor type (extracted from path: /api/v1/actors/{namespace}/{actor_type})
|
|
1972
|
+
Used to lookup actors via ActorRegistry discover_actors_by_type
|
|
1973
|
+
"""
|
|
1974
|
+
|
|
1975
|
+
http_method: str = betterproto.string_field(3)
|
|
1976
|
+
"""HTTP method metadata (GET, POST, or PUT)"""
|
|
1977
|
+
|
|
1978
|
+
payload: bytes = betterproto.bytes_field(4)
|
|
1979
|
+
"""
|
|
1980
|
+
Request payload
|
|
1981
|
+
For GET: JSON string of query parameters
|
|
1982
|
+
For POST/PUT: Request body bytes
|
|
1983
|
+
"""
|
|
1984
|
+
|
|
1985
|
+
headers: Dict[str, str] = betterproto.map_field(
|
|
1986
|
+
5, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
1987
|
+
)
|
|
1988
|
+
"""
|
|
1989
|
+
HTTP headers
|
|
1990
|
+
Converted from HTTP request headers
|
|
1991
|
+
"""
|
|
1992
|
+
|
|
1993
|
+
query_params: Dict[str, str] = betterproto.map_field(
|
|
1994
|
+
6, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
1995
|
+
)
|
|
1996
|
+
"""
|
|
1997
|
+
Query parameters (for GET requests)
|
|
1998
|
+
Converted to JSON and stored in payload
|
|
1999
|
+
"""
|
|
2000
|
+
|
|
2001
|
+
path: str = betterproto.string_field(7)
|
|
2002
|
+
"""
|
|
2003
|
+
Full HTTP path for the request (optional)
|
|
2004
|
+
Example: "/api/v1/actors/default/counter/custom/path"
|
|
2005
|
+
Allows actors to perform custom routing based on the complete URL
|
|
2006
|
+
"""
|
|
2007
|
+
|
|
2008
|
+
subpath: str = betterproto.string_field(8)
|
|
2009
|
+
"""
|
|
2010
|
+
Subpath after the actor_type segment (optional)
|
|
2011
|
+
Example: for "/api/v1/actors/default/counter/metrics/latest"
|
|
2012
|
+
subpath = "metrics/latest"
|
|
2013
|
+
This will be used in future for advanced per-actor routing capabilities.
|
|
2014
|
+
"""
|
|
2015
|
+
|
|
2016
|
+
sender_id: str = betterproto.string_field(9)
|
|
2017
|
+
"""Optional sender actor id for remoting and tracing."""
|
|
2018
|
+
|
|
2019
|
+
message_type: str = betterproto.string_field(10)
|
|
2020
|
+
"""Optional transport message type."""
|
|
2021
|
+
|
|
2022
|
+
correlation_id: str = betterproto.string_field(11)
|
|
2023
|
+
"""Optional correlation id preserved for remoting."""
|
|
2024
|
+
|
|
2025
|
+
reply_to: str = betterproto.string_field(12)
|
|
2026
|
+
"""Optional reply_to preserved for remoting."""
|
|
2027
|
+
|
|
2028
|
+
message_id: str = betterproto.string_field(13)
|
|
2029
|
+
"""Optional client-provided message id."""
|
|
2030
|
+
|
|
2031
|
+
timeout: timedelta = betterproto.message_field(14)
|
|
2032
|
+
"""
|
|
2033
|
+
Optional timeout for request-reply (ask) operations.
|
|
2034
|
+
Defaults to 5 seconds if not specified. Use for long-running operations like training.
|
|
2035
|
+
HTTP gateway extracts from ?timeout=30 query parameter (in seconds).
|
|
2036
|
+
"""
|
|
2037
|
+
|
|
2038
|
+
actor_name: str = betterproto.string_field(20)
|
|
2039
|
+
"""
|
|
2040
|
+
Optional actor instance name. When set together with actor_type and namespace,
|
|
2041
|
+
the handler constructs the canonical actor ID directly:
|
|
2042
|
+
actor_name//actor_type::namespace@node_id
|
|
2043
|
+
If empty, falls back to registry lookup by actor_type within the namespace.
|
|
2044
|
+
"""
|
|
2045
|
+
|
|
2046
|
+
|
|
2047
|
+
@dataclass(eq=False, repr=False)
|
|
2048
|
+
class AskReplyResponse(betterproto.Message):
|
|
2049
|
+
"""
|
|
2050
|
+
Response from asking an actor
|
|
2051
|
+
|
|
2052
|
+
## Purpose
|
|
2053
|
+
Returns the result of an actor ask request.
|
|
2054
|
+
"""
|
|
2055
|
+
|
|
2056
|
+
success: bool = betterproto.bool_field(1)
|
|
2057
|
+
"""Success status"""
|
|
2058
|
+
|
|
2059
|
+
payload: bytes = betterproto.bytes_field(2)
|
|
2060
|
+
"""
|
|
2061
|
+
Response payload (for GET/ask requests)
|
|
2062
|
+
Contains the reply message from actor
|
|
2063
|
+
"""
|
|
2064
|
+
|
|
2065
|
+
headers: Dict[str, str] = betterproto.map_field(
|
|
2066
|
+
3, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
2067
|
+
)
|
|
2068
|
+
"""Response headers (optional metadata)"""
|
|
2069
|
+
|
|
2070
|
+
actor_id: str = betterproto.string_field(4)
|
|
2071
|
+
"""Actor ID that was invoked (format: "actor_id@node_id")"""
|
|
2072
|
+
|
|
2073
|
+
error_message: str = betterproto.string_field(5)
|
|
2074
|
+
"""Error message (if success is false)"""
|
|
2075
|
+
|
|
2076
|
+
|
|
2077
|
+
@dataclass(eq=False, repr=False)
|
|
2078
|
+
class LifecycleEventFilter(betterproto.Message):
|
|
2079
|
+
"""
|
|
2080
|
+
Lifecycle event filter for subscribers
|
|
2081
|
+
|
|
2082
|
+
## Purpose
|
|
2083
|
+
Defines what events a subscriber wants to receive. Supports filtering by:
|
|
2084
|
+
- Event types (Created, Terminated, Failed, etc.)
|
|
2085
|
+
- Actor ID patterns (regex)
|
|
2086
|
+
- Node ID patterns (regex)
|
|
2087
|
+
- Custom tags
|
|
2088
|
+
|
|
2089
|
+
## Examples
|
|
2090
|
+
```
|
|
2091
|
+
// Prometheus exporter - only care about actor spawn/terminate for counts
|
|
2092
|
+
EventFilter {
|
|
2093
|
+
event_types: [ACTOR_CREATED, ACTOR_TERMINATED, ACTOR_FAILED]
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
// Tracing system - want all events for specific actor group
|
|
2097
|
+
EventFilter {
|
|
2098
|
+
actor_id_pattern: "worker-.*@node1"
|
|
2099
|
+
event_types: [ACTOR_ACTIVATED, ACTOR_DEACTIVATED]
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
// Monitoring dashboard - all critical events across cluster
|
|
2103
|
+
EventFilter {
|
|
2104
|
+
event_types: [ACTOR_FAILED, ACTOR_MIGRATING]
|
|
2105
|
+
}
|
|
2106
|
+
```
|
|
2107
|
+
"""
|
|
2108
|
+
|
|
2109
|
+
subscription_id: str = betterproto.string_field(1)
|
|
2110
|
+
"""
|
|
2111
|
+
Subscription ID (ULID, generated by subscriber)
|
|
2112
|
+
Used for unsubscribe and tracking
|
|
2113
|
+
"""
|
|
2114
|
+
|
|
2115
|
+
event_types: List["LifecycleEventType"] = betterproto.enum_field(2)
|
|
2116
|
+
"""
|
|
2117
|
+
Event types to receive (empty = all types)
|
|
2118
|
+
Maps to ActorLifecycleEvent.event_type oneof
|
|
2119
|
+
"""
|
|
2120
|
+
|
|
2121
|
+
actor_id_pattern: str = betterproto.string_field(3)
|
|
2122
|
+
"""
|
|
2123
|
+
Actor ID pattern (regex, empty = all actors)
|
|
2124
|
+
Example: "worker-.*@node1" matches all workers on node1
|
|
2125
|
+
"""
|
|
2126
|
+
|
|
2127
|
+
node_id_pattern: str = betterproto.string_field(4)
|
|
2128
|
+
"""
|
|
2129
|
+
Node ID pattern (regex, empty = all nodes)
|
|
2130
|
+
Example: "prod-.*" matches all production nodes
|
|
2131
|
+
"""
|
|
2132
|
+
|
|
2133
|
+
required_tags: Dict[str, str] = betterproto.map_field(
|
|
2134
|
+
5, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
2135
|
+
)
|
|
2136
|
+
"""
|
|
2137
|
+
Custom tags filter (AND logic - event must have all tags)
|
|
2138
|
+
Example: {"env": "production", "team": "platform"}
|
|
2139
|
+
"""
|
|
2140
|
+
|
|
2141
|
+
buffer_size: int = betterproto.uint32_field(6)
|
|
2142
|
+
"""
|
|
2143
|
+
Buffer size for slow subscriber (default: 1000 events)
|
|
2144
|
+
When buffer full, drop_policy determines behavior
|
|
2145
|
+
"""
|
|
2146
|
+
|
|
2147
|
+
drop_policy: "DropPolicy" = betterproto.enum_field(7)
|
|
2148
|
+
"""Drop policy when buffer full"""
|
|
2149
|
+
|
|
2150
|
+
|
|
2151
|
+
@dataclass(eq=False, repr=False)
|
|
2152
|
+
class VirtualActorLifecycle(betterproto.Message):
|
|
2153
|
+
"""
|
|
2154
|
+
Virtual Actor Lifecycle (Orleans-inspired)
|
|
2155
|
+
|
|
2156
|
+
## Purpose
|
|
2157
|
+
Tracks activation/deactivation state for virtual actors (actors that exist virtually,
|
|
2158
|
+
activated on-demand). Virtual actors are always addressable but not always in memory.
|
|
2159
|
+
|
|
2160
|
+
## When Used
|
|
2161
|
+
Only present when actor has VirtualActorFacet attached (opt-in pattern).
|
|
2162
|
+
Regular actors (explicit creation) don't have this lifecycle tracking.
|
|
2163
|
+
|
|
2164
|
+
## Design Decision
|
|
2165
|
+
Virtual actor lifecycle is tracked separately from core ActorState to maintain
|
|
2166
|
+
simplicity: core actors are explicit, virtual actors are opt-in via facet.
|
|
2167
|
+
|
|
2168
|
+
## Example
|
|
2169
|
+
```protobuf
|
|
2170
|
+
Actor {
|
|
2171
|
+
actor_id: "user-123"
|
|
2172
|
+
state: ACTOR_STATE_INACTIVE // Virtual actor, not in memory
|
|
2173
|
+
facets: [
|
|
2174
|
+
Facet {
|
|
2175
|
+
type: "virtual_actor"
|
|
2176
|
+
config: {
|
|
2177
|
+
"idle_timeout": "5m",
|
|
2178
|
+
"activation_strategy": "lazy"
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
]
|
|
2182
|
+
}
|
|
2183
|
+
```
|
|
2184
|
+
Virtual Actor Lifecycle Metadata
|
|
2185
|
+
|
|
2186
|
+
## Purpose
|
|
2187
|
+
Provides metadata about virtual actor activation/deactivation (timestamps, counts, etc.).
|
|
2188
|
+
This is METADATA only - the actual lifecycle state is tracked in Actor.state (ActorState enum).
|
|
2189
|
+
|
|
2190
|
+
## Design Decision
|
|
2191
|
+
All actors (virtual or not) use the same ActorState enum for state consistency.
|
|
2192
|
+
VirtualActorLifecycle provides additional metadata useful for virtual actors:
|
|
2193
|
+
- Activation timestamps (for monitoring/debugging)
|
|
2194
|
+
- Activation counts (for metrics)
|
|
2195
|
+
- Idle timeout configuration
|
|
2196
|
+
- Pending message counts
|
|
2197
|
+
|
|
2198
|
+
## Usage
|
|
2199
|
+
- Actor.state: Source of truth for lifecycle state (CREATING, ACTIVE, INACTIVE, etc.)
|
|
2200
|
+
- VirtualActorLifecycle: Optional metadata for virtual actors only
|
|
2201
|
+
"""
|
|
2202
|
+
|
|
2203
|
+
last_activated: datetime = betterproto.message_field(1)
|
|
2204
|
+
"""Last time actor was activated (loaded into memory)"""
|
|
2205
|
+
|
|
2206
|
+
last_accessed: datetime = betterproto.message_field(2)
|
|
2207
|
+
"""Last time actor received a message or performed an operation"""
|
|
2208
|
+
|
|
2209
|
+
idle_timeout: timedelta = betterproto.message_field(3)
|
|
2210
|
+
"""Idle timeout before deactivation (from facet config)"""
|
|
2211
|
+
|
|
2212
|
+
activation_count: int = betterproto.uint32_field(4)
|
|
2213
|
+
"""Number of times this actor has been activated"""
|
|
2214
|
+
|
|
2215
|
+
is_activating: bool = betterproto.bool_field(5)
|
|
2216
|
+
"""Is currently activating (prevents duplicate activations)"""
|
|
2217
|
+
|
|
2218
|
+
pending_message_count: int = betterproto.uint32_field(6)
|
|
2219
|
+
"""
|
|
2220
|
+
Messages queued during activation (processed after activation completes)
|
|
2221
|
+
Note: This is a simplified representation - actual queue is in Node
|
|
2222
|
+
"""
|
|
2223
|
+
|
|
2224
|
+
|
|
2225
|
+
@dataclass(eq=False, repr=False)
|
|
2226
|
+
class VirtualActorConfig(betterproto.Message):
|
|
2227
|
+
"""
|
|
2228
|
+
Virtual Actor Configuration (for VirtualActorFacet)
|
|
2229
|
+
|
|
2230
|
+
## Purpose
|
|
2231
|
+
Configuration for virtual actor behavior (activation strategy, idle timeout, etc.)
|
|
2232
|
+
|
|
2233
|
+
## Usage
|
|
2234
|
+
This config is stored in the VirtualActorFacet's config map:
|
|
2235
|
+
```protobuf
|
|
2236
|
+
Facet {
|
|
2237
|
+
type: "virtual_actor"
|
|
2238
|
+
config: {
|
|
2239
|
+
"idle_timeout": "5m",
|
|
2240
|
+
"activation_strategy": "lazy"
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
```
|
|
2244
|
+
|
|
2245
|
+
## Design Decision
|
|
2246
|
+
Config is stored as string map in Facet (simplicity, flexibility).
|
|
2247
|
+
This message is for documentation and type safety in Rust code.
|
|
2248
|
+
"""
|
|
2249
|
+
|
|
2250
|
+
activation_strategy: "__common_v1__.ActivationStrategy" = betterproto.enum_field(1)
|
|
2251
|
+
"""Activation strategy (from common.proto)"""
|
|
2252
|
+
|
|
2253
|
+
idle_timeout: timedelta = betterproto.message_field(2)
|
|
2254
|
+
"""Idle timeout before deactivation"""
|
|
2255
|
+
|
|
2256
|
+
persist_on_deactivation: bool = betterproto.bool_field(3)
|
|
2257
|
+
"""Should actor persist state on deactivation?"""
|
|
2258
|
+
|
|
2259
|
+
|
|
2260
|
+
@dataclass(eq=False, repr=False)
|
|
2261
|
+
class ActorRefError(betterproto.Message):
|
|
2262
|
+
"""ActorRef error message"""
|
|
2263
|
+
|
|
2264
|
+
code: "ActorRefErrorCode" = betterproto.enum_field(1)
|
|
2265
|
+
message: str = betterproto.string_field(2)
|
|
2266
|
+
actor_id: str = betterproto.string_field(3)
|
|
2267
|
+
|
|
2268
|
+
|
|
2269
|
+
@dataclass(eq=False, repr=False)
|
|
2270
|
+
class ResourceContract(betterproto.Message):
|
|
2271
|
+
"""
|
|
2272
|
+
Resource contract for an actor
|
|
2273
|
+
Declares resource requirements and limits upfront
|
|
2274
|
+
"""
|
|
2275
|
+
|
|
2276
|
+
max_cpu_percent: float = betterproto.float_field(1)
|
|
2277
|
+
"""Maximum CPU usage as percentage (0.0 - 100.0)"""
|
|
2278
|
+
|
|
2279
|
+
max_memory_bytes: int = betterproto.uint64_field(2)
|
|
2280
|
+
"""Maximum memory usage in bytes"""
|
|
2281
|
+
|
|
2282
|
+
max_io_ops_per_sec: Optional[int] = betterproto.uint32_field(3, optional=True)
|
|
2283
|
+
"""Maximum I/O operations per second"""
|
|
2284
|
+
|
|
2285
|
+
guaranteed_bandwidth_mbps: Optional[int] = betterproto.uint32_field(
|
|
2286
|
+
4, optional=True
|
|
2287
|
+
)
|
|
2288
|
+
"""Guaranteed network bandwidth in Mbps"""
|
|
2289
|
+
|
|
2290
|
+
max_execution_time: Optional[timedelta] = betterproto.message_field(
|
|
2291
|
+
5, optional=True
|
|
2292
|
+
)
|
|
2293
|
+
"""Maximum execution time per message"""
|
|
2294
|
+
|
|
2295
|
+
|
|
2296
|
+
@dataclass(eq=False, repr=False)
|
|
2297
|
+
class ResourceUsage(betterproto.Message):
|
|
2298
|
+
"""Current resource usage of an actor"""
|
|
2299
|
+
|
|
2300
|
+
cpu_percent: float = betterproto.float_field(1)
|
|
2301
|
+
"""Current CPU usage percentage"""
|
|
2302
|
+
|
|
2303
|
+
memory_bytes: int = betterproto.uint64_field(2)
|
|
2304
|
+
"""Current memory usage in bytes"""
|
|
2305
|
+
|
|
2306
|
+
io_ops_per_sec: int = betterproto.uint32_field(3)
|
|
2307
|
+
"""Current I/O operations per second"""
|
|
2308
|
+
|
|
2309
|
+
network_mbps: int = betterproto.uint32_field(4)
|
|
2310
|
+
"""Current network bandwidth in Mbps"""
|
|
2311
|
+
|
|
2312
|
+
|
|
2313
|
+
@dataclass(eq=False, repr=False)
|
|
2314
|
+
class ResourceViolation(betterproto.Message):
|
|
2315
|
+
"""Resource violation error message"""
|
|
2316
|
+
|
|
2317
|
+
code: "ResourceViolationCode" = betterproto.enum_field(1)
|
|
2318
|
+
message: str = betterproto.string_field(2)
|
|
2319
|
+
allowed_value: Optional[float] = betterproto.float_field(3, optional=True)
|
|
2320
|
+
"""Allowed value (e.g., max_cpu_percent)"""
|
|
2321
|
+
|
|
2322
|
+
actual_value: Optional[float] = betterproto.float_field(4, optional=True)
|
|
2323
|
+
"""Actual value (e.g., current cpu_percent)"""
|
|
2324
|
+
|
|
2325
|
+
|
|
2326
|
+
@dataclass(eq=False, repr=False)
|
|
2327
|
+
class ActorHealth(betterproto.Message):
|
|
2328
|
+
"""Actor health message"""
|
|
2329
|
+
|
|
2330
|
+
status: "ActorHealthStatus" = betterproto.enum_field(1)
|
|
2331
|
+
stuck_since: Optional[timedelta] = betterproto.message_field(2, optional=True)
|
|
2332
|
+
"""For STUCK status: how long actor has been stuck"""
|
|
2333
|
+
|
|
2334
|
+
failure_reason: Optional[str] = betterproto.string_field(3, optional=True)
|
|
2335
|
+
"""For FAILED status: reason for failure"""
|
|
2336
|
+
|
|
2337
|
+
|
|
2338
|
+
@dataclass(eq=False, repr=False)
|
|
2339
|
+
class ActorSpawnSpec(betterproto.Message):
|
|
2340
|
+
"""
|
|
2341
|
+
Complete specification for spawning or reactivating any actor.
|
|
2342
|
+
|
|
2343
|
+
## Purpose
|
|
2344
|
+
Single source of truth for all information needed to spawn an actor, whether
|
|
2345
|
+
from TOML app-config, SDK annotations, gRPC, or virtual actor reactivation.
|
|
2346
|
+
Replaces the fragmented triple of (init_config_template, initial_state, labels)
|
|
2347
|
+
and the VirtualActorDefinitionRegistration intermediary.
|
|
2348
|
+
|
|
2349
|
+
## Design
|
|
2350
|
+
- node_id is NOT included: ActorFactory always resolves local_node_id at spawn time.
|
|
2351
|
+
- tenant_id is overridden from JWT at request time if available.
|
|
2352
|
+
- args map is the canonical user-supplied init payload: becomes "args" key in WASM init().
|
|
2353
|
+
- facets carry the full facet declaration (type, config, priority) verbatim from ChildSpec.
|
|
2354
|
+
|
|
2355
|
+
## Usage
|
|
2356
|
+
- TOML ChildSpec → ActorSpawnSpec via actor_spawn_spec_from_child_spec()
|
|
2357
|
+
- SDK annotations → ActorSpawnSpec built from behavior + declared facets
|
|
2358
|
+
- VirtualActorMetadata stores ActorSpawnSpec as its spec field
|
|
2359
|
+
- ActorBuilder.from_spec() accepts ActorSpawnSpec
|
|
2360
|
+
- ActorFactory.spawn_actor() accepts ActorSpawnSpec
|
|
2361
|
+
"""
|
|
2362
|
+
|
|
2363
|
+
identity: "__common_v1__.ActorIdentity" = betterproto.message_field(1)
|
|
2364
|
+
"""
|
|
2365
|
+
Instance name + behavior class (namespace and tenant added in fields below).
|
|
2366
|
+
"""
|
|
2367
|
+
|
|
2368
|
+
role: str = betterproto.string_field(2)
|
|
2369
|
+
"""
|
|
2370
|
+
Role of the actor within its application (e.g. "worker", "leader").
|
|
2371
|
+
Maps 1:1 to ChildSpec.role (TOML `role` field in [[supervisor.children]]).
|
|
2372
|
+
Used by BehaviorRegistry to dispatch the correct spec when multiple children
|
|
2373
|
+
share the same actor_type (behavior class).
|
|
2374
|
+
"""
|
|
2375
|
+
|
|
2376
|
+
namespace: str = betterproto.string_field(3)
|
|
2377
|
+
"""Namespace for actor isolation (required at spawn time)."""
|
|
2378
|
+
|
|
2379
|
+
tenant_id: str = betterproto.string_field(4)
|
|
2380
|
+
"""
|
|
2381
|
+
Tenant ID for multi-tenancy isolation (empty if auth disabled).
|
|
2382
|
+
Overridden from JWT claims at request time when auth is enabled.
|
|
2383
|
+
"""
|
|
2384
|
+
|
|
2385
|
+
visibility: "ActorVisibility" = betterproto.enum_field(5)
|
|
2386
|
+
"""
|
|
2387
|
+
Tell/ask isolation for cross-tenant/cross-namespace callers (see ActorVisibility).
|
|
2388
|
+
UNSPECIFIED is treated as PUBLIC.
|
|
2389
|
+
"""
|
|
2390
|
+
|
|
2391
|
+
behavior_kind: str = betterproto.string_field(6)
|
|
2392
|
+
"""
|
|
2393
|
+
OTP-style behavior kind for logging and observability.
|
|
2394
|
+
Examples: "GenServer", "GenEvent", "GenStateMachine", "Workflow".
|
|
2395
|
+
"""
|
|
2396
|
+
|
|
2397
|
+
args: Dict[str, str] = betterproto.map_field(
|
|
2398
|
+
7, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
2399
|
+
)
|
|
2400
|
+
"""
|
|
2401
|
+
User-supplied initialization arguments.
|
|
2402
|
+
These become the "args" field in the WASM init() payload so TypeScript/Python/Go
|
|
2403
|
+
actors can read them via host.config("initial_count"), etc.
|
|
2404
|
+
Also used by Rust embedded actors as configuration.
|
|
2405
|
+
"""
|
|
2406
|
+
|
|
2407
|
+
facets: List["__common_v1__.Facet"] = betterproto.message_field(8)
|
|
2408
|
+
"""
|
|
2409
|
+
Facet declarations attached to this actor.
|
|
2410
|
+
Carries virtual_actor, durability, timer, etc. facets verbatim from ChildSpec.
|
|
2411
|
+
ActorFactory instantiates these at spawn time via create_facets_from_config().
|
|
2412
|
+
"""
|
|
2413
|
+
|
|
2414
|
+
labels: Dict[str, str] = betterproto.map_field(
|
|
2415
|
+
9, betterproto.TYPE_STRING, betterproto.TYPE_STRING
|
|
2416
|
+
)
|
|
2417
|
+
"""Observability labels propagated to metrics and traces."""
|
|
2418
|
+
|
|
2419
|
+
config: "ActorConfig" = betterproto.message_field(10)
|
|
2420
|
+
"""
|
|
2421
|
+
Actor runtime configuration (mailbox, restart policy, etc.).
|
|
2422
|
+
Optional — defaults apply when absent.
|
|
2423
|
+
"""
|
|
2424
|
+
|
|
2425
|
+
register_in_object_registry: bool = betterproto.bool_field(11)
|
|
2426
|
+
"""
|
|
2427
|
+
If true, auto-register this actor in ObjectRegistry on spawn and unregister on stop.
|
|
2428
|
+
Auto-enabled when facets include both "virtual_actor" and "durability".
|
|
2429
|
+
"""
|
|
2430
|
+
|
|
2431
|
+
enforce_unique_placement: bool = betterproto.bool_field(12)
|
|
2432
|
+
"""
|
|
2433
|
+
If true, enforce unique placement via alias (requires register_in_object_registry=true or auto-enabled).
|
|
2434
|
+
Spawn fails with ACTOR_ERROR_PLACEMENT_CONFLICT if another active instance with same identity exists.
|
|
2435
|
+
"""
|
|
2436
|
+
|
|
2437
|
+
placement_strategy: "PlacementStrategy" = betterproto.enum_field(13)
|
|
2438
|
+
"""
|
|
2439
|
+
Placement strategy for distributed actor placement (default: PREFER_LOCAL).
|
|
2440
|
+
"""
|
|
2441
|
+
|
|
2442
|
+
|
|
2443
|
+
class ActorServiceStub(betterproto.ServiceStub):
|
|
2444
|
+
async def spawn_actor(
|
|
2445
|
+
self,
|
|
2446
|
+
spawn_actor_request: "SpawnActorRequest",
|
|
2447
|
+
*,
|
|
2448
|
+
timeout: Optional[float] = None,
|
|
2449
|
+
deadline: Optional["Deadline"] = None,
|
|
2450
|
+
metadata: Optional["MetadataLike"] = None
|
|
2451
|
+
) -> "SpawnActorResponse":
|
|
2452
|
+
return await self._unary_unary(
|
|
2453
|
+
"/plexspaces.actor.v1.ActorService/SpawnActor",
|
|
2454
|
+
spawn_actor_request,
|
|
2455
|
+
SpawnActorResponse,
|
|
2456
|
+
timeout=timeout,
|
|
2457
|
+
deadline=deadline,
|
|
2458
|
+
metadata=metadata,
|
|
2459
|
+
)
|
|
2460
|
+
|
|
2461
|
+
async def spawn_actors(
|
|
2462
|
+
self,
|
|
2463
|
+
spawn_actors_request: "SpawnActorsRequest",
|
|
2464
|
+
*,
|
|
2465
|
+
timeout: Optional[float] = None,
|
|
2466
|
+
deadline: Optional["Deadline"] = None,
|
|
2467
|
+
metadata: Optional["MetadataLike"] = None
|
|
2468
|
+
) -> "SpawnActorsResponse":
|
|
2469
|
+
return await self._unary_unary(
|
|
2470
|
+
"/plexspaces.actor.v1.ActorService/SpawnActors",
|
|
2471
|
+
spawn_actors_request,
|
|
2472
|
+
SpawnActorsResponse,
|
|
2473
|
+
timeout=timeout,
|
|
2474
|
+
deadline=deadline,
|
|
2475
|
+
metadata=metadata,
|
|
2476
|
+
)
|
|
2477
|
+
|
|
2478
|
+
async def get_actor(
|
|
2479
|
+
self,
|
|
2480
|
+
get_actor_request: "GetActorRequest",
|
|
2481
|
+
*,
|
|
2482
|
+
timeout: Optional[float] = None,
|
|
2483
|
+
deadline: Optional["Deadline"] = None,
|
|
2484
|
+
metadata: Optional["MetadataLike"] = None
|
|
2485
|
+
) -> "GetActorResponse":
|
|
2486
|
+
return await self._unary_unary(
|
|
2487
|
+
"/plexspaces.actor.v1.ActorService/GetActor",
|
|
2488
|
+
get_actor_request,
|
|
2489
|
+
GetActorResponse,
|
|
2490
|
+
timeout=timeout,
|
|
2491
|
+
deadline=deadline,
|
|
2492
|
+
metadata=metadata,
|
|
2493
|
+
)
|
|
2494
|
+
|
|
2495
|
+
async def list_actors(
|
|
2496
|
+
self,
|
|
2497
|
+
list_actors_request: "ListActorsRequest",
|
|
2498
|
+
*,
|
|
2499
|
+
timeout: Optional[float] = None,
|
|
2500
|
+
deadline: Optional["Deadline"] = None,
|
|
2501
|
+
metadata: Optional["MetadataLike"] = None
|
|
2502
|
+
) -> "ListActorsResponse":
|
|
2503
|
+
return await self._unary_unary(
|
|
2504
|
+
"/plexspaces.actor.v1.ActorService/ListActors",
|
|
2505
|
+
list_actors_request,
|
|
2506
|
+
ListActorsResponse,
|
|
2507
|
+
timeout=timeout,
|
|
2508
|
+
deadline=deadline,
|
|
2509
|
+
metadata=metadata,
|
|
2510
|
+
)
|
|
2511
|
+
|
|
2512
|
+
async def send_message(
|
|
2513
|
+
self,
|
|
2514
|
+
send_message_request: "SendMessageRequest",
|
|
2515
|
+
*,
|
|
2516
|
+
timeout: Optional[float] = None,
|
|
2517
|
+
deadline: Optional["Deadline"] = None,
|
|
2518
|
+
metadata: Optional["MetadataLike"] = None
|
|
2519
|
+
) -> "SendMessageResponse":
|
|
2520
|
+
return await self._unary_unary(
|
|
2521
|
+
"/plexspaces.actor.v1.ActorService/SendMessage",
|
|
2522
|
+
send_message_request,
|
|
2523
|
+
SendMessageResponse,
|
|
2524
|
+
timeout=timeout,
|
|
2525
|
+
deadline=deadline,
|
|
2526
|
+
metadata=metadata,
|
|
2527
|
+
)
|
|
2528
|
+
|
|
2529
|
+
async def stream_messages(
|
|
2530
|
+
self,
|
|
2531
|
+
stream_message_request_iterator: Union[
|
|
2532
|
+
AsyncIterable[StreamMessageRequest], Iterable[StreamMessageRequest]
|
|
2533
|
+
],
|
|
2534
|
+
*,
|
|
2535
|
+
timeout: Optional[float] = None,
|
|
2536
|
+
deadline: Optional["Deadline"] = None,
|
|
2537
|
+
metadata: Optional["MetadataLike"] = None
|
|
2538
|
+
) -> AsyncIterator[StreamMessageResponse]:
|
|
2539
|
+
async for response in self._stream_stream(
|
|
2540
|
+
"/plexspaces.actor.v1.ActorService/StreamMessages",
|
|
2541
|
+
stream_message_request_iterator,
|
|
2542
|
+
StreamMessageRequest,
|
|
2543
|
+
StreamMessageResponse,
|
|
2544
|
+
timeout=timeout,
|
|
2545
|
+
deadline=deadline,
|
|
2546
|
+
metadata=metadata,
|
|
2547
|
+
):
|
|
2548
|
+
yield response
|
|
2549
|
+
|
|
2550
|
+
async def delete_actor(
|
|
2551
|
+
self,
|
|
2552
|
+
delete_actor_request: "DeleteActorRequest",
|
|
2553
|
+
*,
|
|
2554
|
+
timeout: Optional[float] = None,
|
|
2555
|
+
deadline: Optional["Deadline"] = None,
|
|
2556
|
+
metadata: Optional["MetadataLike"] = None
|
|
2557
|
+
) -> "__common_v1__.Empty":
|
|
2558
|
+
return await self._unary_unary(
|
|
2559
|
+
"/plexspaces.actor.v1.ActorService/DeleteActor",
|
|
2560
|
+
delete_actor_request,
|
|
2561
|
+
__common_v1__.Empty,
|
|
2562
|
+
timeout=timeout,
|
|
2563
|
+
deadline=deadline,
|
|
2564
|
+
metadata=metadata,
|
|
2565
|
+
)
|
|
2566
|
+
|
|
2567
|
+
async def monitor_actor(
|
|
2568
|
+
self,
|
|
2569
|
+
monitor_actor_request: "MonitorActorRequest",
|
|
2570
|
+
*,
|
|
2571
|
+
timeout: Optional[float] = None,
|
|
2572
|
+
deadline: Optional["Deadline"] = None,
|
|
2573
|
+
metadata: Optional["MetadataLike"] = None
|
|
2574
|
+
) -> "MonitorActorResponse":
|
|
2575
|
+
return await self._unary_unary(
|
|
2576
|
+
"/plexspaces.actor.v1.ActorService/MonitorActor",
|
|
2577
|
+
monitor_actor_request,
|
|
2578
|
+
MonitorActorResponse,
|
|
2579
|
+
timeout=timeout,
|
|
2580
|
+
deadline=deadline,
|
|
2581
|
+
metadata=metadata,
|
|
2582
|
+
)
|
|
2583
|
+
|
|
2584
|
+
async def demonitor_actor(
|
|
2585
|
+
self,
|
|
2586
|
+
demonitor_actor_request: "DemonitorActorRequest",
|
|
2587
|
+
*,
|
|
2588
|
+
timeout: Optional[float] = None,
|
|
2589
|
+
deadline: Optional["Deadline"] = None,
|
|
2590
|
+
metadata: Optional["MetadataLike"] = None
|
|
2591
|
+
) -> "__common_v1__.Empty":
|
|
2592
|
+
return await self._unary_unary(
|
|
2593
|
+
"/plexspaces.actor.v1.ActorService/DemonitorActor",
|
|
2594
|
+
demonitor_actor_request,
|
|
2595
|
+
__common_v1__.Empty,
|
|
2596
|
+
timeout=timeout,
|
|
2597
|
+
deadline=deadline,
|
|
2598
|
+
metadata=metadata,
|
|
2599
|
+
)
|
|
2600
|
+
|
|
2601
|
+
async def link_actor(
|
|
2602
|
+
self,
|
|
2603
|
+
link_actor_request: "LinkActorRequest",
|
|
2604
|
+
*,
|
|
2605
|
+
timeout: Optional[float] = None,
|
|
2606
|
+
deadline: Optional["Deadline"] = None,
|
|
2607
|
+
metadata: Optional["MetadataLike"] = None
|
|
2608
|
+
) -> "LinkActorResponse":
|
|
2609
|
+
return await self._unary_unary(
|
|
2610
|
+
"/plexspaces.actor.v1.ActorService/LinkActor",
|
|
2611
|
+
link_actor_request,
|
|
2612
|
+
LinkActorResponse,
|
|
2613
|
+
timeout=timeout,
|
|
2614
|
+
deadline=deadline,
|
|
2615
|
+
metadata=metadata,
|
|
2616
|
+
)
|
|
2617
|
+
|
|
2618
|
+
async def unlink_actor(
|
|
2619
|
+
self,
|
|
2620
|
+
unlink_actor_request: "UnlinkActorRequest",
|
|
2621
|
+
*,
|
|
2622
|
+
timeout: Optional[float] = None,
|
|
2623
|
+
deadline: Optional["Deadline"] = None,
|
|
2624
|
+
metadata: Optional["MetadataLike"] = None
|
|
2625
|
+
) -> "UnlinkActorResponse":
|
|
2626
|
+
return await self._unary_unary(
|
|
2627
|
+
"/plexspaces.actor.v1.ActorService/UnlinkActor",
|
|
2628
|
+
unlink_actor_request,
|
|
2629
|
+
UnlinkActorResponse,
|
|
2630
|
+
timeout=timeout,
|
|
2631
|
+
deadline=deadline,
|
|
2632
|
+
metadata=metadata,
|
|
2633
|
+
)
|
|
2634
|
+
|
|
2635
|
+
async def notify_actor_down(
|
|
2636
|
+
self,
|
|
2637
|
+
actor_down_notification: "ActorDownNotification",
|
|
2638
|
+
*,
|
|
2639
|
+
timeout: Optional[float] = None,
|
|
2640
|
+
deadline: Optional["Deadline"] = None,
|
|
2641
|
+
metadata: Optional["MetadataLike"] = None
|
|
2642
|
+
) -> "__common_v1__.Empty":
|
|
2643
|
+
return await self._unary_unary(
|
|
2644
|
+
"/plexspaces.actor.v1.ActorService/NotifyActorDown",
|
|
2645
|
+
actor_down_notification,
|
|
2646
|
+
__common_v1__.Empty,
|
|
2647
|
+
timeout=timeout,
|
|
2648
|
+
deadline=deadline,
|
|
2649
|
+
metadata=metadata,
|
|
2650
|
+
)
|
|
2651
|
+
|
|
2652
|
+
async def check_actor_exists(
|
|
2653
|
+
self,
|
|
2654
|
+
check_actor_exists_request: "CheckActorExistsRequest",
|
|
2655
|
+
*,
|
|
2656
|
+
timeout: Optional[float] = None,
|
|
2657
|
+
deadline: Optional["Deadline"] = None,
|
|
2658
|
+
metadata: Optional["MetadataLike"] = None
|
|
2659
|
+
) -> "CheckActorExistsResponse":
|
|
2660
|
+
return await self._unary_unary(
|
|
2661
|
+
"/plexspaces.actor.v1.ActorService/CheckActorExists",
|
|
2662
|
+
check_actor_exists_request,
|
|
2663
|
+
CheckActorExistsResponse,
|
|
2664
|
+
timeout=timeout,
|
|
2665
|
+
deadline=deadline,
|
|
2666
|
+
metadata=metadata,
|
|
2667
|
+
)
|
|
2668
|
+
|
|
2669
|
+
async def get_actor_states(
|
|
2670
|
+
self,
|
|
2671
|
+
get_actor_states_request: "GetActorStatesRequest",
|
|
2672
|
+
*,
|
|
2673
|
+
timeout: Optional[float] = None,
|
|
2674
|
+
deadline: Optional["Deadline"] = None,
|
|
2675
|
+
metadata: Optional["MetadataLike"] = None
|
|
2676
|
+
) -> "GetActorStatesResponse":
|
|
2677
|
+
return await self._unary_unary(
|
|
2678
|
+
"/plexspaces.actor.v1.ActorService/GetActorStates",
|
|
2679
|
+
get_actor_states_request,
|
|
2680
|
+
GetActorStatesResponse,
|
|
2681
|
+
timeout=timeout,
|
|
2682
|
+
deadline=deadline,
|
|
2683
|
+
metadata=metadata,
|
|
2684
|
+
)
|
|
2685
|
+
|
|
2686
|
+
async def ask_reply(
|
|
2687
|
+
self,
|
|
2688
|
+
ask_reply_request: "AskReplyRequest",
|
|
2689
|
+
*,
|
|
2690
|
+
timeout: Optional[float] = None,
|
|
2691
|
+
deadline: Optional["Deadline"] = None,
|
|
2692
|
+
metadata: Optional["MetadataLike"] = None
|
|
2693
|
+
) -> "AskReplyResponse":
|
|
2694
|
+
return await self._unary_unary(
|
|
2695
|
+
"/plexspaces.actor.v1.ActorService/AskReply",
|
|
2696
|
+
ask_reply_request,
|
|
2697
|
+
AskReplyResponse,
|
|
2698
|
+
timeout=timeout,
|
|
2699
|
+
deadline=deadline,
|
|
2700
|
+
metadata=metadata,
|
|
2701
|
+
)
|
|
2702
|
+
|
|
2703
|
+
async def create_shard_group(
|
|
2704
|
+
self,
|
|
2705
|
+
create_shard_group_request: "CreateShardGroupRequest",
|
|
2706
|
+
*,
|
|
2707
|
+
timeout: Optional[float] = None,
|
|
2708
|
+
deadline: Optional["Deadline"] = None,
|
|
2709
|
+
metadata: Optional["MetadataLike"] = None
|
|
2710
|
+
) -> "CreateShardGroupResponse":
|
|
2711
|
+
return await self._unary_unary(
|
|
2712
|
+
"/plexspaces.actor.v1.ActorService/CreateShardGroup",
|
|
2713
|
+
create_shard_group_request,
|
|
2714
|
+
CreateShardGroupResponse,
|
|
2715
|
+
timeout=timeout,
|
|
2716
|
+
deadline=deadline,
|
|
2717
|
+
metadata=metadata,
|
|
2718
|
+
)
|
|
2719
|
+
|
|
2720
|
+
async def delete_shard_group(
|
|
2721
|
+
self,
|
|
2722
|
+
delete_shard_group_request: "DeleteShardGroupRequest",
|
|
2723
|
+
*,
|
|
2724
|
+
timeout: Optional[float] = None,
|
|
2725
|
+
deadline: Optional["Deadline"] = None,
|
|
2726
|
+
metadata: Optional["MetadataLike"] = None
|
|
2727
|
+
) -> "__common_v1__.Empty":
|
|
2728
|
+
return await self._unary_unary(
|
|
2729
|
+
"/plexspaces.actor.v1.ActorService/DeleteShardGroup",
|
|
2730
|
+
delete_shard_group_request,
|
|
2731
|
+
__common_v1__.Empty,
|
|
2732
|
+
timeout=timeout,
|
|
2733
|
+
deadline=deadline,
|
|
2734
|
+
metadata=metadata,
|
|
2735
|
+
)
|
|
2736
|
+
|
|
2737
|
+
async def get_shard_group(
|
|
2738
|
+
self,
|
|
2739
|
+
get_shard_group_request: "GetShardGroupRequest",
|
|
2740
|
+
*,
|
|
2741
|
+
timeout: Optional[float] = None,
|
|
2742
|
+
deadline: Optional["Deadline"] = None,
|
|
2743
|
+
metadata: Optional["MetadataLike"] = None
|
|
2744
|
+
) -> "GetShardGroupResponse":
|
|
2745
|
+
return await self._unary_unary(
|
|
2746
|
+
"/plexspaces.actor.v1.ActorService/GetShardGroup",
|
|
2747
|
+
get_shard_group_request,
|
|
2748
|
+
GetShardGroupResponse,
|
|
2749
|
+
timeout=timeout,
|
|
2750
|
+
deadline=deadline,
|
|
2751
|
+
metadata=metadata,
|
|
2752
|
+
)
|
|
2753
|
+
|
|
2754
|
+
async def list_shard_groups(
|
|
2755
|
+
self,
|
|
2756
|
+
list_shard_groups_request: "ListShardGroupsRequest",
|
|
2757
|
+
*,
|
|
2758
|
+
timeout: Optional[float] = None,
|
|
2759
|
+
deadline: Optional["Deadline"] = None,
|
|
2760
|
+
metadata: Optional["MetadataLike"] = None
|
|
2761
|
+
) -> "ListShardGroupsResponse":
|
|
2762
|
+
return await self._unary_unary(
|
|
2763
|
+
"/plexspaces.actor.v1.ActorService/ListShardGroups",
|
|
2764
|
+
list_shard_groups_request,
|
|
2765
|
+
ListShardGroupsResponse,
|
|
2766
|
+
timeout=timeout,
|
|
2767
|
+
deadline=deadline,
|
|
2768
|
+
metadata=metadata,
|
|
2769
|
+
)
|
|
2770
|
+
|
|
2771
|
+
async def scale_shard_group(
|
|
2772
|
+
self,
|
|
2773
|
+
scale_shard_group_request: "ScaleShardGroupRequest",
|
|
2774
|
+
*,
|
|
2775
|
+
timeout: Optional[float] = None,
|
|
2776
|
+
deadline: Optional["Deadline"] = None,
|
|
2777
|
+
metadata: Optional["MetadataLike"] = None
|
|
2778
|
+
) -> "ScaleShardGroupResponse":
|
|
2779
|
+
return await self._unary_unary(
|
|
2780
|
+
"/plexspaces.actor.v1.ActorService/ScaleShardGroup",
|
|
2781
|
+
scale_shard_group_request,
|
|
2782
|
+
ScaleShardGroupResponse,
|
|
2783
|
+
timeout=timeout,
|
|
2784
|
+
deadline=deadline,
|
|
2785
|
+
metadata=metadata,
|
|
2786
|
+
)
|
|
2787
|
+
|
|
2788
|
+
async def send_to_shard(
|
|
2789
|
+
self,
|
|
2790
|
+
send_to_shard_request: "SendToShardRequest",
|
|
2791
|
+
*,
|
|
2792
|
+
timeout: Optional[float] = None,
|
|
2793
|
+
deadline: Optional["Deadline"] = None,
|
|
2794
|
+
metadata: Optional["MetadataLike"] = None
|
|
2795
|
+
) -> "SendToShardResponse":
|
|
2796
|
+
return await self._unary_unary(
|
|
2797
|
+
"/plexspaces.actor.v1.ActorService/SendToShard",
|
|
2798
|
+
send_to_shard_request,
|
|
2799
|
+
SendToShardResponse,
|
|
2800
|
+
timeout=timeout,
|
|
2801
|
+
deadline=deadline,
|
|
2802
|
+
metadata=metadata,
|
|
2803
|
+
)
|
|
2804
|
+
|
|
2805
|
+
async def broadcast_shard_group(
|
|
2806
|
+
self,
|
|
2807
|
+
broadcast_shard_group_request: "BroadcastShardGroupRequest",
|
|
2808
|
+
*,
|
|
2809
|
+
timeout: Optional[float] = None,
|
|
2810
|
+
deadline: Optional["Deadline"] = None,
|
|
2811
|
+
metadata: Optional["MetadataLike"] = None
|
|
2812
|
+
) -> "BroadcastShardGroupResponse":
|
|
2813
|
+
return await self._unary_unary(
|
|
2814
|
+
"/plexspaces.actor.v1.ActorService/BroadcastShardGroup",
|
|
2815
|
+
broadcast_shard_group_request,
|
|
2816
|
+
BroadcastShardGroupResponse,
|
|
2817
|
+
timeout=timeout,
|
|
2818
|
+
deadline=deadline,
|
|
2819
|
+
metadata=metadata,
|
|
2820
|
+
)
|
|
2821
|
+
|
|
2822
|
+
async def reduce_shard_group(
|
|
2823
|
+
self,
|
|
2824
|
+
reduce_shard_group_request: "ReduceShardGroupRequest",
|
|
2825
|
+
*,
|
|
2826
|
+
timeout: Optional[float] = None,
|
|
2827
|
+
deadline: Optional["Deadline"] = None,
|
|
2828
|
+
metadata: Optional["MetadataLike"] = None
|
|
2829
|
+
) -> "ReduceShardGroupResponse":
|
|
2830
|
+
return await self._unary_unary(
|
|
2831
|
+
"/plexspaces.actor.v1.ActorService/ReduceShardGroup",
|
|
2832
|
+
reduce_shard_group_request,
|
|
2833
|
+
ReduceShardGroupResponse,
|
|
2834
|
+
timeout=timeout,
|
|
2835
|
+
deadline=deadline,
|
|
2836
|
+
metadata=metadata,
|
|
2837
|
+
)
|
|
2838
|
+
|
|
2839
|
+
async def all_reduce_shard_group(
|
|
2840
|
+
self,
|
|
2841
|
+
all_reduce_shard_group_request: "AllReduceShardGroupRequest",
|
|
2842
|
+
*,
|
|
2843
|
+
timeout: Optional[float] = None,
|
|
2844
|
+
deadline: Optional["Deadline"] = None,
|
|
2845
|
+
metadata: Optional["MetadataLike"] = None
|
|
2846
|
+
) -> "AllReduceShardGroupResponse":
|
|
2847
|
+
return await self._unary_unary(
|
|
2848
|
+
"/plexspaces.actor.v1.ActorService/AllReduceShardGroup",
|
|
2849
|
+
all_reduce_shard_group_request,
|
|
2850
|
+
AllReduceShardGroupResponse,
|
|
2851
|
+
timeout=timeout,
|
|
2852
|
+
deadline=deadline,
|
|
2853
|
+
metadata=metadata,
|
|
2854
|
+
)
|
|
2855
|
+
|
|
2856
|
+
async def barrier_shard_group(
|
|
2857
|
+
self,
|
|
2858
|
+
barrier_shard_group_request: "BarrierShardGroupRequest",
|
|
2859
|
+
*,
|
|
2860
|
+
timeout: Optional[float] = None,
|
|
2861
|
+
deadline: Optional["Deadline"] = None,
|
|
2862
|
+
metadata: Optional["MetadataLike"] = None
|
|
2863
|
+
) -> "BarrierShardGroupResponse":
|
|
2864
|
+
return await self._unary_unary(
|
|
2865
|
+
"/plexspaces.actor.v1.ActorService/BarrierShardGroup",
|
|
2866
|
+
barrier_shard_group_request,
|
|
2867
|
+
BarrierShardGroupResponse,
|
|
2868
|
+
timeout=timeout,
|
|
2869
|
+
deadline=deadline,
|
|
2870
|
+
metadata=metadata,
|
|
2871
|
+
)
|
|
2872
|
+
|
|
2873
|
+
async def scatter_gather(
|
|
2874
|
+
self,
|
|
2875
|
+
scatter_gather_request: "ScatterGatherRequest",
|
|
2876
|
+
*,
|
|
2877
|
+
timeout: Optional[float] = None,
|
|
2878
|
+
deadline: Optional["Deadline"] = None,
|
|
2879
|
+
metadata: Optional["MetadataLike"] = None
|
|
2880
|
+
) -> "ScatterGatherResponse":
|
|
2881
|
+
return await self._unary_unary(
|
|
2882
|
+
"/plexspaces.actor.v1.ActorService/ScatterGather",
|
|
2883
|
+
scatter_gather_request,
|
|
2884
|
+
ScatterGatherResponse,
|
|
2885
|
+
timeout=timeout,
|
|
2886
|
+
deadline=deadline,
|
|
2887
|
+
metadata=metadata,
|
|
2888
|
+
)
|
|
2889
|
+
|
|
2890
|
+
async def bulk_update_shard_group(
|
|
2891
|
+
self,
|
|
2892
|
+
bulk_update_shard_group_request: "BulkUpdateShardGroupRequest",
|
|
2893
|
+
*,
|
|
2894
|
+
timeout: Optional[float] = None,
|
|
2895
|
+
deadline: Optional["Deadline"] = None,
|
|
2896
|
+
metadata: Optional["MetadataLike"] = None
|
|
2897
|
+
) -> "BulkUpdateShardGroupResponse":
|
|
2898
|
+
return await self._unary_unary(
|
|
2899
|
+
"/plexspaces.actor.v1.ActorService/BulkUpdateShardGroup",
|
|
2900
|
+
bulk_update_shard_group_request,
|
|
2901
|
+
BulkUpdateShardGroupResponse,
|
|
2902
|
+
timeout=timeout,
|
|
2903
|
+
deadline=deadline,
|
|
2904
|
+
metadata=metadata,
|
|
2905
|
+
)
|
|
2906
|
+
|
|
2907
|
+
async def map_shard_group(
|
|
2908
|
+
self,
|
|
2909
|
+
map_shard_group_request: "MapShardGroupRequest",
|
|
2910
|
+
*,
|
|
2911
|
+
timeout: Optional[float] = None,
|
|
2912
|
+
deadline: Optional["Deadline"] = None,
|
|
2913
|
+
metadata: Optional["MetadataLike"] = None
|
|
2914
|
+
) -> "MapShardGroupResponse":
|
|
2915
|
+
return await self._unary_unary(
|
|
2916
|
+
"/plexspaces.actor.v1.ActorService/MapShardGroup",
|
|
2917
|
+
map_shard_group_request,
|
|
2918
|
+
MapShardGroupResponse,
|
|
2919
|
+
timeout=timeout,
|
|
2920
|
+
deadline=deadline,
|
|
2921
|
+
metadata=metadata,
|
|
2922
|
+
)
|
|
2923
|
+
|
|
2924
|
+
|
|
2925
|
+
class LifecycleEventChannelStub(betterproto.ServiceStub):
|
|
2926
|
+
async def subscribe_lifecycle_events(
|
|
2927
|
+
self,
|
|
2928
|
+
lifecycle_event_filter: "LifecycleEventFilter",
|
|
2929
|
+
*,
|
|
2930
|
+
timeout: Optional[float] = None,
|
|
2931
|
+
deadline: Optional["Deadline"] = None,
|
|
2932
|
+
metadata: Optional["MetadataLike"] = None
|
|
2933
|
+
) -> AsyncIterator[ActorLifecycleEvent]:
|
|
2934
|
+
async for response in self._unary_stream(
|
|
2935
|
+
"/plexspaces.actor.v1.LifecycleEventChannel/SubscribeLifecycleEvents",
|
|
2936
|
+
lifecycle_event_filter,
|
|
2937
|
+
ActorLifecycleEvent,
|
|
2938
|
+
timeout=timeout,
|
|
2939
|
+
deadline=deadline,
|
|
2940
|
+
metadata=metadata,
|
|
2941
|
+
):
|
|
2942
|
+
yield response
|
|
2943
|
+
|
|
2944
|
+
async def publish_lifecycle_event(
|
|
2945
|
+
self,
|
|
2946
|
+
actor_lifecycle_event: "ActorLifecycleEvent",
|
|
2947
|
+
*,
|
|
2948
|
+
timeout: Optional[float] = None,
|
|
2949
|
+
deadline: Optional["Deadline"] = None,
|
|
2950
|
+
metadata: Optional["MetadataLike"] = None
|
|
2951
|
+
) -> "__common_v1__.Empty":
|
|
2952
|
+
return await self._unary_unary(
|
|
2953
|
+
"/plexspaces.actor.v1.LifecycleEventChannel/PublishLifecycleEvent",
|
|
2954
|
+
actor_lifecycle_event,
|
|
2955
|
+
__common_v1__.Empty,
|
|
2956
|
+
timeout=timeout,
|
|
2957
|
+
deadline=deadline,
|
|
2958
|
+
metadata=metadata,
|
|
2959
|
+
)
|
|
2960
|
+
|
|
2961
|
+
|
|
2962
|
+
class ActorServiceBase(ServiceBase):
|
|
2963
|
+
|
|
2964
|
+
async def spawn_actor(
|
|
2965
|
+
self, spawn_actor_request: "SpawnActorRequest"
|
|
2966
|
+
) -> "SpawnActorResponse":
|
|
2967
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
2968
|
+
|
|
2969
|
+
async def spawn_actors(
|
|
2970
|
+
self, spawn_actors_request: "SpawnActorsRequest"
|
|
2971
|
+
) -> "SpawnActorsResponse":
|
|
2972
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
2973
|
+
|
|
2974
|
+
async def get_actor(
|
|
2975
|
+
self, get_actor_request: "GetActorRequest"
|
|
2976
|
+
) -> "GetActorResponse":
|
|
2977
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
2978
|
+
|
|
2979
|
+
async def list_actors(
|
|
2980
|
+
self, list_actors_request: "ListActorsRequest"
|
|
2981
|
+
) -> "ListActorsResponse":
|
|
2982
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
2983
|
+
|
|
2984
|
+
async def send_message(
|
|
2985
|
+
self, send_message_request: "SendMessageRequest"
|
|
2986
|
+
) -> "SendMessageResponse":
|
|
2987
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
2988
|
+
|
|
2989
|
+
async def stream_messages(
|
|
2990
|
+
self, stream_message_request_iterator: AsyncIterator[StreamMessageRequest]
|
|
2991
|
+
) -> AsyncIterator[StreamMessageResponse]:
|
|
2992
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
2993
|
+
yield StreamMessageResponse()
|
|
2994
|
+
|
|
2995
|
+
async def delete_actor(
|
|
2996
|
+
self, delete_actor_request: "DeleteActorRequest"
|
|
2997
|
+
) -> "__common_v1__.Empty":
|
|
2998
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
2999
|
+
|
|
3000
|
+
async def monitor_actor(
|
|
3001
|
+
self, monitor_actor_request: "MonitorActorRequest"
|
|
3002
|
+
) -> "MonitorActorResponse":
|
|
3003
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3004
|
+
|
|
3005
|
+
async def demonitor_actor(
|
|
3006
|
+
self, demonitor_actor_request: "DemonitorActorRequest"
|
|
3007
|
+
) -> "__common_v1__.Empty":
|
|
3008
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3009
|
+
|
|
3010
|
+
async def link_actor(
|
|
3011
|
+
self, link_actor_request: "LinkActorRequest"
|
|
3012
|
+
) -> "LinkActorResponse":
|
|
3013
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3014
|
+
|
|
3015
|
+
async def unlink_actor(
|
|
3016
|
+
self, unlink_actor_request: "UnlinkActorRequest"
|
|
3017
|
+
) -> "UnlinkActorResponse":
|
|
3018
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3019
|
+
|
|
3020
|
+
async def notify_actor_down(
|
|
3021
|
+
self, actor_down_notification: "ActorDownNotification"
|
|
3022
|
+
) -> "__common_v1__.Empty":
|
|
3023
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3024
|
+
|
|
3025
|
+
async def check_actor_exists(
|
|
3026
|
+
self, check_actor_exists_request: "CheckActorExistsRequest"
|
|
3027
|
+
) -> "CheckActorExistsResponse":
|
|
3028
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3029
|
+
|
|
3030
|
+
async def get_actor_states(
|
|
3031
|
+
self, get_actor_states_request: "GetActorStatesRequest"
|
|
3032
|
+
) -> "GetActorStatesResponse":
|
|
3033
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3034
|
+
|
|
3035
|
+
async def ask_reply(
|
|
3036
|
+
self, ask_reply_request: "AskReplyRequest"
|
|
3037
|
+
) -> "AskReplyResponse":
|
|
3038
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3039
|
+
|
|
3040
|
+
async def create_shard_group(
|
|
3041
|
+
self, create_shard_group_request: "CreateShardGroupRequest"
|
|
3042
|
+
) -> "CreateShardGroupResponse":
|
|
3043
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3044
|
+
|
|
3045
|
+
async def delete_shard_group(
|
|
3046
|
+
self, delete_shard_group_request: "DeleteShardGroupRequest"
|
|
3047
|
+
) -> "__common_v1__.Empty":
|
|
3048
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3049
|
+
|
|
3050
|
+
async def get_shard_group(
|
|
3051
|
+
self, get_shard_group_request: "GetShardGroupRequest"
|
|
3052
|
+
) -> "GetShardGroupResponse":
|
|
3053
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3054
|
+
|
|
3055
|
+
async def list_shard_groups(
|
|
3056
|
+
self, list_shard_groups_request: "ListShardGroupsRequest"
|
|
3057
|
+
) -> "ListShardGroupsResponse":
|
|
3058
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3059
|
+
|
|
3060
|
+
async def scale_shard_group(
|
|
3061
|
+
self, scale_shard_group_request: "ScaleShardGroupRequest"
|
|
3062
|
+
) -> "ScaleShardGroupResponse":
|
|
3063
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3064
|
+
|
|
3065
|
+
async def send_to_shard(
|
|
3066
|
+
self, send_to_shard_request: "SendToShardRequest"
|
|
3067
|
+
) -> "SendToShardResponse":
|
|
3068
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3069
|
+
|
|
3070
|
+
async def broadcast_shard_group(
|
|
3071
|
+
self, broadcast_shard_group_request: "BroadcastShardGroupRequest"
|
|
3072
|
+
) -> "BroadcastShardGroupResponse":
|
|
3073
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3074
|
+
|
|
3075
|
+
async def reduce_shard_group(
|
|
3076
|
+
self, reduce_shard_group_request: "ReduceShardGroupRequest"
|
|
3077
|
+
) -> "ReduceShardGroupResponse":
|
|
3078
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3079
|
+
|
|
3080
|
+
async def all_reduce_shard_group(
|
|
3081
|
+
self, all_reduce_shard_group_request: "AllReduceShardGroupRequest"
|
|
3082
|
+
) -> "AllReduceShardGroupResponse":
|
|
3083
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3084
|
+
|
|
3085
|
+
async def barrier_shard_group(
|
|
3086
|
+
self, barrier_shard_group_request: "BarrierShardGroupRequest"
|
|
3087
|
+
) -> "BarrierShardGroupResponse":
|
|
3088
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3089
|
+
|
|
3090
|
+
async def scatter_gather(
|
|
3091
|
+
self, scatter_gather_request: "ScatterGatherRequest"
|
|
3092
|
+
) -> "ScatterGatherResponse":
|
|
3093
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3094
|
+
|
|
3095
|
+
async def bulk_update_shard_group(
|
|
3096
|
+
self, bulk_update_shard_group_request: "BulkUpdateShardGroupRequest"
|
|
3097
|
+
) -> "BulkUpdateShardGroupResponse":
|
|
3098
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3099
|
+
|
|
3100
|
+
async def map_shard_group(
|
|
3101
|
+
self, map_shard_group_request: "MapShardGroupRequest"
|
|
3102
|
+
) -> "MapShardGroupResponse":
|
|
3103
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3104
|
+
|
|
3105
|
+
async def __rpc_spawn_actor(
|
|
3106
|
+
self, stream: "grpclib.server.Stream[SpawnActorRequest, SpawnActorResponse]"
|
|
3107
|
+
) -> None:
|
|
3108
|
+
request = await stream.recv_message()
|
|
3109
|
+
response = await self.spawn_actor(request)
|
|
3110
|
+
await stream.send_message(response)
|
|
3111
|
+
|
|
3112
|
+
async def __rpc_spawn_actors(
|
|
3113
|
+
self, stream: "grpclib.server.Stream[SpawnActorsRequest, SpawnActorsResponse]"
|
|
3114
|
+
) -> None:
|
|
3115
|
+
request = await stream.recv_message()
|
|
3116
|
+
response = await self.spawn_actors(request)
|
|
3117
|
+
await stream.send_message(response)
|
|
3118
|
+
|
|
3119
|
+
async def __rpc_get_actor(
|
|
3120
|
+
self, stream: "grpclib.server.Stream[GetActorRequest, GetActorResponse]"
|
|
3121
|
+
) -> None:
|
|
3122
|
+
request = await stream.recv_message()
|
|
3123
|
+
response = await self.get_actor(request)
|
|
3124
|
+
await stream.send_message(response)
|
|
3125
|
+
|
|
3126
|
+
async def __rpc_list_actors(
|
|
3127
|
+
self, stream: "grpclib.server.Stream[ListActorsRequest, ListActorsResponse]"
|
|
3128
|
+
) -> None:
|
|
3129
|
+
request = await stream.recv_message()
|
|
3130
|
+
response = await self.list_actors(request)
|
|
3131
|
+
await stream.send_message(response)
|
|
3132
|
+
|
|
3133
|
+
async def __rpc_send_message(
|
|
3134
|
+
self, stream: "grpclib.server.Stream[SendMessageRequest, SendMessageResponse]"
|
|
3135
|
+
) -> None:
|
|
3136
|
+
request = await stream.recv_message()
|
|
3137
|
+
response = await self.send_message(request)
|
|
3138
|
+
await stream.send_message(response)
|
|
3139
|
+
|
|
3140
|
+
async def __rpc_stream_messages(
|
|
3141
|
+
self,
|
|
3142
|
+
stream: "grpclib.server.Stream[StreamMessageRequest, StreamMessageResponse]",
|
|
3143
|
+
) -> None:
|
|
3144
|
+
request = stream.__aiter__()
|
|
3145
|
+
await self._call_rpc_handler_server_stream(
|
|
3146
|
+
self.stream_messages,
|
|
3147
|
+
stream,
|
|
3148
|
+
request,
|
|
3149
|
+
)
|
|
3150
|
+
|
|
3151
|
+
async def __rpc_delete_actor(
|
|
3152
|
+
self, stream: "grpclib.server.Stream[DeleteActorRequest, __common_v1__.Empty]"
|
|
3153
|
+
) -> None:
|
|
3154
|
+
request = await stream.recv_message()
|
|
3155
|
+
response = await self.delete_actor(request)
|
|
3156
|
+
await stream.send_message(response)
|
|
3157
|
+
|
|
3158
|
+
async def __rpc_monitor_actor(
|
|
3159
|
+
self, stream: "grpclib.server.Stream[MonitorActorRequest, MonitorActorResponse]"
|
|
3160
|
+
) -> None:
|
|
3161
|
+
request = await stream.recv_message()
|
|
3162
|
+
response = await self.monitor_actor(request)
|
|
3163
|
+
await stream.send_message(response)
|
|
3164
|
+
|
|
3165
|
+
async def __rpc_demonitor_actor(
|
|
3166
|
+
self,
|
|
3167
|
+
stream: "grpclib.server.Stream[DemonitorActorRequest, __common_v1__.Empty]",
|
|
3168
|
+
) -> None:
|
|
3169
|
+
request = await stream.recv_message()
|
|
3170
|
+
response = await self.demonitor_actor(request)
|
|
3171
|
+
await stream.send_message(response)
|
|
3172
|
+
|
|
3173
|
+
async def __rpc_link_actor(
|
|
3174
|
+
self, stream: "grpclib.server.Stream[LinkActorRequest, LinkActorResponse]"
|
|
3175
|
+
) -> None:
|
|
3176
|
+
request = await stream.recv_message()
|
|
3177
|
+
response = await self.link_actor(request)
|
|
3178
|
+
await stream.send_message(response)
|
|
3179
|
+
|
|
3180
|
+
async def __rpc_unlink_actor(
|
|
3181
|
+
self, stream: "grpclib.server.Stream[UnlinkActorRequest, UnlinkActorResponse]"
|
|
3182
|
+
) -> None:
|
|
3183
|
+
request = await stream.recv_message()
|
|
3184
|
+
response = await self.unlink_actor(request)
|
|
3185
|
+
await stream.send_message(response)
|
|
3186
|
+
|
|
3187
|
+
async def __rpc_notify_actor_down(
|
|
3188
|
+
self,
|
|
3189
|
+
stream: "grpclib.server.Stream[ActorDownNotification, __common_v1__.Empty]",
|
|
3190
|
+
) -> None:
|
|
3191
|
+
request = await stream.recv_message()
|
|
3192
|
+
response = await self.notify_actor_down(request)
|
|
3193
|
+
await stream.send_message(response)
|
|
3194
|
+
|
|
3195
|
+
async def __rpc_check_actor_exists(
|
|
3196
|
+
self,
|
|
3197
|
+
stream: "grpclib.server.Stream[CheckActorExistsRequest, CheckActorExistsResponse]",
|
|
3198
|
+
) -> None:
|
|
3199
|
+
request = await stream.recv_message()
|
|
3200
|
+
response = await self.check_actor_exists(request)
|
|
3201
|
+
await stream.send_message(response)
|
|
3202
|
+
|
|
3203
|
+
async def __rpc_get_actor_states(
|
|
3204
|
+
self,
|
|
3205
|
+
stream: "grpclib.server.Stream[GetActorStatesRequest, GetActorStatesResponse]",
|
|
3206
|
+
) -> None:
|
|
3207
|
+
request = await stream.recv_message()
|
|
3208
|
+
response = await self.get_actor_states(request)
|
|
3209
|
+
await stream.send_message(response)
|
|
3210
|
+
|
|
3211
|
+
async def __rpc_ask_reply(
|
|
3212
|
+
self, stream: "grpclib.server.Stream[AskReplyRequest, AskReplyResponse]"
|
|
3213
|
+
) -> None:
|
|
3214
|
+
request = await stream.recv_message()
|
|
3215
|
+
response = await self.ask_reply(request)
|
|
3216
|
+
await stream.send_message(response)
|
|
3217
|
+
|
|
3218
|
+
async def __rpc_create_shard_group(
|
|
3219
|
+
self,
|
|
3220
|
+
stream: "grpclib.server.Stream[CreateShardGroupRequest, CreateShardGroupResponse]",
|
|
3221
|
+
) -> None:
|
|
3222
|
+
request = await stream.recv_message()
|
|
3223
|
+
response = await self.create_shard_group(request)
|
|
3224
|
+
await stream.send_message(response)
|
|
3225
|
+
|
|
3226
|
+
async def __rpc_delete_shard_group(
|
|
3227
|
+
self,
|
|
3228
|
+
stream: "grpclib.server.Stream[DeleteShardGroupRequest, __common_v1__.Empty]",
|
|
3229
|
+
) -> None:
|
|
3230
|
+
request = await stream.recv_message()
|
|
3231
|
+
response = await self.delete_shard_group(request)
|
|
3232
|
+
await stream.send_message(response)
|
|
3233
|
+
|
|
3234
|
+
async def __rpc_get_shard_group(
|
|
3235
|
+
self,
|
|
3236
|
+
stream: "grpclib.server.Stream[GetShardGroupRequest, GetShardGroupResponse]",
|
|
3237
|
+
) -> None:
|
|
3238
|
+
request = await stream.recv_message()
|
|
3239
|
+
response = await self.get_shard_group(request)
|
|
3240
|
+
await stream.send_message(response)
|
|
3241
|
+
|
|
3242
|
+
async def __rpc_list_shard_groups(
|
|
3243
|
+
self,
|
|
3244
|
+
stream: "grpclib.server.Stream[ListShardGroupsRequest, ListShardGroupsResponse]",
|
|
3245
|
+
) -> None:
|
|
3246
|
+
request = await stream.recv_message()
|
|
3247
|
+
response = await self.list_shard_groups(request)
|
|
3248
|
+
await stream.send_message(response)
|
|
3249
|
+
|
|
3250
|
+
async def __rpc_scale_shard_group(
|
|
3251
|
+
self,
|
|
3252
|
+
stream: "grpclib.server.Stream[ScaleShardGroupRequest, ScaleShardGroupResponse]",
|
|
3253
|
+
) -> None:
|
|
3254
|
+
request = await stream.recv_message()
|
|
3255
|
+
response = await self.scale_shard_group(request)
|
|
3256
|
+
await stream.send_message(response)
|
|
3257
|
+
|
|
3258
|
+
async def __rpc_send_to_shard(
|
|
3259
|
+
self, stream: "grpclib.server.Stream[SendToShardRequest, SendToShardResponse]"
|
|
3260
|
+
) -> None:
|
|
3261
|
+
request = await stream.recv_message()
|
|
3262
|
+
response = await self.send_to_shard(request)
|
|
3263
|
+
await stream.send_message(response)
|
|
3264
|
+
|
|
3265
|
+
async def __rpc_broadcast_shard_group(
|
|
3266
|
+
self,
|
|
3267
|
+
stream: "grpclib.server.Stream[BroadcastShardGroupRequest, BroadcastShardGroupResponse]",
|
|
3268
|
+
) -> None:
|
|
3269
|
+
request = await stream.recv_message()
|
|
3270
|
+
response = await self.broadcast_shard_group(request)
|
|
3271
|
+
await stream.send_message(response)
|
|
3272
|
+
|
|
3273
|
+
async def __rpc_reduce_shard_group(
|
|
3274
|
+
self,
|
|
3275
|
+
stream: "grpclib.server.Stream[ReduceShardGroupRequest, ReduceShardGroupResponse]",
|
|
3276
|
+
) -> None:
|
|
3277
|
+
request = await stream.recv_message()
|
|
3278
|
+
response = await self.reduce_shard_group(request)
|
|
3279
|
+
await stream.send_message(response)
|
|
3280
|
+
|
|
3281
|
+
async def __rpc_all_reduce_shard_group(
|
|
3282
|
+
self,
|
|
3283
|
+
stream: "grpclib.server.Stream[AllReduceShardGroupRequest, AllReduceShardGroupResponse]",
|
|
3284
|
+
) -> None:
|
|
3285
|
+
request = await stream.recv_message()
|
|
3286
|
+
response = await self.all_reduce_shard_group(request)
|
|
3287
|
+
await stream.send_message(response)
|
|
3288
|
+
|
|
3289
|
+
async def __rpc_barrier_shard_group(
|
|
3290
|
+
self,
|
|
3291
|
+
stream: "grpclib.server.Stream[BarrierShardGroupRequest, BarrierShardGroupResponse]",
|
|
3292
|
+
) -> None:
|
|
3293
|
+
request = await stream.recv_message()
|
|
3294
|
+
response = await self.barrier_shard_group(request)
|
|
3295
|
+
await stream.send_message(response)
|
|
3296
|
+
|
|
3297
|
+
async def __rpc_scatter_gather(
|
|
3298
|
+
self,
|
|
3299
|
+
stream: "grpclib.server.Stream[ScatterGatherRequest, ScatterGatherResponse]",
|
|
3300
|
+
) -> None:
|
|
3301
|
+
request = await stream.recv_message()
|
|
3302
|
+
response = await self.scatter_gather(request)
|
|
3303
|
+
await stream.send_message(response)
|
|
3304
|
+
|
|
3305
|
+
async def __rpc_bulk_update_shard_group(
|
|
3306
|
+
self,
|
|
3307
|
+
stream: "grpclib.server.Stream[BulkUpdateShardGroupRequest, BulkUpdateShardGroupResponse]",
|
|
3308
|
+
) -> None:
|
|
3309
|
+
request = await stream.recv_message()
|
|
3310
|
+
response = await self.bulk_update_shard_group(request)
|
|
3311
|
+
await stream.send_message(response)
|
|
3312
|
+
|
|
3313
|
+
async def __rpc_map_shard_group(
|
|
3314
|
+
self,
|
|
3315
|
+
stream: "grpclib.server.Stream[MapShardGroupRequest, MapShardGroupResponse]",
|
|
3316
|
+
) -> None:
|
|
3317
|
+
request = await stream.recv_message()
|
|
3318
|
+
response = await self.map_shard_group(request)
|
|
3319
|
+
await stream.send_message(response)
|
|
3320
|
+
|
|
3321
|
+
def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
|
|
3322
|
+
return {
|
|
3323
|
+
"/plexspaces.actor.v1.ActorService/SpawnActor": grpclib.const.Handler(
|
|
3324
|
+
self.__rpc_spawn_actor,
|
|
3325
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3326
|
+
SpawnActorRequest,
|
|
3327
|
+
SpawnActorResponse,
|
|
3328
|
+
),
|
|
3329
|
+
"/plexspaces.actor.v1.ActorService/SpawnActors": grpclib.const.Handler(
|
|
3330
|
+
self.__rpc_spawn_actors,
|
|
3331
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3332
|
+
SpawnActorsRequest,
|
|
3333
|
+
SpawnActorsResponse,
|
|
3334
|
+
),
|
|
3335
|
+
"/plexspaces.actor.v1.ActorService/GetActor": grpclib.const.Handler(
|
|
3336
|
+
self.__rpc_get_actor,
|
|
3337
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3338
|
+
GetActorRequest,
|
|
3339
|
+
GetActorResponse,
|
|
3340
|
+
),
|
|
3341
|
+
"/plexspaces.actor.v1.ActorService/ListActors": grpclib.const.Handler(
|
|
3342
|
+
self.__rpc_list_actors,
|
|
3343
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3344
|
+
ListActorsRequest,
|
|
3345
|
+
ListActorsResponse,
|
|
3346
|
+
),
|
|
3347
|
+
"/plexspaces.actor.v1.ActorService/SendMessage": grpclib.const.Handler(
|
|
3348
|
+
self.__rpc_send_message,
|
|
3349
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3350
|
+
SendMessageRequest,
|
|
3351
|
+
SendMessageResponse,
|
|
3352
|
+
),
|
|
3353
|
+
"/plexspaces.actor.v1.ActorService/StreamMessages": grpclib.const.Handler(
|
|
3354
|
+
self.__rpc_stream_messages,
|
|
3355
|
+
grpclib.const.Cardinality.STREAM_STREAM,
|
|
3356
|
+
StreamMessageRequest,
|
|
3357
|
+
StreamMessageResponse,
|
|
3358
|
+
),
|
|
3359
|
+
"/plexspaces.actor.v1.ActorService/DeleteActor": grpclib.const.Handler(
|
|
3360
|
+
self.__rpc_delete_actor,
|
|
3361
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3362
|
+
DeleteActorRequest,
|
|
3363
|
+
__common_v1__.Empty,
|
|
3364
|
+
),
|
|
3365
|
+
"/plexspaces.actor.v1.ActorService/MonitorActor": grpclib.const.Handler(
|
|
3366
|
+
self.__rpc_monitor_actor,
|
|
3367
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3368
|
+
MonitorActorRequest,
|
|
3369
|
+
MonitorActorResponse,
|
|
3370
|
+
),
|
|
3371
|
+
"/plexspaces.actor.v1.ActorService/DemonitorActor": grpclib.const.Handler(
|
|
3372
|
+
self.__rpc_demonitor_actor,
|
|
3373
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3374
|
+
DemonitorActorRequest,
|
|
3375
|
+
__common_v1__.Empty,
|
|
3376
|
+
),
|
|
3377
|
+
"/plexspaces.actor.v1.ActorService/LinkActor": grpclib.const.Handler(
|
|
3378
|
+
self.__rpc_link_actor,
|
|
3379
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3380
|
+
LinkActorRequest,
|
|
3381
|
+
LinkActorResponse,
|
|
3382
|
+
),
|
|
3383
|
+
"/plexspaces.actor.v1.ActorService/UnlinkActor": grpclib.const.Handler(
|
|
3384
|
+
self.__rpc_unlink_actor,
|
|
3385
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3386
|
+
UnlinkActorRequest,
|
|
3387
|
+
UnlinkActorResponse,
|
|
3388
|
+
),
|
|
3389
|
+
"/plexspaces.actor.v1.ActorService/NotifyActorDown": grpclib.const.Handler(
|
|
3390
|
+
self.__rpc_notify_actor_down,
|
|
3391
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3392
|
+
ActorDownNotification,
|
|
3393
|
+
__common_v1__.Empty,
|
|
3394
|
+
),
|
|
3395
|
+
"/plexspaces.actor.v1.ActorService/CheckActorExists": grpclib.const.Handler(
|
|
3396
|
+
self.__rpc_check_actor_exists,
|
|
3397
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3398
|
+
CheckActorExistsRequest,
|
|
3399
|
+
CheckActorExistsResponse,
|
|
3400
|
+
),
|
|
3401
|
+
"/plexspaces.actor.v1.ActorService/GetActorStates": grpclib.const.Handler(
|
|
3402
|
+
self.__rpc_get_actor_states,
|
|
3403
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3404
|
+
GetActorStatesRequest,
|
|
3405
|
+
GetActorStatesResponse,
|
|
3406
|
+
),
|
|
3407
|
+
"/plexspaces.actor.v1.ActorService/AskReply": grpclib.const.Handler(
|
|
3408
|
+
self.__rpc_ask_reply,
|
|
3409
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3410
|
+
AskReplyRequest,
|
|
3411
|
+
AskReplyResponse,
|
|
3412
|
+
),
|
|
3413
|
+
"/plexspaces.actor.v1.ActorService/CreateShardGroup": grpclib.const.Handler(
|
|
3414
|
+
self.__rpc_create_shard_group,
|
|
3415
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3416
|
+
CreateShardGroupRequest,
|
|
3417
|
+
CreateShardGroupResponse,
|
|
3418
|
+
),
|
|
3419
|
+
"/plexspaces.actor.v1.ActorService/DeleteShardGroup": grpclib.const.Handler(
|
|
3420
|
+
self.__rpc_delete_shard_group,
|
|
3421
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3422
|
+
DeleteShardGroupRequest,
|
|
3423
|
+
__common_v1__.Empty,
|
|
3424
|
+
),
|
|
3425
|
+
"/plexspaces.actor.v1.ActorService/GetShardGroup": grpclib.const.Handler(
|
|
3426
|
+
self.__rpc_get_shard_group,
|
|
3427
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3428
|
+
GetShardGroupRequest,
|
|
3429
|
+
GetShardGroupResponse,
|
|
3430
|
+
),
|
|
3431
|
+
"/plexspaces.actor.v1.ActorService/ListShardGroups": grpclib.const.Handler(
|
|
3432
|
+
self.__rpc_list_shard_groups,
|
|
3433
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3434
|
+
ListShardGroupsRequest,
|
|
3435
|
+
ListShardGroupsResponse,
|
|
3436
|
+
),
|
|
3437
|
+
"/plexspaces.actor.v1.ActorService/ScaleShardGroup": grpclib.const.Handler(
|
|
3438
|
+
self.__rpc_scale_shard_group,
|
|
3439
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3440
|
+
ScaleShardGroupRequest,
|
|
3441
|
+
ScaleShardGroupResponse,
|
|
3442
|
+
),
|
|
3443
|
+
"/plexspaces.actor.v1.ActorService/SendToShard": grpclib.const.Handler(
|
|
3444
|
+
self.__rpc_send_to_shard,
|
|
3445
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3446
|
+
SendToShardRequest,
|
|
3447
|
+
SendToShardResponse,
|
|
3448
|
+
),
|
|
3449
|
+
"/plexspaces.actor.v1.ActorService/BroadcastShardGroup": grpclib.const.Handler(
|
|
3450
|
+
self.__rpc_broadcast_shard_group,
|
|
3451
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3452
|
+
BroadcastShardGroupRequest,
|
|
3453
|
+
BroadcastShardGroupResponse,
|
|
3454
|
+
),
|
|
3455
|
+
"/plexspaces.actor.v1.ActorService/ReduceShardGroup": grpclib.const.Handler(
|
|
3456
|
+
self.__rpc_reduce_shard_group,
|
|
3457
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3458
|
+
ReduceShardGroupRequest,
|
|
3459
|
+
ReduceShardGroupResponse,
|
|
3460
|
+
),
|
|
3461
|
+
"/plexspaces.actor.v1.ActorService/AllReduceShardGroup": grpclib.const.Handler(
|
|
3462
|
+
self.__rpc_all_reduce_shard_group,
|
|
3463
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3464
|
+
AllReduceShardGroupRequest,
|
|
3465
|
+
AllReduceShardGroupResponse,
|
|
3466
|
+
),
|
|
3467
|
+
"/plexspaces.actor.v1.ActorService/BarrierShardGroup": grpclib.const.Handler(
|
|
3468
|
+
self.__rpc_barrier_shard_group,
|
|
3469
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3470
|
+
BarrierShardGroupRequest,
|
|
3471
|
+
BarrierShardGroupResponse,
|
|
3472
|
+
),
|
|
3473
|
+
"/plexspaces.actor.v1.ActorService/ScatterGather": grpclib.const.Handler(
|
|
3474
|
+
self.__rpc_scatter_gather,
|
|
3475
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3476
|
+
ScatterGatherRequest,
|
|
3477
|
+
ScatterGatherResponse,
|
|
3478
|
+
),
|
|
3479
|
+
"/plexspaces.actor.v1.ActorService/BulkUpdateShardGroup": grpclib.const.Handler(
|
|
3480
|
+
self.__rpc_bulk_update_shard_group,
|
|
3481
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3482
|
+
BulkUpdateShardGroupRequest,
|
|
3483
|
+
BulkUpdateShardGroupResponse,
|
|
3484
|
+
),
|
|
3485
|
+
"/plexspaces.actor.v1.ActorService/MapShardGroup": grpclib.const.Handler(
|
|
3486
|
+
self.__rpc_map_shard_group,
|
|
3487
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3488
|
+
MapShardGroupRequest,
|
|
3489
|
+
MapShardGroupResponse,
|
|
3490
|
+
),
|
|
3491
|
+
}
|
|
3492
|
+
|
|
3493
|
+
|
|
3494
|
+
class LifecycleEventChannelBase(ServiceBase):
|
|
3495
|
+
|
|
3496
|
+
async def subscribe_lifecycle_events(
|
|
3497
|
+
self, lifecycle_event_filter: "LifecycleEventFilter"
|
|
3498
|
+
) -> AsyncIterator[ActorLifecycleEvent]:
|
|
3499
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3500
|
+
yield ActorLifecycleEvent()
|
|
3501
|
+
|
|
3502
|
+
async def publish_lifecycle_event(
|
|
3503
|
+
self, actor_lifecycle_event: "ActorLifecycleEvent"
|
|
3504
|
+
) -> "__common_v1__.Empty":
|
|
3505
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
3506
|
+
|
|
3507
|
+
async def __rpc_subscribe_lifecycle_events(
|
|
3508
|
+
self, stream: "grpclib.server.Stream[LifecycleEventFilter, ActorLifecycleEvent]"
|
|
3509
|
+
) -> None:
|
|
3510
|
+
request = await stream.recv_message()
|
|
3511
|
+
await self._call_rpc_handler_server_stream(
|
|
3512
|
+
self.subscribe_lifecycle_events,
|
|
3513
|
+
stream,
|
|
3514
|
+
request,
|
|
3515
|
+
)
|
|
3516
|
+
|
|
3517
|
+
async def __rpc_publish_lifecycle_event(
|
|
3518
|
+
self, stream: "grpclib.server.Stream[ActorLifecycleEvent, __common_v1__.Empty]"
|
|
3519
|
+
) -> None:
|
|
3520
|
+
request = await stream.recv_message()
|
|
3521
|
+
response = await self.publish_lifecycle_event(request)
|
|
3522
|
+
await stream.send_message(response)
|
|
3523
|
+
|
|
3524
|
+
def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
|
|
3525
|
+
return {
|
|
3526
|
+
"/plexspaces.actor.v1.LifecycleEventChannel/SubscribeLifecycleEvents": grpclib.const.Handler(
|
|
3527
|
+
self.__rpc_subscribe_lifecycle_events,
|
|
3528
|
+
grpclib.const.Cardinality.UNARY_STREAM,
|
|
3529
|
+
LifecycleEventFilter,
|
|
3530
|
+
ActorLifecycleEvent,
|
|
3531
|
+
),
|
|
3532
|
+
"/plexspaces.actor.v1.LifecycleEventChannel/PublishLifecycleEvent": grpclib.const.Handler(
|
|
3533
|
+
self.__rpc_publish_lifecycle_event,
|
|
3534
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
3535
|
+
ActorLifecycleEvent,
|
|
3536
|
+
__common_v1__.Empty,
|
|
3537
|
+
),
|
|
3538
|
+
}
|