vortexpy 4.0.23__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.
- vortex/DataWrapTuple.py +27 -0
- vortex/DeferUtil.py +224 -0
- vortex/Jsonable.py +304 -0
- vortex/Payload.py +115 -0
- vortex/PayloadEndpoint.py +216 -0
- vortex/PayloadEndpointTest.py +164 -0
- vortex/PayloadEnvelope.py +166 -0
- vortex/PayloadFilterKeys.py +15 -0
- vortex/PayloadIO.py +152 -0
- vortex/PayloadPriority.py +11 -0
- vortex/PayloadResponse.py +173 -0
- vortex/PayloadResponseTest.py +39 -0
- vortex/PayloadTest.py +136 -0
- vortex/PerformTestActionTuple.py +30 -0
- vortex/SerialiseUtil.py +273 -0
- vortex/TestTuple.py +61 -0
- vortex/Tuple.py +968 -0
- vortex/TupleAction.py +72 -0
- vortex/TupleActionVortex.py +5 -0
- vortex/TupleDataForTest.py +25 -0
- vortex/TuplePerfTest.py +71 -0
- vortex/TuplePolymorphicTupleTypeFieldArgTest.py +74 -0
- vortex/TupleRestfulTest.py +140 -0
- vortex/TupleSelector.py +105 -0
- vortex/TupleTest.py +127 -0
- vortex/VortexABC.py +55 -0
- vortex/VortexClientHttp.py +308 -0
- vortex/VortexClientHttpTest.py +71 -0
- vortex/VortexClientTcp.py +355 -0
- vortex/VortexClientWebsocketFactory.py +383 -0
- vortex/VortexConnectionABC.py +88 -0
- vortex/VortexFactory.py +932 -0
- vortex/VortexPayloadProtocol.py +180 -0
- vortex/VortexServer.py +367 -0
- vortex/VortexServerConnection.py +127 -0
- vortex/VortexServerHttpResource.py +193 -0
- vortex/VortexServerTcp.py +104 -0
- vortex/VortexServerWebsocket.py +287 -0
- vortex/VortexTcpMemoryLeakPayloadTest.py +611 -0
- vortex/VortexTcpMemoryLeakRawTest.py +87 -0
- vortex/VortexTest.py +22 -0
- vortex/VortexUtil.py +314 -0
- vortex/VortexWritePushProducer.py +321 -0
- vortex/__init__.py +10 -0
- vortex/data_loader/TupleDataLiveLockManager.py +383 -0
- vortex/data_loader/TupleDataLoader.py +326 -0
- vortex/data_loader/TupleDataLoaderDelegate.py +90 -0
- vortex/data_loader/TupleDataLoaderTupleABC.py +10 -0
- vortex/data_loader/TupleDataLoaderTuples.py +53 -0
- vortex/data_loader/__init__.py +0 -0
- vortex/event_bus/TupleChangeEventABC.py +15 -0
- vortex/event_bus/TupleChangeEventBus.py +192 -0
- vortex/event_bus/TupleChangeEventBusObserverABC.py +11 -0
- vortex/event_bus/__init__.py +0 -0
- vortex/handler/TupleActionProcessor.py +270 -0
- vortex/handler/TupleActionProcessorProxy.py +218 -0
- vortex/handler/TupleActionProcessorTestHandler.py +27 -0
- vortex/handler/TupleDataActionClient.py +67 -0
- vortex/handler/TupleDataObservableCache.py +201 -0
- vortex/handler/TupleDataObservableHandler.py +371 -0
- vortex/handler/TupleDataObservableProxyHandler.py +340 -0
- vortex/handler/TupleDataObservableTestHandler.py +60 -0
- vortex/handler/TupleDataObserverClient.py +158 -0
- vortex/handler/VortexJSTupleLoaderTestHandler.py +42 -0
- vortex/handler/__init__.py +0 -0
- vortex/restful/GzippedDataHttpClient.py +170 -0
- vortex/restful/GzippedDataHttpClientTest.py +103 -0
- vortex/restful/GzippedPayloadHttpClient.py +181 -0
- vortex/restful/RestfulHttpClient.py +107 -0
- vortex/restful/RestfulHttpClientTest.py +60 -0
- vortex/restful/RestfulResource.py +153 -0
- vortex/restful/RestfulResourceTest.py +100 -0
- vortex/restful/__init__.py +0 -0
- vortex/rpc/RPC.py +446 -0
- vortex/rpc/RPCTest.py +12 -0
- vortex/rpc/__init__.py +0 -0
- vortex/sqla_orm/OrmCrudHandler.py +431 -0
- vortex/sqla_orm/TupleProviderForDb.py +42 -0
- vortex/sqla_orm/VortexTupleJson.py +24 -0
- vortex/sqla_orm/__init__.py +0 -0
- vortex/storage/TupleStorageSqlite.py +359 -0
- vortex/storage/__init__.py +0 -0
- vortexpy-4.0.23.dist-info/LICENSE +21 -0
- vortexpy-4.0.23.dist-info/METADATA +43 -0
- vortexpy-4.0.23.dist-info/RECORD +87 -0
- vortexpy-4.0.23.dist-info/WHEEL +5 -0
- vortexpy-4.0.23.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
"""
|
|
2
|
+
* Created by Synerty Pty Ltd
|
|
3
|
+
*
|
|
4
|
+
* This software is open source, the MIT license applies.
|
|
5
|
+
*
|
|
6
|
+
* Website : http://www.synerty.com
|
|
7
|
+
* Support : support@synerty.com
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
import uuid
|
|
12
|
+
from collections import deque, namedtuple
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Union, Optional, List, Deque
|
|
15
|
+
from urllib.parse import urlencode, urlparse, urlunparse
|
|
16
|
+
|
|
17
|
+
import pytz
|
|
18
|
+
import twisted
|
|
19
|
+
from autobahn.twisted.websocket import (
|
|
20
|
+
WebSocketClientProtocol,
|
|
21
|
+
WebSocketClientFactory,
|
|
22
|
+
connectWS,
|
|
23
|
+
)
|
|
24
|
+
from twisted.internet import reactor
|
|
25
|
+
from twisted.internet import task
|
|
26
|
+
from twisted.internet.defer import Deferred, inlineCallbacks
|
|
27
|
+
from twisted.internet.protocol import connectionDone, ReconnectingClientFactory
|
|
28
|
+
|
|
29
|
+
from vortex.DeferUtil import isMainThread, vortexLogFailure, nonConcurrentMethod
|
|
30
|
+
from vortex.PayloadEnvelope import PayloadEnvelope, VortexMsgList
|
|
31
|
+
from vortex.PayloadPriority import DEFAULT_PRIORITY
|
|
32
|
+
from vortex.VortexABC import VortexABC, VortexInfo
|
|
33
|
+
from vortex.VortexPayloadProtocol import VortexPayloadProtocol
|
|
34
|
+
from vortex.VortexServer import HEART_BEAT_PERIOD
|
|
35
|
+
from vortex.VortexServer import HEART_BEAT_TIMEOUT
|
|
36
|
+
from vortex.VortexUtil import logLargeMessages
|
|
37
|
+
|
|
38
|
+
logger = logging.getLogger(name=__name__)
|
|
39
|
+
|
|
40
|
+
VortexMsgToSend = namedtuple("VortexMsgToSend", ["deferred", "vortexMsgs"])
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class VortexPayloadWebsocketClientProtocol(
|
|
44
|
+
WebSocketClientProtocol, VortexPayloadProtocol
|
|
45
|
+
):
|
|
46
|
+
def __init__(self, vortexClient: "VortexClientWebsocketFactory"):
|
|
47
|
+
WebSocketClientProtocol.__init__(self)
|
|
48
|
+
VortexPayloadProtocol.__init__(self, logger)
|
|
49
|
+
self._vortexClient = vortexClient
|
|
50
|
+
|
|
51
|
+
self._vortexClientConnectionMade()
|
|
52
|
+
|
|
53
|
+
def _vortexClientConnectionMade(self):
|
|
54
|
+
self._closed = False
|
|
55
|
+
|
|
56
|
+
# Start our heart beat
|
|
57
|
+
self._sendBeatLoopingCall = task.LoopingCall(self._sendBeat)
|
|
58
|
+
d = self._sendBeatLoopingCall.start(HEART_BEAT_PERIOD, now=False)
|
|
59
|
+
d.addErrback(lambda f: logger.exception(f.value))
|
|
60
|
+
|
|
61
|
+
def onMessage(self, message, isBinary):
|
|
62
|
+
VortexPayloadProtocol.vortexMsgReceived(self, message)
|
|
63
|
+
|
|
64
|
+
def _beat(self):
|
|
65
|
+
if self._vortexClient:
|
|
66
|
+
self._vortexClient._beat()
|
|
67
|
+
|
|
68
|
+
def _nameAndUuidReceived(self, name, uuid):
|
|
69
|
+
from vortex.VortexFactory import VortexFactory
|
|
70
|
+
|
|
71
|
+
# self._producer.setRemoteVortexName(name)
|
|
72
|
+
|
|
73
|
+
if self._vortexClient:
|
|
74
|
+
self._vortexClient._setNameAndUuid(name=name, uuid=uuid)
|
|
75
|
+
|
|
76
|
+
VortexFactory._notifyOfVortexStatusChange(name, online=True)
|
|
77
|
+
|
|
78
|
+
def _createResponseSenderCallable(self):
|
|
79
|
+
def sendResponse(
|
|
80
|
+
vortexMsgs: Union[VortexMsgList, bytes],
|
|
81
|
+
priority: int = DEFAULT_PRIORITY,
|
|
82
|
+
):
|
|
83
|
+
return self._vortexClient.sendVortexMsg(
|
|
84
|
+
vortexMsgs=vortexMsgs, priority=priority
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return sendResponse
|
|
88
|
+
|
|
89
|
+
def _sendBeat(self):
|
|
90
|
+
if self._closed:
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
# Send the heartbeats
|
|
94
|
+
self.sendMessage(b".")
|
|
95
|
+
|
|
96
|
+
def write(self, payloadVortexStr: bytes, _priority: int = DEFAULT_PRIORITY):
|
|
97
|
+
if not twisted.python.threadable.isInIOThread():
|
|
98
|
+
e = Exception("Write called from NON main thread")
|
|
99
|
+
logger.exception(str(e))
|
|
100
|
+
raise e
|
|
101
|
+
|
|
102
|
+
assert not self._closed
|
|
103
|
+
self.sendMessage(payloadVortexStr)
|
|
104
|
+
|
|
105
|
+
def onConnect(self, response):
|
|
106
|
+
logger.info(f"Connected to {response.peer}")
|
|
107
|
+
|
|
108
|
+
self._vortexClientConnectionMade()
|
|
109
|
+
|
|
110
|
+
# Send a heart beat down the new connection, tell it who we are.
|
|
111
|
+
connectPayloadFilt = {
|
|
112
|
+
PayloadEnvelope.vortexUuidKey: self._vortexClient.uuid,
|
|
113
|
+
PayloadEnvelope.vortexNameKey: self._vortexClient.name,
|
|
114
|
+
}
|
|
115
|
+
self.write(PayloadEnvelope(filt=connectPayloadFilt).toVortexMsg())
|
|
116
|
+
|
|
117
|
+
def connectionLost(self, reason=connectionDone):
|
|
118
|
+
from vortex.VortexFactory import VortexFactory
|
|
119
|
+
|
|
120
|
+
VortexFactory._notifyOfVortexStatusChange(
|
|
121
|
+
self._serverVortexName, online=False
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
if self._sendBeatLoopingCall.running:
|
|
125
|
+
self._sendBeatLoopingCall.stop()
|
|
126
|
+
self._closed = True
|
|
127
|
+
|
|
128
|
+
def close(self):
|
|
129
|
+
self.transport.loseConnection()
|
|
130
|
+
if self._sendBeatLoopingCall.running:
|
|
131
|
+
self._sendBeatLoopingCall.stop()
|
|
132
|
+
self._closed = True
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def closed(self) -> bool:
|
|
136
|
+
return self._closed
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class VortexClientWebsocketFactory(
|
|
140
|
+
WebSocketClientFactory, ReconnectingClientFactory, VortexABC
|
|
141
|
+
):
|
|
142
|
+
maxDelay = 1.0
|
|
143
|
+
|
|
144
|
+
def __init__(self, name: str, *args, **kwargs):
|
|
145
|
+
|
|
146
|
+
ReconnectingClientFactory.__init__(self)
|
|
147
|
+
|
|
148
|
+
self._vortexName = name
|
|
149
|
+
self._vortexUuid = str(uuid.uuid4())
|
|
150
|
+
|
|
151
|
+
if "url" in kwargs:
|
|
152
|
+
params = dict(
|
|
153
|
+
vortexName=self._vortexName, vortexUuid=self._vortexUuid
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
url_parts = list(urlparse(kwargs["url"]))
|
|
157
|
+
query = dict(url_parts[4])
|
|
158
|
+
query.update(params)
|
|
159
|
+
|
|
160
|
+
url_parts[4] = urlencode(query)
|
|
161
|
+
url = urlunparse(url_parts)
|
|
162
|
+
kwargs["url"] = url
|
|
163
|
+
|
|
164
|
+
WebSocketClientFactory.__init__(self, *args, **kwargs)
|
|
165
|
+
self.setProtocolOptions(utf8validateIncoming=False)
|
|
166
|
+
|
|
167
|
+
self._server = None
|
|
168
|
+
self._port = None
|
|
169
|
+
|
|
170
|
+
self._retrying = False
|
|
171
|
+
|
|
172
|
+
self._serverVortexName = None
|
|
173
|
+
self._serverVortexUuid = None
|
|
174
|
+
|
|
175
|
+
self._lastBeatReceiveTime = None
|
|
176
|
+
self._lastHeartBeatCheckTime = datetime.now(pytz.utc)
|
|
177
|
+
|
|
178
|
+
# Start our heart beat checker
|
|
179
|
+
self._beatLoopingCall = task.LoopingCall(self._checkBeat)
|
|
180
|
+
|
|
181
|
+
self._reconnectVortexMsgs = [PayloadEnvelope().toVortexMsg()]
|
|
182
|
+
|
|
183
|
+
# Buffer messages while the reconnecting factory is reconnecting
|
|
184
|
+
# but only in that state, if the vortex times out, we errback alll these
|
|
185
|
+
self._pendingMessages: Deque[VortexMsgToSend] = deque()
|
|
186
|
+
|
|
187
|
+
self.__protocol = None
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def name(self):
|
|
191
|
+
return self._vortexName
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def uuid(self):
|
|
195
|
+
return self._vortexUuid
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def requiresBase64Encoding(self) -> bool:
|
|
199
|
+
return False
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def localVortexInfo(self) -> VortexInfo:
|
|
203
|
+
return VortexInfo(name=self._vortexName, uuid=self._vortexUuid)
|
|
204
|
+
|
|
205
|
+
@property
|
|
206
|
+
def remoteVortexInfo(self) -> List[VortexInfo]:
|
|
207
|
+
if not self.__protocol:
|
|
208
|
+
return []
|
|
209
|
+
|
|
210
|
+
if not self._serverVortexUuid:
|
|
211
|
+
return []
|
|
212
|
+
|
|
213
|
+
return [
|
|
214
|
+
VortexInfo(name=self._serverVortexName, uuid=self._serverVortexUuid)
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
def buildProtocol(self, addr) -> VortexPayloadWebsocketClientProtocol:
|
|
218
|
+
logger.debug(f"Building protocol for {addr}")
|
|
219
|
+
self._close()
|
|
220
|
+
|
|
221
|
+
# Reset the times in the ReconnectingClientFactory
|
|
222
|
+
self.resetDelay()
|
|
223
|
+
|
|
224
|
+
self.__protocol = VortexPayloadWebsocketClientProtocol(self)
|
|
225
|
+
self.__protocol.factory = self
|
|
226
|
+
return self.__protocol
|
|
227
|
+
|
|
228
|
+
def clientConnectionLost(self, connector, reason):
|
|
229
|
+
logger.debug("Lost connection, Reason: %s", reason.value)
|
|
230
|
+
logger.info("Lost connection, Trying to reconnect.")
|
|
231
|
+
ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
|
|
232
|
+
|
|
233
|
+
def clientConnectionFailed(self, connector, reason):
|
|
234
|
+
logger.debug("Connection failed. Reason: %s", reason.value)
|
|
235
|
+
logger.info("Connection failed, Trying to reconnect.")
|
|
236
|
+
ReconnectingClientFactory.clientConnectionFailed(
|
|
237
|
+
self, connector, reason
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
@inlineCallbacks
|
|
241
|
+
def connect(self, server, port, sslContextFactory):
|
|
242
|
+
self._server = server
|
|
243
|
+
self._port = port
|
|
244
|
+
self._sslContextFactory = sslContextFactory
|
|
245
|
+
|
|
246
|
+
self._beat()
|
|
247
|
+
d = self._beatLoopingCall.start(HEART_BEAT_PERIOD, now=False)
|
|
248
|
+
d.addErrback(vortexLogFailure, logger, consumeError=True)
|
|
249
|
+
deferred = Deferred()
|
|
250
|
+
|
|
251
|
+
yield connectWS(self, sslContextFactory)
|
|
252
|
+
|
|
253
|
+
def checkUuid():
|
|
254
|
+
if self._serverVortexName:
|
|
255
|
+
deferred.callback(True)
|
|
256
|
+
else:
|
|
257
|
+
reactor.callLater(0.1, checkUuid)
|
|
258
|
+
|
|
259
|
+
checkUuid()
|
|
260
|
+
|
|
261
|
+
return (yield deferred)
|
|
262
|
+
|
|
263
|
+
def close(self):
|
|
264
|
+
if self._beatLoopingCall and self._beatLoopingCall.running:
|
|
265
|
+
self._beatLoopingCall.stop()
|
|
266
|
+
self._beatLoopingCall = None
|
|
267
|
+
|
|
268
|
+
# Stop the ReconnectingClientFactory from trying to reconnect
|
|
269
|
+
self.stopTrying()
|
|
270
|
+
self._close()
|
|
271
|
+
|
|
272
|
+
def addReconnectVortexMsg(self, vortexMsg: bytes):
|
|
273
|
+
"""Add Reconnect Payload
|
|
274
|
+
|
|
275
|
+
:param vortexMsg: An encoded PayloadEnvelope to send when the connection reconnects
|
|
276
|
+
:return:
|
|
277
|
+
"""
|
|
278
|
+
self._reconnectVortexMsgs.append(vortexMsg)
|
|
279
|
+
|
|
280
|
+
def sendVortexMsg(
|
|
281
|
+
self,
|
|
282
|
+
vortexMsgs: Union[VortexMsgList, bytes, None] = None,
|
|
283
|
+
vortexUuid: Optional[str] = None,
|
|
284
|
+
priority: int = DEFAULT_PRIORITY,
|
|
285
|
+
) -> Deferred:
|
|
286
|
+
"""Send Vortex Msg
|
|
287
|
+
|
|
288
|
+
NOTE: Priority ins't supported as there is no buffer for this class.
|
|
289
|
+
|
|
290
|
+
"""
|
|
291
|
+
if not self.__protocol:
|
|
292
|
+
from vortex.VortexFactory import NoVortexException
|
|
293
|
+
|
|
294
|
+
raise NoVortexException("The vortex is not yet connected")
|
|
295
|
+
|
|
296
|
+
if vortexMsgs is None:
|
|
297
|
+
vortexMsgs = self._reconnectVortexMsgs
|
|
298
|
+
|
|
299
|
+
if not isinstance(vortexMsgs, list):
|
|
300
|
+
vortexMsgs = [vortexMsgs]
|
|
301
|
+
|
|
302
|
+
logLargeMessages(logger, vortexMsgs, self._serverVortexUuid)
|
|
303
|
+
|
|
304
|
+
if isMainThread():
|
|
305
|
+
return self._sendVortexMsgLater(vortexMsgs)
|
|
306
|
+
|
|
307
|
+
return task.deferLater(reactor, 0, self._sendVortexMsgLater, vortexMsgs)
|
|
308
|
+
|
|
309
|
+
@inlineCallbacks
|
|
310
|
+
def _sendVortexMsgLater(self, vortexMsgs: VortexMsgList):
|
|
311
|
+
yield None
|
|
312
|
+
|
|
313
|
+
if not self.__protocol:
|
|
314
|
+
from vortex.VortexFactory import NoVortexException
|
|
315
|
+
|
|
316
|
+
raise NoVortexException("The vortex is not yet connected")
|
|
317
|
+
|
|
318
|
+
assert self._server
|
|
319
|
+
assert vortexMsgs
|
|
320
|
+
|
|
321
|
+
# If this transport requires base64 encoding
|
|
322
|
+
if self.requiresBase64Encoding:
|
|
323
|
+
for index, vortexMsg in enumerate(vortexMsgs):
|
|
324
|
+
if vortexMsg.startswith(b"{"):
|
|
325
|
+
vortexMsg = yield PayloadEnvelope.base64EncodeDefer(
|
|
326
|
+
vortexMsg
|
|
327
|
+
)
|
|
328
|
+
vortexMsgs[index] = vortexMsg + b"."
|
|
329
|
+
|
|
330
|
+
for vortexMsg in vortexMsgs:
|
|
331
|
+
self.__protocol.write(vortexMsg)
|
|
332
|
+
|
|
333
|
+
return True
|
|
334
|
+
|
|
335
|
+
def _beat(self):
|
|
336
|
+
"""Beat, Called by protocol"""
|
|
337
|
+
self._lastBeatReceiveTime = datetime.now(pytz.utc)
|
|
338
|
+
|
|
339
|
+
def _setNameAndUuid(self, name, uuid):
|
|
340
|
+
"""Set Name And Uuid, Called by protocol"""
|
|
341
|
+
self._serverVortexName = name
|
|
342
|
+
self._serverVortexUuid = uuid
|
|
343
|
+
|
|
344
|
+
def _checkBeat(self):
|
|
345
|
+
# If we've been asleep, then make note of that (VM suspended)
|
|
346
|
+
checkTimout = (
|
|
347
|
+
datetime.now(pytz.utc) - self._lastHeartBeatCheckTime
|
|
348
|
+
).seconds > HEART_BEAT_TIMEOUT
|
|
349
|
+
|
|
350
|
+
# Has the heart beat expired?
|
|
351
|
+
beatTimeout = (
|
|
352
|
+
datetime.now(pytz.utc) - self._lastBeatReceiveTime
|
|
353
|
+
).seconds > HEART_BEAT_TIMEOUT
|
|
354
|
+
|
|
355
|
+
# Mark that we've just checked it
|
|
356
|
+
self._lastHeartBeatCheckTime = datetime.now(pytz.utc)
|
|
357
|
+
|
|
358
|
+
if checkTimout:
|
|
359
|
+
self._lastBeatReceiveTime = datetime.now(pytz.utc)
|
|
360
|
+
return
|
|
361
|
+
|
|
362
|
+
if beatTimeout:
|
|
363
|
+
self._reconnectAfterHeartBeatLost()
|
|
364
|
+
return
|
|
365
|
+
|
|
366
|
+
def _reconnectAfterHeartBeatLost(self):
|
|
367
|
+
if self._retrying:
|
|
368
|
+
return
|
|
369
|
+
|
|
370
|
+
self._retrying = True
|
|
371
|
+
|
|
372
|
+
logger.info(
|
|
373
|
+
"VortexServer client dead, reconnecting %s:%s",
|
|
374
|
+
self._server,
|
|
375
|
+
self._port,
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
self._close()
|
|
379
|
+
|
|
380
|
+
def _close(self):
|
|
381
|
+
if self.__protocol:
|
|
382
|
+
self.__protocol.close()
|
|
383
|
+
self.__protocol = None
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
* Created by Synerty Pty Ltd
|
|
3
|
+
*
|
|
4
|
+
* This software is open source, the MIT license applies.
|
|
5
|
+
*
|
|
6
|
+
* Website : http://www.synerty.com
|
|
7
|
+
* Support : support@synerty.com
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from abc import ABCMeta, abstractmethod
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
|
|
14
|
+
import pytz
|
|
15
|
+
|
|
16
|
+
from .PayloadPriority import DEFAULT_PRIORITY
|
|
17
|
+
from .VortexServer import VortexServer
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(name=__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class VortexConnectionABC(metaclass=ABCMeta):
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
logger,
|
|
26
|
+
vortexServer: VortexServer,
|
|
27
|
+
remoteVortexUuid: str,
|
|
28
|
+
remoteVortexName: str,
|
|
29
|
+
httpSessionUuid=None,
|
|
30
|
+
) -> None:
|
|
31
|
+
self._vortexServer = vortexServer
|
|
32
|
+
self._logger = logger
|
|
33
|
+
self._remoteVortexUuid = remoteVortexUuid
|
|
34
|
+
self._remoteVortexName = remoteVortexName
|
|
35
|
+
self._closed = False
|
|
36
|
+
self._timedOut = False
|
|
37
|
+
self._httpSessionUuid = httpSessionUuid
|
|
38
|
+
self._connectDateTime = datetime.now(pytz.UTC)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def closed(self) -> bool:
|
|
42
|
+
return self._closed
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def timedOut(self) -> bool:
|
|
46
|
+
return self._timedOut
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def connectDateTime(self) -> datetime:
|
|
50
|
+
return self._connectDateTime
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def httpSessionUuid(self):
|
|
54
|
+
return self._httpSessionUuid
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def remoteVortexUuid(self):
|
|
58
|
+
"""Vortex UUID
|
|
59
|
+
|
|
60
|
+
The vortex UUID of the remote vortex which this connection represents.
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
return self._remoteVortexUuid
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def remoteVortexName(self):
|
|
67
|
+
"""Vortex Name
|
|
68
|
+
|
|
69
|
+
The name of the remote vortex which this connection represents.
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
return self._remoteVortexName
|
|
73
|
+
|
|
74
|
+
@abstractmethod
|
|
75
|
+
def write(self, payloadVortexStr: bytes, priority: int = DEFAULT_PRIORITY):
|
|
76
|
+
"""Write
|
|
77
|
+
|
|
78
|
+
EG
|
|
79
|
+
|
|
80
|
+
> assert not self._closed
|
|
81
|
+
> self._request.write(payloadVortexStr)
|
|
82
|
+
> self._request.write('.')
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def close(self):
|
|
87
|
+
self._vortexServer.connectionClosed(self)
|
|
88
|
+
self._closed = True
|