vortexpy 4.0.23__tar.gz → 4.0.25__tar.gz

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.
Files changed (92) hide show
  1. {vortexpy-4.0.23/vortexpy.egg-info → vortexpy-4.0.25}/PKG-INFO +3 -2
  2. {vortexpy-4.0.23 → vortexpy-4.0.25}/pyproject.toml +1 -1
  3. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexServerWebsocket.py +45 -0
  4. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/__init__.py +1 -1
  5. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleDataObservableCache.py +21 -18
  6. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleDataObservableHandler.py +15 -6
  7. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleDataObservableProxyHandler.py +11 -5
  8. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleDataObserverClient.py +5 -4
  9. {vortexpy-4.0.23 → vortexpy-4.0.25/vortexpy.egg-info}/PKG-INFO +3 -2
  10. {vortexpy-4.0.23 → vortexpy-4.0.25}/LICENSE +0 -0
  11. {vortexpy-4.0.23 → vortexpy-4.0.25}/README.md +0 -0
  12. {vortexpy-4.0.23 → vortexpy-4.0.25}/setup.cfg +0 -0
  13. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/DataWrapTuple.py +0 -0
  14. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/DeferUtil.py +0 -0
  15. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/Jsonable.py +0 -0
  16. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/Payload.py +0 -0
  17. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadEndpoint.py +0 -0
  18. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadEndpointTest.py +0 -0
  19. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadEnvelope.py +0 -0
  20. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadFilterKeys.py +0 -0
  21. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadIO.py +0 -0
  22. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadPriority.py +0 -0
  23. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadResponse.py +0 -0
  24. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadResponseTest.py +0 -0
  25. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PayloadTest.py +0 -0
  26. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/PerformTestActionTuple.py +0 -0
  27. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/SerialiseUtil.py +0 -0
  28. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TestTuple.py +0 -0
  29. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/Tuple.py +0 -0
  30. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TupleAction.py +0 -0
  31. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TupleActionVortex.py +0 -0
  32. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TupleDataForTest.py +0 -0
  33. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TuplePerfTest.py +0 -0
  34. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TuplePolymorphicTupleTypeFieldArgTest.py +0 -0
  35. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TupleRestfulTest.py +0 -0
  36. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TupleSelector.py +0 -0
  37. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/TupleTest.py +0 -0
  38. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexABC.py +0 -0
  39. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexClientHttp.py +0 -0
  40. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexClientHttpTest.py +0 -0
  41. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexClientTcp.py +0 -0
  42. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexClientWebsocketFactory.py +0 -0
  43. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexConnectionABC.py +0 -0
  44. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexFactory.py +0 -0
  45. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexPayloadProtocol.py +0 -0
  46. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexServer.py +0 -0
  47. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexServerConnection.py +0 -0
  48. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexServerHttpResource.py +0 -0
  49. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexServerTcp.py +0 -0
  50. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexTcpMemoryLeakPayloadTest.py +0 -0
  51. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexTcpMemoryLeakRawTest.py +0 -0
  52. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexTest.py +0 -0
  53. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexUtil.py +0 -0
  54. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/VortexWritePushProducer.py +0 -0
  55. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/data_loader/TupleDataLiveLockManager.py +0 -0
  56. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/data_loader/TupleDataLoader.py +0 -0
  57. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/data_loader/TupleDataLoaderDelegate.py +0 -0
  58. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/data_loader/TupleDataLoaderTupleABC.py +0 -0
  59. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/data_loader/TupleDataLoaderTuples.py +0 -0
  60. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/data_loader/__init__.py +0 -0
  61. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/event_bus/TupleChangeEventABC.py +0 -0
  62. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/event_bus/TupleChangeEventBus.py +0 -0
  63. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/event_bus/TupleChangeEventBusObserverABC.py +0 -0
  64. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/event_bus/__init__.py +0 -0
  65. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleActionProcessor.py +0 -0
  66. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleActionProcessorProxy.py +0 -0
  67. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleActionProcessorTestHandler.py +0 -0
  68. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleDataActionClient.py +0 -0
  69. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/TupleDataObservableTestHandler.py +0 -0
  70. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/VortexJSTupleLoaderTestHandler.py +0 -0
  71. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/handler/__init__.py +0 -0
  72. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/GzippedDataHttpClient.py +0 -0
  73. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/GzippedDataHttpClientTest.py +0 -0
  74. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/GzippedPayloadHttpClient.py +0 -0
  75. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/RestfulHttpClient.py +0 -0
  76. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/RestfulHttpClientTest.py +0 -0
  77. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/RestfulResource.py +0 -0
  78. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/RestfulResourceTest.py +0 -0
  79. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/restful/__init__.py +0 -0
  80. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/rpc/RPC.py +0 -0
  81. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/rpc/RPCTest.py +0 -0
  82. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/rpc/__init__.py +0 -0
  83. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/sqla_orm/OrmCrudHandler.py +0 -0
  84. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/sqla_orm/TupleProviderForDb.py +0 -0
  85. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/sqla_orm/VortexTupleJson.py +0 -0
  86. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/sqla_orm/__init__.py +0 -0
  87. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/storage/TupleStorageSqlite.py +0 -0
  88. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortex/storage/__init__.py +0 -0
  89. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortexpy.egg-info/SOURCES.txt +0 -0
  90. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortexpy.egg-info/dependency_links.txt +0 -0
  91. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortexpy.egg-info/requires.txt +0 -0
  92. {vortexpy-4.0.23 → vortexpy-4.0.25}/vortexpy.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: vortexpy
3
- Version: 4.0.23
3
+ Version: 4.0.25
4
4
  Summary: Synertys observable, routable, data serialisation and transport code.
5
5
  Author-email: Synerty <contact@synerty.com>
6
6
  License: MIT License
@@ -41,3 +41,4 @@ Requires-Dist: reactivex>=4.0.4
41
41
  Requires-Dist: ddt>=1.6.0
42
42
  Requires-Dist: psutil
43
43
  Requires-Dist: txhttputil>=1.2.0
44
+ Dynamic: license-file
@@ -7,7 +7,7 @@ license-file = "LICENSE"
7
7
 
8
8
  [project]
9
9
  name = "vortexpy"
10
- version = "4.0.23"
10
+ version = "4.0.25"
11
11
  license = {file = "LICENSE"}
12
12
  authors = [{name = "Synerty", email = "contact@synerty.com"}]
13
13
  description = "Synertys observable, routable, data serialisation and transport code."
@@ -7,8 +7,10 @@
7
7
  * Support : support@synerty.com
8
8
  """
9
9
 
10
+ import json
10
11
  import logging
11
12
  from collections import deque
13
+ from datetime import datetime, timezone
12
14
  from random import random
13
15
  from urllib.parse import parse_qs
14
16
  from urllib.parse import urlparse
@@ -226,6 +228,11 @@ class VortexWebSocketUpgradeResource(resource.Resource):
226
228
 
227
229
  If this resource is hit, it will attempt to upgrade the connection to a websocket.
228
230
 
231
+ Plain HTTP GETs without WebSocket upgrade headers are answered with 200 and a
232
+ small JSON body so browser-side reachability probes (vortexjs NetworkStateBrowser
233
+ on /vortexws) can confirm the resource is present. txWS rejects non-upgrade
234
+ requests during an upgrade handshake, which App Proxy surfaces as 502 Bad Gateway.
235
+
229
236
  """
230
237
 
231
238
  isLeaf = 1
@@ -238,9 +245,47 @@ class VortexWebSocketUpgradeResource(resource.Resource):
238
245
  resource.Resource.__init__(self)
239
246
  self._websocketFactory = websocketFactory
240
247
 
248
+ @staticmethod
249
+ def _isWebsocketUpgrade(request) -> bool:
250
+ connection = b"".join(
251
+ request.requestHeaders.getRawHeaders(b"connection", [])
252
+ ).lower()
253
+ upgrade = b"".join(
254
+ request.requestHeaders.getRawHeaders(b"upgrade", [])
255
+ ).lower()
256
+ return b"upgrade" in connection and upgrade == b"websocket"
257
+
258
+ def _renderGet(self, request):
259
+ from vortex.VortexFactory import VortexFactory
260
+
261
+ if not VortexFactory.canConnect(str(request.client.host)):
262
+ request.setResponseCode(503)
263
+ request.setHeader("Retry-After", str(max(10, int(random() * 100))))
264
+ return b"Rejected due to new connections throttling."
265
+
266
+ request.setResponseCode(200)
267
+ request.setHeader(b"Content-Type", b"application/json")
268
+ request.setHeader(b"Cache-Control", b"no-store")
269
+ return json.dumps(
270
+ {
271
+ "success": True,
272
+ "websocket": True,
273
+ "upgradeable": True,
274
+ "date": datetime.now(timezone.utc).isoformat(),
275
+ }
276
+ ).encode("utf-8")
277
+
241
278
  def render(self, request):
242
279
  from vortex.VortexFactory import VortexFactory
243
280
 
281
+ if request.method in (b"GET", b"HEAD") and not self._isWebsocketUpgrade(
282
+ request
283
+ ):
284
+ body = self._renderGet(request)
285
+ if request.method == b"HEAD":
286
+ return b""
287
+ return body
288
+
244
289
  if not VortexFactory.canConnect(str(request.client.host)):
245
290
  request.setResponseCode(503)
246
291
  request.setHeader("Retry-After", str(max(10, int(random() * 100))))
@@ -7,4 +7,4 @@
7
7
  * Support : support@synerty.com
8
8
  """
9
9
 
10
- __version__ = '4.0.23'
10
+ __version__ = '4.0.25'
@@ -109,6 +109,13 @@ class TupleDataObservableCache(metaclass=ABCMeta):
109
109
  def __init__(self) -> None:
110
110
  self.__cache: Dict[str, _CachedSubscribedData] = {}
111
111
 
112
+ def start(self):
113
+
114
+ self.__pollLoopingCall = task.LoopingCall(self.__cacheCheck)
115
+
116
+ d = self.__pollLoopingCall.start(self.__CHECK_PERIOD, now=False)
117
+ d.addErrback(vortexLogFailure, logger, consumeError=True)
118
+
112
119
  def shutdown(self):
113
120
  if not self.__pollLoopingCall:
114
121
  raise Exception("This has already been shutdown")
@@ -122,13 +129,6 @@ class TupleDataObservableCache(metaclass=ABCMeta):
122
129
 
123
130
  self.__cache = {}
124
131
 
125
- def start(self):
126
-
127
- self.__pollLoopingCall = task.LoopingCall(self.__cacheCheck)
128
-
129
- d = self.__pollLoopingCall.start(self.__CHECK_PERIOD, now=False)
130
- d.addErrback(vortexLogFailure, logger, consumeError=True)
131
-
132
132
  def _tupleSelectors(self) -> typing.List[TupleSelector]:
133
133
  tupleSelectors = []
134
134
  for key in self.__cache:
@@ -138,21 +138,24 @@ class TupleDataObservableCache(metaclass=ABCMeta):
138
138
  ## ----- Implement local observable
139
139
 
140
140
  def __cacheCheck(self):
141
- currentVortexUuids = set(VortexFactory.getRemoteVortexUuids())
141
+ try:
142
+ currentVortexUuids = set(VortexFactory.getRemoteVortexUuids())
142
143
 
143
- for ts, cache in list(self.__cache.items()):
144
- cache.vortexUuids = cache.vortexUuids & currentVortexUuids
144
+ for ts, cache in list(self.__cache.items()):
145
+ cache.vortexUuids = cache.vortexUuids & currentVortexUuids
145
146
 
146
- if cache.vortexUuids or cache.subject.observers:
147
- cache.resetTearDown()
147
+ if cache.vortexUuids or cache.subject.observers:
148
+ cache.resetTearDown()
148
149
 
149
- elif cache.isReadyForTearDown():
150
- logger.debug("Cleaning cache for %s", cache.tupleSelector)
151
- self._sendUnsubscribeToServer(cache.tupleSelector)
152
- del self.__cache[ts]
150
+ elif cache.isReadyForTearDown():
151
+ logger.debug("Cleaning cache for %s", cache.tupleSelector)
152
+ self._sendUnsubscribeToServer(cache.tupleSelector)
153
+ del self.__cache[ts]
153
154
 
154
- else:
155
- cache.markForTearDown()
155
+ else:
156
+ cache.markForTearDown()
157
+ except Exception as e:
158
+ logger.error("Looping call __cacheCheck threw exception: %s", e)
156
159
 
157
160
  def _getCache(
158
161
  self, tupleSelector: TupleSelector
@@ -195,6 +195,7 @@ class TupleDataObservableHandler:
195
195
  sendResponse: SendVortexMsgResponseCallable,
196
196
  **kwargs,
197
197
  ):
198
+
198
199
  if not VortexFactory.isVortexUuidOnline(vortexUuid):
199
200
  logger.debug(
200
201
  "Vortex %s is no longer online, skipping reply", vortexUuid
@@ -215,16 +216,24 @@ class TupleDataObservableHandler:
215
216
  # Handle unsubscribe
216
217
  if payloadEnvelope.filt.get("unsubscribe"):
217
218
  if tsStr in self._observerDataByTupleSelector:
218
- try:
219
- self._observerDataByTupleSelector[tsStr].observers.remove(
220
- observerDetails
219
+ observers = self._observerDataByTupleSelector[tsStr].observers
220
+ if observerDetails in observers:
221
+ observers.remove(observerDetails)
222
+ logger.debug(f"Processed unsubscribe for: {tsStr}")
223
+ else:
224
+ logger.debug(
225
+ "Unsubscribe called for missing subscription: %s",
226
+ tsStr,
221
227
  )
222
228
 
223
- except KeyError:
224
- pass
225
-
226
229
  if not self._observerDataByTupleSelector[tsStr].observers:
230
+ logger.debug(f"Last subscription unsubscribed for {tsStr}")
227
231
  del self._observerDataByTupleSelector[tsStr]
232
+ else:
233
+ logger.debug(
234
+ "Unsubscribe called for non-existent tuple selector: %s",
235
+ tsStr,
236
+ )
228
237
 
229
238
  return
230
239
 
@@ -173,10 +173,14 @@ class TupleDataObservableProxyHandler(TupleDataObservableCache):
173
173
  return
174
174
 
175
175
  cache = self._getCache(tupleSelector)
176
- try:
176
+ if vortexUuid in cache.vortexUuids:
177
177
  cache.vortexUuids.remove(vortexUuid)
178
- except KeyError:
179
- pass
178
+ else:
179
+ logger.debug(
180
+ "VortexUuid %s not found in cache for %s",
181
+ vortexUuid,
182
+ tupleSelector.toJsonStr(),
183
+ )
180
184
 
181
185
  def _handleSubscribe(
182
186
  self,
@@ -219,14 +223,16 @@ class TupleDataObservableProxyHandler(TupleDataObservableCache):
219
223
 
220
224
  def _sendRequestToServer(self, payloadEnvelope: PayloadEnvelope):
221
225
  payloadEnvelope.filt["observerName"] = self._observerName
226
+ vortexMsg = payloadEnvelope.toVortexMsg()
222
227
  d = VortexFactory.sendVortexMsg(
223
- vortexMsgs=payloadEnvelope.toVortexMsg(),
228
+ vortexMsgs=vortexMsg,
224
229
  destVortexName=self._proxyToVortexName,
225
230
  )
226
231
  d.addErrback(vortexLogFailure, logger, consumeError=True)
227
232
 
228
233
  def _sendUnsubscribeToServer(self, tupleSelector: TupleSelector):
229
- payloadEnvelope = PayloadEnvelope()
234
+ logger.debug("Sending unsubscribe for: %s", tupleSelector.name)
235
+ payloadEnvelope = PayloadEnvelope(filt=self._filt.copy())
230
236
  payloadEnvelope.filt["tupleSelector"] = tupleSelector
231
237
  payloadEnvelope.filt["unsubscribe"] = True
232
238
  self._sendRequestToServer(payloadEnvelope)
@@ -63,9 +63,9 @@ class TupleDataObserverClient(TupleDataObservableCache):
63
63
  # .subscribe(online= > self.vortexOnlineChanged())
64
64
  #
65
65
  # self.onDestroyEvent.subscribe(() = > isOnlineSub.unsubscribe())
66
- VortexFactory.subscribeToVortexStatusChange(destVortexName).pipe(ops.filter(
67
- lambda online: online is True
68
- )).subscribe(self._vortexOnlineChanged)
66
+ VortexFactory.subscribeToVortexStatusChange(destVortexName).pipe(
67
+ ops.filter(lambda online: online is True)
68
+ ).subscribe(self._vortexOnlineChanged)
69
69
 
70
70
  TupleDataObservableCache.start(self)
71
71
 
@@ -152,7 +152,8 @@ class TupleDataObserverClient(TupleDataObservableCache):
152
152
  d.addErrback(vortexLogFailure, logger, consumeError=True)
153
153
 
154
154
  def _sendUnsubscribeToServer(self, tupleSelector: TupleSelector):
155
- payload = PayloadEnvelope()
155
+ logger.debug("Sending unsubscribe for: %s", tupleSelector.name)
156
+ payload = PayloadEnvelope(self._sendFilt.copy())
156
157
  payload.filt["tupleSelector"] = tupleSelector
157
158
  payload.filt["unsubscribe"] = True
158
159
  self._sendRequestToServer(payload)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: vortexpy
3
- Version: 4.0.23
3
+ Version: 4.0.25
4
4
  Summary: Synertys observable, routable, data serialisation and transport code.
5
5
  Author-email: Synerty <contact@synerty.com>
6
6
  License: MIT License
@@ -41,3 +41,4 @@ Requires-Dist: reactivex>=4.0.4
41
41
  Requires-Dist: ddt>=1.6.0
42
42
  Requires-Dist: psutil
43
43
  Requires-Dist: txhttputil>=1.2.0
44
+ Dynamic: license-file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes