socketflow 0.2.1__tar.gz → 0.2.3__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.
- {socketflow-0.2.1 → socketflow-0.2.3}/PKG-INFO +1 -1
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/__init__.py +1 -1
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/client_side/client.py +13 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/blueprint.py +16 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/event_loop.py +14 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/transport.py +11 -2
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/server_side/server.py +25 -9
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow.egg-info/PKG-INFO +1 -1
- {socketflow-0.2.1 → socketflow-0.2.3}/README.md +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/setup.cfg +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/setup.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/client_side/__init__.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/__init__.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/compression.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/dispatcher.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/event.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/exceptions.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/logs.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/message_handler.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/message_manager.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/metrics.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/global_side/protocol.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow/server_side/__init__.py +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow.egg-info/SOURCES.txt +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow.egg-info/dependency_links.txt +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow.egg-info/not-zip-safe +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow.egg-info/requires.txt +0 -0
- {socketflow-0.2.1 → socketflow-0.2.3}/socketflow.egg-info/top_level.txt +0 -0
|
@@ -235,6 +235,12 @@ class TcpClientProtocol:
|
|
|
235
235
|
with self._control_lock:
|
|
236
236
|
self.socket.sendall(data)
|
|
237
237
|
|
|
238
|
+
def has_backpressure(self) -> bool:
|
|
239
|
+
"""True when the outbound queue to the server is full."""
|
|
240
|
+
if self._writer is None:
|
|
241
|
+
return False
|
|
242
|
+
return self._writer.has_backpressure()
|
|
243
|
+
|
|
238
244
|
def close(self):
|
|
239
245
|
self._writer.abort()
|
|
240
246
|
|
|
@@ -986,6 +992,13 @@ class TcpClient:
|
|
|
986
992
|
def is_connected(self):
|
|
987
993
|
return self._connected
|
|
988
994
|
|
|
995
|
+
def has_backpressure(self) -> bool:
|
|
996
|
+
"""True when the outbound queue to the server is full."""
|
|
997
|
+
protocol = self._protocol
|
|
998
|
+
if protocol is None:
|
|
999
|
+
return False
|
|
1000
|
+
return protocol.has_backpressure()
|
|
1001
|
+
|
|
989
1002
|
@property
|
|
990
1003
|
def handshake_completed(self):
|
|
991
1004
|
return self._handshake_completed
|
|
@@ -78,6 +78,22 @@ class Blueprint:
|
|
|
78
78
|
"Blueprint not registered with client or server"
|
|
79
79
|
)
|
|
80
80
|
|
|
81
|
+
def has_backpressure(self, client_addr: tuple = None) -> bool:
|
|
82
|
+
"""True when the outbound queue is full.
|
|
83
|
+
|
|
84
|
+
On a server blueprint, client_addr selects the client to check.
|
|
85
|
+
"""
|
|
86
|
+
if hasattr(self, "_client") and self._client:
|
|
87
|
+
return self._client.has_backpressure()
|
|
88
|
+
elif hasattr(self, "_server") and self._server:
|
|
89
|
+
if not client_addr:
|
|
90
|
+
raise ExceptionType.BlueprintError("client_addr parameter is required")
|
|
91
|
+
return self._server.has_backpressure(client_addr)
|
|
92
|
+
else:
|
|
93
|
+
raise ExceptionType.BlueprintError(
|
|
94
|
+
"Blueprint not registered with client or server"
|
|
95
|
+
)
|
|
96
|
+
|
|
81
97
|
def send(
|
|
82
98
|
self,
|
|
83
99
|
data: Any,
|
|
@@ -176,6 +176,12 @@ class EventLoopWriter:
|
|
|
176
176
|
return True
|
|
177
177
|
return self.connection.flush(timeout)
|
|
178
178
|
|
|
179
|
+
def has_backpressure(self) -> bool:
|
|
180
|
+
"""True when the next send would raise Backpressure."""
|
|
181
|
+
if self.connection is None:
|
|
182
|
+
return False
|
|
183
|
+
return self.connection.has_backpressure()
|
|
184
|
+
|
|
179
185
|
def abort(self, timeout=1.0):
|
|
180
186
|
if self.connection is not None:
|
|
181
187
|
self.connection.close()
|
|
@@ -233,6 +239,14 @@ class _SelectorConnection:
|
|
|
233
239
|
with self._lock:
|
|
234
240
|
return self._pending_writes
|
|
235
241
|
|
|
242
|
+
def has_backpressure(self) -> bool:
|
|
243
|
+
"""True when the next send would raise Backpressure."""
|
|
244
|
+
with self._lock:
|
|
245
|
+
return (
|
|
246
|
+
self._pending_writes >= self._max_pending_writes
|
|
247
|
+
or self._queued_bytes >= self._max_queue_bytes
|
|
248
|
+
)
|
|
249
|
+
|
|
236
250
|
def flush(self, timeout: float = 5.0) -> bool:
|
|
237
251
|
"""Wait until the send buffer is empty.
|
|
238
252
|
|
|
@@ -50,7 +50,6 @@ class MemoryBudget:
|
|
|
50
50
|
self._used_bytes = max(0, self._used_bytes - amount)
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
|
|
54
53
|
class TimeoutScheduler:
|
|
55
54
|
"""Run request timeouts from a single shared thread.
|
|
56
55
|
|
|
@@ -217,7 +216,9 @@ class PendingResponseRegistry:
|
|
|
217
216
|
key = self._key(data_id, owner)
|
|
218
217
|
with self._lock:
|
|
219
218
|
if key in self._responses:
|
|
220
|
-
raise ValueError(
|
|
219
|
+
raise ValueError(
|
|
220
|
+
f"A request with data_id {data_id!r} is already pending"
|
|
221
|
+
)
|
|
221
222
|
self._responses[key] = future
|
|
222
223
|
|
|
223
224
|
def pop(self, data_id: str, owner: Any = None) -> Optional[Any]:
|
|
@@ -335,6 +336,14 @@ class SocketWriter:
|
|
|
335
336
|
return False
|
|
336
337
|
time.sleep(0.002)
|
|
337
338
|
|
|
339
|
+
def has_backpressure(self) -> bool:
|
|
340
|
+
"""True when the next send would raise Backpressure."""
|
|
341
|
+
with self._state_lock:
|
|
342
|
+
return (
|
|
343
|
+
self._pending_writes >= self._max_pending_writes
|
|
344
|
+
or self._queued_bytes >= self._max_queue_bytes
|
|
345
|
+
)
|
|
346
|
+
|
|
338
347
|
def _complete(self, payload: bytes):
|
|
339
348
|
with self._state_lock:
|
|
340
349
|
self._queued_bytes -= len(payload)
|
|
@@ -436,6 +436,12 @@ class TcpServerProtocol:
|
|
|
436
436
|
except Exception:
|
|
437
437
|
return False
|
|
438
438
|
|
|
439
|
+
def has_backpressure(self) -> bool:
|
|
440
|
+
"""True when the outbound queue to this client is full."""
|
|
441
|
+
if self._writer is None:
|
|
442
|
+
return False
|
|
443
|
+
return self._writer.has_backpressure()
|
|
444
|
+
|
|
439
445
|
def close(self):
|
|
440
446
|
if self._writer is not None:
|
|
441
447
|
self._writer.abort()
|
|
@@ -815,20 +821,17 @@ class TcpServer:
|
|
|
815
821
|
pass
|
|
816
822
|
|
|
817
823
|
protocol.attach_socket(client_socket)
|
|
818
|
-
try:
|
|
819
|
-
protocol._send_server_ready()
|
|
820
|
-
except Exception:
|
|
821
|
-
protocol.handle_connection_lost()
|
|
822
|
-
return
|
|
823
824
|
with self._clients_lock:
|
|
824
825
|
self._clients[address] = protocol
|
|
825
|
-
|
|
826
826
|
try:
|
|
827
|
+
protocol._send_server_ready()
|
|
827
828
|
if not self.auth_required:
|
|
829
|
+
if self.require_handshake:
|
|
830
|
+
protocol._send_handshake_ok()
|
|
828
831
|
protocol._notify_connected()
|
|
829
832
|
except Exception:
|
|
830
833
|
protocol.handle_connection_lost()
|
|
831
|
-
|
|
834
|
+
return
|
|
832
835
|
|
|
833
836
|
while True:
|
|
834
837
|
try:
|
|
@@ -943,6 +946,10 @@ class TcpServer:
|
|
|
943
946
|
self._clients[address] = protocol
|
|
944
947
|
protocol._event_loop_mode = False
|
|
945
948
|
protocol._send_server_ready()
|
|
949
|
+
if not self.auth_required:
|
|
950
|
+
if self.require_handshake:
|
|
951
|
+
protocol._send_handshake_ok()
|
|
952
|
+
protocol._notify_connected()
|
|
946
953
|
protocol._event_loop_mode = True
|
|
947
954
|
|
|
948
955
|
def on_close():
|
|
@@ -962,8 +969,6 @@ class TcpServer:
|
|
|
962
969
|
memory_budget=self.memory_budget,
|
|
963
970
|
)
|
|
964
971
|
registered = True
|
|
965
|
-
if not self.auth_required and not self.require_handshake:
|
|
966
|
-
protocol._notify_connected()
|
|
967
972
|
except Exception as error:
|
|
968
973
|
if protocol is not None:
|
|
969
974
|
protocol.handle_connection_lost()
|
|
@@ -1432,6 +1437,17 @@ class TcpServer:
|
|
|
1432
1437
|
with self._clients_lock:
|
|
1433
1438
|
return client_addr in self._clients
|
|
1434
1439
|
|
|
1440
|
+
def has_backpressure(self, client_addr) -> bool:
|
|
1441
|
+
"""True when the outbound queue to one client is full.
|
|
1442
|
+
|
|
1443
|
+
Returns False when the client is not connected.
|
|
1444
|
+
"""
|
|
1445
|
+
with self._clients_lock:
|
|
1446
|
+
protocol = self._clients.get(client_addr)
|
|
1447
|
+
if protocol is None:
|
|
1448
|
+
return False
|
|
1449
|
+
return protocol.has_backpressure()
|
|
1450
|
+
|
|
1435
1451
|
def get_client_identity(self, client_addr: tuple) -> Optional[str]:
|
|
1436
1452
|
"""Return the verified certificate common name for a client, or None."""
|
|
1437
1453
|
with self._clients_lock:
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|