@scrypted/server 0.123.34 → 0.123.35
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.
- package/dist/cluster/cluster-labels.d.ts +5 -0
- package/dist/cluster/cluster-labels.js +15 -5
- package/dist/cluster/cluster-labels.js.map +1 -1
- package/dist/cluster/cluster-setup.js +9 -2
- package/dist/cluster/cluster-setup.js.map +1 -1
- package/dist/plugin/plugin-host.js +2 -1
- package/dist/plugin/plugin-host.js.map +1 -1
- package/dist/plugin/plugin-remote-worker.js +2 -2
- package/dist/plugin/plugin-remote-worker.js.map +1 -1
- package/dist/scrypted-cluster-main.d.ts +4 -1
- package/dist/scrypted-cluster-main.js +94 -77
- package/dist/scrypted-cluster-main.js.map +1 -1
- package/dist/scrypted-server-main.js +6 -6
- package/dist/scrypted-server-main.js.map +1 -1
- package/dist/services/cluster-fork.js +19 -9
- package/dist/services/cluster-fork.js.map +1 -1
- package/package.json +1 -1
- package/python/cluster_labels.py +4 -1
- package/python/cluster_setup.py +16 -7
- package/python/plugin_console.py +1 -0
- package/python/plugin_pip.py +14 -8
- package/python/plugin_remote.py +120 -38
- package/python/plugin_repl.py +42 -15
- package/python/plugin_volume.py +17 -11
- package/python/rpc-iterator-test.py +11 -8
- package/python/rpc.py +242 -154
- package/python/rpc_reader.py +35 -28
- package/src/cluster/cluster-labels.ts +16 -5
- package/src/cluster/cluster-setup.ts +9 -2
- package/src/plugin/plugin-host.ts +4 -2
- package/src/plugin/plugin-remote-worker.ts +4 -5
- package/src/scrypted-cluster-main.ts +110 -89
- package/src/scrypted-server-main.ts +9 -8
- package/src/services/cluster-fork.ts +25 -11
package/python/rpc.py
CHANGED
@@ -16,7 +16,7 @@ jsonSerializable.add(list)
|
|
16
16
|
|
17
17
|
|
18
18
|
async def maybe_await(value):
|
19
|
-
if
|
19
|
+
if inspect.isawaitable(value):
|
20
20
|
return await value
|
21
21
|
return value
|
22
22
|
|
@@ -58,69 +58,112 @@ class LocalProxiedEntry(TypedDict):
|
|
58
58
|
|
59
59
|
|
60
60
|
class RpcProxy(object):
|
61
|
-
def __init__(
|
62
|
-
self
|
63
|
-
|
64
|
-
|
61
|
+
def __init__(
|
62
|
+
self,
|
63
|
+
peer,
|
64
|
+
entry: LocalProxiedEntry,
|
65
|
+
proxyConstructorName: str,
|
66
|
+
proxyProps: any,
|
67
|
+
proxyOneWayMethods: List[str],
|
68
|
+
):
|
69
|
+
self.__dict__["__proxy_id"] = entry["id"]
|
70
|
+
self.__dict__["__proxy_entry"] = entry
|
71
|
+
self.__dict__["__proxy_constructor"] = proxyConstructorName
|
65
72
|
self.__dict__[RpcPeer.PROPERTY_PROXY_PEER] = peer
|
66
73
|
self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES] = proxyProps
|
67
|
-
self.__dict__[
|
74
|
+
self.__dict__["__proxy_oneway_methods"] = proxyOneWayMethods
|
68
75
|
|
69
76
|
def __aiter__(self):
|
70
|
-
if
|
77
|
+
if (
|
78
|
+
self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
79
|
+
and "Symbol(Symbol.asyncIterator)"
|
80
|
+
in self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
81
|
+
):
|
71
82
|
return self
|
72
|
-
raise Exception(
|
83
|
+
raise Exception("RpcProxy is not an async iterable")
|
73
84
|
|
74
85
|
async def __anext__(self):
|
75
|
-
if
|
86
|
+
if (
|
87
|
+
self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
88
|
+
and "Symbol(Symbol.asyncIterator)"
|
89
|
+
in self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
90
|
+
):
|
76
91
|
try:
|
77
|
-
return await RpcProxyMethod(
|
92
|
+
return await RpcProxyMethod(
|
93
|
+
self,
|
94
|
+
self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES][
|
95
|
+
"Symbol(Symbol.asyncIterator)"
|
96
|
+
]["next"],
|
97
|
+
)()
|
78
98
|
except RPCResultError as e:
|
79
|
-
if e.name ==
|
99
|
+
if e.name == "StopAsyncIteration":
|
80
100
|
raise StopAsyncIteration()
|
81
101
|
raise
|
82
|
-
raise Exception(
|
102
|
+
raise Exception("RpcProxy is not an async iterable")
|
83
103
|
|
84
104
|
async def aclose(self):
|
85
|
-
if
|
105
|
+
if (
|
106
|
+
self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
107
|
+
and "Symbol(Symbol.asyncIterator)"
|
108
|
+
in self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
109
|
+
):
|
86
110
|
try:
|
87
|
-
return await RpcProxyMethod(
|
111
|
+
return await RpcProxyMethod(
|
112
|
+
self,
|
113
|
+
self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES][
|
114
|
+
"Symbol(Symbol.asyncIterator)"
|
115
|
+
]["return"],
|
116
|
+
)()
|
88
117
|
except Exception:
|
89
118
|
return
|
90
|
-
raise Exception(
|
119
|
+
raise Exception("RpcProxy is not an async iterable")
|
91
120
|
|
92
121
|
def __getattr__(self, name):
|
93
|
-
if name ==
|
94
|
-
return self.dict[
|
122
|
+
if name == "__proxy_finalizer_id":
|
123
|
+
return self.dict["__proxy_entry"]["finalizerId"]
|
95
124
|
if name in self.__dict__:
|
96
125
|
return self.__dict__[name]
|
97
|
-
if
|
126
|
+
if (
|
127
|
+
self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
128
|
+
and name in self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES]
|
129
|
+
):
|
98
130
|
return self.__dict__[RpcPeer.PROPERTY_PROXY_PROPERTIES][name]
|
99
131
|
return RpcProxyMethod(self, name)
|
100
132
|
|
101
133
|
def __setattr__(self, name: str, value: Any) -> None:
|
102
|
-
if name ==
|
103
|
-
self.__dict__[
|
134
|
+
if name == "__proxy_finalizer_id":
|
135
|
+
self.__dict__["__proxy_entry"]["finalizerId"] = value
|
104
136
|
|
105
137
|
return super().__setattr__(name, value)
|
106
138
|
|
107
139
|
def __call__(self, *args, **kwargs):
|
108
|
-
return self.__dict__[RpcPeer.PROPERTY_PROXY_PEER].__apply__(
|
109
|
-
|
140
|
+
return self.__dict__[RpcPeer.PROPERTY_PROXY_PEER].__apply__(
|
141
|
+
self.__dict__["__proxy_id"],
|
142
|
+
self.__dict__["__proxy_oneway_methods"],
|
143
|
+
None,
|
144
|
+
args,
|
145
|
+
)
|
110
146
|
|
111
147
|
def __apply__(self, method: str, args: list):
|
112
|
-
return self.__dict__[RpcPeer.PROPERTY_PROXY_PEER].__apply__(
|
148
|
+
return self.__dict__[RpcPeer.PROPERTY_PROXY_PEER].__apply__(
|
149
|
+
self.__dict__["__proxy_id"],
|
150
|
+
self.__dict__["__proxy_oneway_methods"],
|
151
|
+
method,
|
152
|
+
args,
|
153
|
+
)
|
113
154
|
|
114
155
|
|
115
156
|
class RpcPeer:
|
116
|
-
RPC_RESULT_ERROR_NAME =
|
117
|
-
PROPERTY_PROXY_PROPERTIES =
|
118
|
-
PROPERTY_JSON_COPY_SERIALIZE_CHILDREN =
|
119
|
-
PROPERTY_PROXY_PEER =
|
120
|
-
|
121
|
-
def __init__(
|
157
|
+
RPC_RESULT_ERROR_NAME = "RPCResultError"
|
158
|
+
PROPERTY_PROXY_PROPERTIES = "__proxy_props"
|
159
|
+
PROPERTY_JSON_COPY_SERIALIZE_CHILDREN = "__json_copy_serialize_children"
|
160
|
+
PROPERTY_PROXY_PEER = "__proxy_peer"
|
161
|
+
|
162
|
+
def __init__(
|
163
|
+
self, send: Callable[[object, Callable[[Exception], None], Dict], None]
|
164
|
+
) -> None:
|
122
165
|
self.send = send
|
123
|
-
self.peerName =
|
166
|
+
self.peerName = "Unnamed Peer"
|
124
167
|
self.params: Mapping[str, any] = {}
|
125
168
|
self.localProxied: Mapping[any, LocalProxiedEntry] = {}
|
126
169
|
self.localProxyMap: Mapping[str, any] = {}
|
@@ -132,7 +175,9 @@ class RpcPeer:
|
|
132
175
|
self.killed = False
|
133
176
|
self.tags = {}
|
134
177
|
|
135
|
-
def __apply__(
|
178
|
+
def __apply__(
|
179
|
+
self, proxyId: str, oneWayMethods: List[str], method: str, args: list
|
180
|
+
):
|
136
181
|
oneway = oneWayMethods and method in oneWayMethods
|
137
182
|
|
138
183
|
if self.killed:
|
@@ -140,7 +185,9 @@ class RpcPeer:
|
|
140
185
|
if oneway:
|
141
186
|
future.set_result(None)
|
142
187
|
return future
|
143
|
-
future.set_exception(
|
188
|
+
future.set_exception(
|
189
|
+
RPCResultError(None, "RpcPeer has been killed (apply) " + str(method))
|
190
|
+
)
|
144
191
|
return future
|
145
192
|
|
146
193
|
serializationContext: Dict = {}
|
@@ -149,23 +196,24 @@ class RpcPeer:
|
|
149
196
|
serializedArgs.append(self.serialize(arg, serializationContext))
|
150
197
|
|
151
198
|
rpcApply = {
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
199
|
+
"type": "apply",
|
200
|
+
"id": None,
|
201
|
+
"proxyId": proxyId,
|
202
|
+
"args": serializedArgs,
|
203
|
+
"method": method,
|
157
204
|
}
|
158
205
|
|
159
206
|
if oneway:
|
160
|
-
rpcApply[
|
207
|
+
rpcApply["oneway"] = True
|
161
208
|
self.send(rpcApply, None, serializationContext)
|
162
209
|
future = Future()
|
163
210
|
future.set_result(None)
|
164
211
|
return future
|
165
212
|
|
166
213
|
async def send(id: str, reject: Callable[[Exception], None]):
|
167
|
-
rpcApply[
|
214
|
+
rpcApply["id"] = id
|
168
215
|
self.send(rpcApply, reject, serializationContext)
|
216
|
+
|
169
217
|
return self.createPendingResult(send)
|
170
218
|
|
171
219
|
def kill(self, message: str = None):
|
@@ -174,7 +222,7 @@ class RpcPeer:
|
|
174
222
|
return
|
175
223
|
self.killed = True
|
176
224
|
|
177
|
-
error = RPCResultError(None, message or
|
225
|
+
error = RPCResultError(None, message or "peer was killed")
|
178
226
|
# this.killedDeferred.reject(error);
|
179
227
|
for str, future in self.pendingResults.items():
|
180
228
|
future.set_exception(error)
|
@@ -187,14 +235,14 @@ class RpcPeer:
|
|
187
235
|
|
188
236
|
def createErrorResult(self, result: Any, e: Exception):
|
189
237
|
s = self.serializeError(e)
|
190
|
-
result[
|
191
|
-
result[
|
238
|
+
result["result"] = s
|
239
|
+
result["throw"] = True
|
192
240
|
return result
|
193
241
|
|
194
242
|
def deserializeError(e: Dict) -> RPCResultError:
|
195
|
-
error = RPCResultError(None, e.get(
|
196
|
-
error.stack = e.get(
|
197
|
-
error.name = e.get(
|
243
|
+
error = RPCResultError(None, e.get("message"))
|
244
|
+
error.stack = e.get("stack")
|
245
|
+
error.name = e.get("name")
|
198
246
|
return error
|
199
247
|
|
200
248
|
def serializeError(self, e: Exception):
|
@@ -203,16 +251,16 @@ class RpcPeer:
|
|
203
251
|
message = str(e)
|
204
252
|
|
205
253
|
serialized = {
|
206
|
-
|
207
|
-
|
208
|
-
|
254
|
+
"stack": tb or "[no stack]",
|
255
|
+
"name": name or "[no name]",
|
256
|
+
"message": message or "[no message]",
|
209
257
|
}
|
210
258
|
|
211
259
|
return {
|
212
|
-
|
213
|
-
|
260
|
+
"__remote_constructor_name": RpcPeer.RPC_RESULT_ERROR_NAME,
|
261
|
+
"__serialized_value": serialized,
|
214
262
|
}
|
215
|
-
|
263
|
+
|
216
264
|
# def getProxyProperties(value):
|
217
265
|
# return getattr(value, RpcPeer.PROPERTY_PROXY_PROPERTIES, None)
|
218
266
|
|
@@ -220,15 +268,15 @@ class RpcPeer:
|
|
220
268
|
# setattr(value, RpcPeer.PROPERTY_PROXY_PROPERTIES, properties)
|
221
269
|
|
222
270
|
def prepareProxyProperties(value):
|
223
|
-
if not hasattr(value,
|
271
|
+
if not hasattr(value, "__aiter__") or not hasattr(value, "__anext__"):
|
224
272
|
return getattr(value, RpcPeer.PROPERTY_PROXY_PROPERTIES, None)
|
225
273
|
|
226
274
|
props = getattr(value, RpcPeer.PROPERTY_PROXY_PROPERTIES, None) or {}
|
227
|
-
if not props.get(
|
228
|
-
props[
|
229
|
-
|
230
|
-
|
231
|
-
|
275
|
+
if not props.get("Symbol(Symbol.asyncIterator)"):
|
276
|
+
props["Symbol(Symbol.asyncIterator)"] = {
|
277
|
+
"next": "__anext__",
|
278
|
+
"throw": "athrow",
|
279
|
+
"return": "aclose",
|
232
280
|
}
|
233
281
|
return props
|
234
282
|
|
@@ -236,34 +284,44 @@ class RpcPeer:
|
|
236
284
|
return not value or (type(value) in jsonSerializable)
|
237
285
|
|
238
286
|
def serialize(self, value, serializationContext: Dict):
|
239
|
-
if type(value) == dict and value.get(
|
287
|
+
if type(value) == dict and value.get(
|
288
|
+
RpcPeer.PROPERTY_JSON_COPY_SERIALIZE_CHILDREN, None
|
289
|
+
):
|
240
290
|
ret = {}
|
241
|
-
for
|
291
|
+
for key, val in value.items():
|
242
292
|
ret[key] = self.serialize(val, serializationContext)
|
243
293
|
return ret
|
244
294
|
|
245
|
-
if
|
295
|
+
if RpcPeer.isTransportSafe(value):
|
246
296
|
return value
|
247
297
|
|
248
|
-
__remote_constructor_name =
|
249
|
-
|
298
|
+
__remote_constructor_name = (
|
299
|
+
"Function"
|
300
|
+
if callable(value)
|
301
|
+
else (
|
302
|
+
value.__proxy_constructor
|
303
|
+
if hasattr(value, "__proxy_constructor")
|
304
|
+
else type(value).__name__
|
305
|
+
)
|
306
|
+
)
|
250
307
|
|
251
308
|
if isinstance(value, Exception):
|
252
309
|
return self.serializeError(value)
|
253
310
|
|
254
|
-
serializerMapName = self.constructorSerializerMap.get(
|
255
|
-
type(value), None)
|
311
|
+
serializerMapName = self.constructorSerializerMap.get(type(value), None)
|
256
312
|
if serializerMapName:
|
257
313
|
__remote_constructor_name = serializerMapName
|
258
314
|
serializer = self.nameDeserializerMap.get(serializerMapName, None)
|
259
315
|
serialized = serializer.serialize(value, serializationContext)
|
260
316
|
ret = {
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
317
|
+
"__remote_proxy_id": None,
|
318
|
+
"__remote_proxy_finalizer_id": None,
|
319
|
+
"__remote_constructor_name": __remote_constructor_name,
|
320
|
+
"__remote_proxy_props": RpcPeer.prepareProxyProperties(value),
|
321
|
+
"__remote_proxy_oneway_methods": getattr(
|
322
|
+
value, "__proxy_oneway_methods", None
|
323
|
+
),
|
324
|
+
"__serialized_value": serialized,
|
267
325
|
}
|
268
326
|
return ret
|
269
327
|
|
@@ -273,26 +331,28 @@ class RpcPeer:
|
|
273
331
|
proxyId, __remote_proxy_props = self.onProxySerialization(value)
|
274
332
|
else:
|
275
333
|
__remote_proxy_props = RpcPeer.prepareProxyProperties(value)
|
276
|
-
proxyId = proxiedEntry[
|
334
|
+
proxyId = proxiedEntry["id"]
|
277
335
|
|
278
|
-
if proxyId != proxiedEntry[
|
279
|
-
raise Exception(
|
336
|
+
if proxyId != proxiedEntry["id"]:
|
337
|
+
raise Exception("onProxySerialization proxy id mismatch")
|
280
338
|
|
281
|
-
proxiedEntry[
|
339
|
+
proxiedEntry["finalizerId"] = RpcPeer.generateId()
|
282
340
|
ret = {
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
341
|
+
"__remote_proxy_id": proxyId,
|
342
|
+
"__remote_proxy_finalizer_id": proxiedEntry["finalizerId"],
|
343
|
+
"__remote_constructor_name": __remote_constructor_name,
|
344
|
+
"__remote_proxy_props": __remote_proxy_props,
|
345
|
+
"__remote_proxy_oneway_methods": getattr(
|
346
|
+
value, "__proxy_oneway_methods", None
|
347
|
+
),
|
288
348
|
}
|
289
349
|
return ret
|
290
350
|
|
291
|
-
__proxy_id = getattr(value,
|
351
|
+
__proxy_id = getattr(value, "__proxy_id", None)
|
292
352
|
__proxy_peer = getattr(value, RpcPeer.PROPERTY_PROXY_PEER, None)
|
293
353
|
if __proxy_id and __proxy_peer == self:
|
294
354
|
ret = {
|
295
|
-
|
355
|
+
"__local_proxy_id": __proxy_id,
|
296
356
|
}
|
297
357
|
return ret
|
298
358
|
|
@@ -303,18 +363,20 @@ class RpcPeer:
|
|
303
363
|
proxyId = RpcPeer.generateId()
|
304
364
|
|
305
365
|
proxiedEntry = {
|
306
|
-
|
307
|
-
|
366
|
+
"id": proxyId,
|
367
|
+
"finalizerId": proxyId,
|
308
368
|
}
|
309
369
|
self.localProxied[value] = proxiedEntry
|
310
370
|
self.localProxyMap[proxyId] = value
|
311
371
|
|
312
372
|
ret = {
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
373
|
+
"__remote_proxy_id": proxyId,
|
374
|
+
"__remote_proxy_finalizer_id": proxyId,
|
375
|
+
"__remote_constructor_name": __remote_constructor_name,
|
376
|
+
"__remote_proxy_props": __remote_proxy_props,
|
377
|
+
"__remote_proxy_oneway_methods": getattr(
|
378
|
+
value, "__proxy_oneway_methods", None
|
379
|
+
),
|
318
380
|
}
|
319
381
|
|
320
382
|
return ret
|
@@ -322,22 +384,33 @@ class RpcPeer:
|
|
322
384
|
def finalize(self, localProxiedEntry: LocalProxiedEntry):
|
323
385
|
if self.killed:
|
324
386
|
return
|
325
|
-
id = localProxiedEntry[
|
387
|
+
id = localProxiedEntry["id"]
|
326
388
|
self.remoteWeakProxies.pop(id, None)
|
327
389
|
rpcFinalize = {
|
328
|
-
|
329
|
-
|
330
|
-
|
390
|
+
"__local_proxy_id": id,
|
391
|
+
"__local_proxy_finalizer_id": localProxiedEntry["finalizerId"],
|
392
|
+
"type": "finalize",
|
331
393
|
}
|
332
394
|
self.send(rpcFinalize)
|
333
395
|
|
334
|
-
def newProxy(
|
396
|
+
def newProxy(
|
397
|
+
self,
|
398
|
+
proxyId: str,
|
399
|
+
proxyConstructorName: str,
|
400
|
+
proxyProps: any,
|
401
|
+
proxyOneWayMethods: List[str],
|
402
|
+
):
|
335
403
|
localProxiedEntry: LocalProxiedEntry = {
|
336
|
-
|
337
|
-
|
404
|
+
"id": proxyId,
|
405
|
+
"finalizerId": None,
|
338
406
|
}
|
339
|
-
proxy = RpcProxy(
|
340
|
-
|
407
|
+
proxy = RpcProxy(
|
408
|
+
self,
|
409
|
+
localProxiedEntry,
|
410
|
+
proxyConstructorName,
|
411
|
+
proxyProps,
|
412
|
+
proxyOneWayMethods,
|
413
|
+
)
|
341
414
|
wr = weakref.ref(proxy)
|
342
415
|
self.remoteWeakProxies[proxyId] = wr
|
343
416
|
weakref.finalize(proxy, lambda: self.finalize(localProxiedEntry))
|
@@ -350,23 +423,22 @@ class RpcPeer:
|
|
350
423
|
if type(value) != dict:
|
351
424
|
return value
|
352
425
|
|
353
|
-
copySerializeChildren = value.get(
|
426
|
+
copySerializeChildren = value.get(
|
427
|
+
RpcPeer.PROPERTY_JSON_COPY_SERIALIZE_CHILDREN, None
|
428
|
+
)
|
354
429
|
if copySerializeChildren:
|
355
430
|
ret = {}
|
356
|
-
for
|
431
|
+
for key, val in value.items():
|
357
432
|
ret[key] = self.deserialize(val, deserializationContext)
|
358
433
|
return ret
|
359
434
|
|
360
|
-
__remote_proxy_id = value.get(
|
361
|
-
__remote_proxy_finalizer_id = value.get(
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
__remote_proxy_props = value.get('__remote_proxy_props', None)
|
368
|
-
__remote_proxy_oneway_methods = value.get(
|
369
|
-
'__remote_proxy_oneway_methods', None)
|
435
|
+
__remote_proxy_id = value.get("__remote_proxy_id", None)
|
436
|
+
__remote_proxy_finalizer_id = value.get("__remote_proxy_finalizer_id", None)
|
437
|
+
__local_proxy_id = value.get("__local_proxy_id", None)
|
438
|
+
__remote_constructor_name = value.get("__remote_constructor_name", None)
|
439
|
+
__serialized_value = value.get("__serialized_value", None)
|
440
|
+
__remote_proxy_props = value.get("__remote_proxy_props", None)
|
441
|
+
__remote_proxy_oneway_methods = value.get("__remote_proxy_oneway_methods", None)
|
370
442
|
|
371
443
|
if __remote_constructor_name == RpcPeer.RPC_RESULT_ERROR_NAME:
|
372
444
|
return RpcPeer.deserializeError(__serialized_value)
|
@@ -375,66 +447,71 @@ class RpcPeer:
|
|
375
447
|
weakref = self.remoteWeakProxies.get(__remote_proxy_id, None)
|
376
448
|
proxy = weakref() if weakref else None
|
377
449
|
if not proxy:
|
378
|
-
proxy = self.newProxy(
|
379
|
-
|
380
|
-
|
450
|
+
proxy = self.newProxy(
|
451
|
+
__remote_proxy_id,
|
452
|
+
__remote_constructor_name,
|
453
|
+
__remote_proxy_props,
|
454
|
+
__remote_proxy_oneway_methods,
|
455
|
+
)
|
456
|
+
setattr(proxy, "__proxy_finalizer_id", __remote_proxy_finalizer_id)
|
381
457
|
return proxy
|
382
458
|
|
383
459
|
if __local_proxy_id:
|
384
460
|
ret = self.localProxyMap.get(__local_proxy_id, None)
|
385
461
|
if not ret:
|
386
462
|
raise RPCResultError(
|
387
|
-
None,
|
463
|
+
None, "invalid local proxy id %s" % __local_proxy_id
|
464
|
+
)
|
388
465
|
return ret
|
389
466
|
|
390
|
-
deserializer = self.nameDeserializerMap.get(
|
391
|
-
__remote_constructor_name, None)
|
467
|
+
deserializer = self.nameDeserializerMap.get(__remote_constructor_name, None)
|
392
468
|
if deserializer:
|
393
469
|
return deserializer.deserialize(__serialized_value, deserializationContext)
|
394
470
|
|
395
471
|
return value
|
396
472
|
|
397
473
|
def sendResult(self, result: Dict, serializationContext: Dict):
|
398
|
-
self.send(
|
474
|
+
self.send(
|
475
|
+
result,
|
476
|
+
lambda e: self.send(self.createErrorResult(result, e, None), None),
|
477
|
+
serializationContext,
|
478
|
+
)
|
399
479
|
|
400
480
|
async def handleMessage(self, message: Dict, deserializationContext: Dict):
|
401
481
|
try:
|
402
|
-
messageType = message[
|
403
|
-
if messageType ==
|
482
|
+
messageType = message["type"]
|
483
|
+
if messageType == "param":
|
404
484
|
result = {
|
405
|
-
|
406
|
-
|
485
|
+
"type": "result",
|
486
|
+
"id": message["id"],
|
407
487
|
}
|
408
488
|
|
409
489
|
serializationContext: Dict = {}
|
410
490
|
try:
|
411
|
-
value = self.params.get(message[
|
491
|
+
value = self.params.get(message["param"], None)
|
412
492
|
value = await maybe_await(value)
|
413
|
-
result[
|
493
|
+
result["result"] = self.serialize(value, serializationContext)
|
414
494
|
except Exception as e:
|
415
495
|
tb = traceback.format_exc()
|
416
|
-
self.createErrorResult(
|
417
|
-
result, type(e).__name, str(e), tb)
|
496
|
+
self.createErrorResult(result, type(e).__name, str(e), tb)
|
418
497
|
|
419
498
|
self.sendResult(result, serializationContext)
|
420
499
|
|
421
|
-
elif messageType ==
|
500
|
+
elif messageType == "apply":
|
422
501
|
result = {
|
423
|
-
|
424
|
-
|
502
|
+
"type": "result",
|
503
|
+
"id": message.get("id", None),
|
425
504
|
}
|
426
|
-
method = message.get(
|
505
|
+
method = message.get("method", None)
|
427
506
|
|
428
507
|
try:
|
429
508
|
serializationContext: Dict = {}
|
430
|
-
target = self.localProxyMap.get(
|
431
|
-
message['proxyId'], None)
|
509
|
+
target = self.localProxyMap.get(message["proxyId"], None)
|
432
510
|
if not target:
|
433
|
-
raise Exception(
|
434
|
-
message['proxyId'])
|
511
|
+
raise Exception("proxy id %s not found" % message["proxyId"])
|
435
512
|
|
436
513
|
args = []
|
437
|
-
for arg in
|
514
|
+
for arg in message["args"] or []:
|
438
515
|
args.append(self.deserialize(arg, deserializationContext))
|
439
516
|
|
440
517
|
# if method == 'asend' and hasattr(target, '__aiter__') and hasattr(target, '__anext__') and not len(args):
|
@@ -444,47 +521,53 @@ class RpcPeer:
|
|
444
521
|
if method:
|
445
522
|
if not hasattr(target, method):
|
446
523
|
raise Exception(
|
447
|
-
|
524
|
+
"target %s does not have method %s"
|
525
|
+
% (type(target), method)
|
526
|
+
)
|
448
527
|
invoke = getattr(target, method)
|
449
528
|
value = await maybe_await(invoke(*args))
|
450
529
|
else:
|
451
530
|
value = await maybe_await(target(*args))
|
452
531
|
|
453
|
-
result[
|
532
|
+
result["result"] = self.serialize(value, serializationContext)
|
454
533
|
except StopAsyncIteration as e:
|
455
534
|
self.createErrorResult(result, e)
|
456
535
|
except Exception as e:
|
457
536
|
self.createErrorResult(result, e)
|
458
537
|
|
459
|
-
if not message.get(
|
538
|
+
if not message.get("oneway", False):
|
460
539
|
self.sendResult(result, serializationContext)
|
461
540
|
|
462
|
-
elif messageType ==
|
463
|
-
id = message[
|
541
|
+
elif messageType == "result":
|
542
|
+
id = message["id"]
|
464
543
|
future = self.pendingResults.get(id, None)
|
465
544
|
if not future:
|
466
|
-
raise RPCResultError(
|
467
|
-
None, 'unknown result %s' % id)
|
545
|
+
raise RPCResultError(None, "unknown result %s" % id)
|
468
546
|
del self.pendingResults[id]
|
469
|
-
deserialized = self.deserialize(
|
470
|
-
|
547
|
+
deserialized = self.deserialize(
|
548
|
+
message.get("result", None), deserializationContext
|
549
|
+
)
|
550
|
+
if message.get("throw"):
|
471
551
|
future.set_exception(deserialized)
|
472
552
|
else:
|
473
553
|
future.set_result(deserialized)
|
474
|
-
elif messageType ==
|
475
|
-
finalizerId = message.get(
|
476
|
-
proxyId = message[
|
554
|
+
elif messageType == "finalize":
|
555
|
+
finalizerId = message.get("__local_proxy_finalizer_id", None)
|
556
|
+
proxyId = message["__local_proxy_id"]
|
477
557
|
local = self.localProxyMap.get(proxyId, None)
|
478
558
|
if local:
|
479
559
|
localProxiedEntry = self.localProxied.get(local)
|
480
|
-
if
|
560
|
+
if (
|
561
|
+
localProxiedEntry
|
562
|
+
and finalizerId
|
563
|
+
and localProxiedEntry["finalizerId"] != finalizerId
|
564
|
+
):
|
481
565
|
# print('mismatch finalizer id', file=sys.stderr)
|
482
566
|
return
|
483
567
|
self.localProxied.pop(local, None)
|
484
568
|
local = self.localProxyMap.pop(proxyId, None)
|
485
569
|
else:
|
486
|
-
raise RPCResultError(
|
487
|
-
None, 'unknown rpc message type %s' % type)
|
570
|
+
raise RPCResultError(None, "unknown rpc message type %s" % type)
|
488
571
|
except Exception as e:
|
489
572
|
print("unhandled rpc error", self.peerName, e)
|
490
573
|
pass
|
@@ -492,12 +575,16 @@ class RpcPeer:
|
|
492
575
|
randomDigits = string.ascii_uppercase + string.ascii_lowercase + string.digits
|
493
576
|
|
494
577
|
def generateId():
|
495
|
-
return
|
578
|
+
return "".join(random.choices(RpcPeer.randomDigits, k=8))
|
496
579
|
|
497
|
-
async def createPendingResult(
|
580
|
+
async def createPendingResult(
|
581
|
+
self, cb: Callable[[str, Callable[[Exception], None]], None]
|
582
|
+
):
|
498
583
|
future = Future()
|
499
584
|
if self.killed:
|
500
|
-
future.set_exception(
|
585
|
+
future.set_exception(
|
586
|
+
RPCResultError(None, "RpcPeer has been killed (createPendingResult)")
|
587
|
+
)
|
501
588
|
return future
|
502
589
|
|
503
590
|
id = RpcPeer.generateId()
|
@@ -508,9 +595,10 @@ class RpcPeer:
|
|
508
595
|
async def getParam(self, param):
|
509
596
|
async def send(id: str, reject: Callable[[Exception], None]):
|
510
597
|
paramMessage = {
|
511
|
-
|
512
|
-
|
513
|
-
|
598
|
+
"id": id,
|
599
|
+
"type": "param",
|
600
|
+
"param": param,
|
514
601
|
}
|
515
602
|
self.send(paramMessage, reject)
|
603
|
+
|
516
604
|
return await self.createPendingResult(send)
|