socketflow 0.1.2__tar.gz → 0.1.4__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.1.2 → socketflow-0.1.4}/PKG-INFO +1 -1
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/__init__.py +1 -1
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/client_side/client.py +13 -5
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/blueprint.py +11 -5
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/dispatcher.py +5 -1
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/event.py +7 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/server_side/server.py +9 -4
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow.egg-info/PKG-INFO +1 -1
- {socketflow-0.1.2 → socketflow-0.1.4}/README.md +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/setup.cfg +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/setup.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/client_side/__init__.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/__init__.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/compression.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/exceptions.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/message_handler.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/global_side/message_manager.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow/server_side/__init__.py +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow.egg-info/SOURCES.txt +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow.egg-info/dependency_links.txt +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow.egg-info/not-zip-safe +0 -0
- {socketflow-0.1.2 → socketflow-0.1.4}/socketflow.egg-info/top_level.txt +0 -0
|
@@ -5,6 +5,7 @@ from ..global_side.event import (
|
|
|
5
5
|
ConnectData,
|
|
6
6
|
DisconnectData,
|
|
7
7
|
MessageReceivedData,
|
|
8
|
+
ResponseData,
|
|
8
9
|
ErrorData,
|
|
9
10
|
)
|
|
10
11
|
from ..global_side.dispatcher import EventDispatcher
|
|
@@ -86,14 +87,17 @@ class TcpClientProtocol:
|
|
|
86
87
|
server_addr = (
|
|
87
88
|
self.socket.getpeername() if self.socket else ("unknown", 0)
|
|
88
89
|
)
|
|
90
|
+
wait_response = headers.get("wait_response", False)
|
|
89
91
|
event_data = MessageReceivedData(
|
|
90
|
-
data=body, server_addr=server_addr, data_id=data_id
|
|
92
|
+
data=body, server_addr=server_addr, data_id=data_id,
|
|
93
|
+
direct_response=wait_response
|
|
91
94
|
)
|
|
92
95
|
|
|
96
|
+
# Resolve pending wait_response futures
|
|
93
97
|
if data_id and data_id in self.client.pending_responses:
|
|
94
98
|
future = self.client.pending_responses.pop(data_id)
|
|
95
99
|
if hasattr(future, "set_result") and not future.done():
|
|
96
|
-
future.set_result(body)
|
|
100
|
+
future.set_result(ResponseData(data=body, data_id=data_id))
|
|
97
101
|
continue
|
|
98
102
|
|
|
99
103
|
if path:
|
|
@@ -294,6 +298,7 @@ class TcpClient:
|
|
|
294
298
|
"type": "__user__",
|
|
295
299
|
"id": data_id,
|
|
296
300
|
"path": path,
|
|
301
|
+
"wait_response": wait_response,
|
|
297
302
|
}
|
|
298
303
|
|
|
299
304
|
if self.compress:
|
|
@@ -337,7 +342,9 @@ class TcpClient:
|
|
|
337
342
|
)
|
|
338
343
|
)
|
|
339
344
|
|
|
340
|
-
threading.Timer(wait_response_timeout, timeout_handler)
|
|
345
|
+
timer = threading.Timer(wait_response_timeout, timeout_handler)
|
|
346
|
+
timer.daemon = True
|
|
347
|
+
timer.start()
|
|
341
348
|
|
|
342
349
|
try:
|
|
343
350
|
return future.result()
|
|
@@ -354,6 +361,7 @@ class TcpClient:
|
|
|
354
361
|
f"Error while waiting for response: {e}"
|
|
355
362
|
)
|
|
356
363
|
finally:
|
|
364
|
+
timer.cancel()
|
|
357
365
|
self.pending_responses.pop(data_id, None)
|
|
358
366
|
|
|
359
367
|
def wait(self):
|
|
@@ -375,8 +383,8 @@ class TcpClient:
|
|
|
375
383
|
def event(self, event_type: str):
|
|
376
384
|
return self.dispatcher.event(event_type)
|
|
377
385
|
|
|
378
|
-
def path(self, path: str, middleware=None):
|
|
379
|
-
return self.dispatcher.path(path, middleware)
|
|
386
|
+
def path(self, path: str, middleware=None, block: bool = False):
|
|
387
|
+
return self.dispatcher.path(path, middleware, block)
|
|
380
388
|
|
|
381
389
|
def register_blueprint(self, blueprint):
|
|
382
390
|
blueprint._client = self # Associate blueprint with this client
|
|
@@ -8,6 +8,7 @@ class Blueprint:
|
|
|
8
8
|
self._event_handlers: Dict[str, List[Callable]] = {}
|
|
9
9
|
self._path_handlers: Dict[str, List[Callable]] = {}
|
|
10
10
|
self._path_middleware: Dict[str, List[Callable]] = {}
|
|
11
|
+
self._path_blocking: Dict[str, bool] = {}
|
|
11
12
|
|
|
12
13
|
def event(self, event_type: str):
|
|
13
14
|
"""Decorator for event handlers"""
|
|
@@ -18,11 +19,11 @@ class Blueprint:
|
|
|
18
19
|
|
|
19
20
|
return decorator
|
|
20
21
|
|
|
21
|
-
def path(self, path: str, middleware=None):
|
|
22
|
+
def path(self, path: str, middleware=None, block: bool = False):
|
|
22
23
|
"""Decorator for path handlers"""
|
|
23
24
|
|
|
24
25
|
def decorator(func):
|
|
25
|
-
self.register_path(path, func, middleware)
|
|
26
|
+
self.register_path(path, func, middleware, block)
|
|
26
27
|
return func
|
|
27
28
|
|
|
28
29
|
return decorator
|
|
@@ -33,7 +34,7 @@ class Blueprint:
|
|
|
33
34
|
self._event_handlers[event_type] = []
|
|
34
35
|
self._event_handlers[event_type].append(handler)
|
|
35
36
|
|
|
36
|
-
def register_path(self, path: str, handler: Callable, middleware=None):
|
|
37
|
+
def register_path(self, path: str, handler: Callable, middleware=None, block: bool = False):
|
|
37
38
|
"""Register a path handler"""
|
|
38
39
|
if path not in self._path_handlers:
|
|
39
40
|
self._path_handlers[path] = []
|
|
@@ -48,6 +49,10 @@ class Blueprint:
|
|
|
48
49
|
else:
|
|
49
50
|
self._path_middleware[path].append(middleware)
|
|
50
51
|
|
|
52
|
+
# Store blocking
|
|
53
|
+
if block:
|
|
54
|
+
self._path_blocking[path] = True
|
|
55
|
+
|
|
51
56
|
def register_with_dispatcher(self, dispatcher):
|
|
52
57
|
"""Register all handlers with a dispatcher"""
|
|
53
58
|
for event_type, handlers in self._event_handlers.items():
|
|
@@ -56,9 +61,10 @@ class Blueprint:
|
|
|
56
61
|
|
|
57
62
|
for path, handlers in self._path_handlers.items():
|
|
58
63
|
for handler in handlers:
|
|
59
|
-
# Get middleware for this path
|
|
64
|
+
# Get middleware and blocking for this path
|
|
60
65
|
middleware = self._path_middleware.get(path, [])
|
|
61
|
-
|
|
66
|
+
block = self._path_blocking.get(path, False)
|
|
67
|
+
dispatcher.register_path(path, handler, middleware, block)
|
|
62
68
|
|
|
63
69
|
def is_connected(self, client_addr: tuple = None):
|
|
64
70
|
if hasattr(self, "_client") and self._client:
|
|
@@ -166,7 +166,11 @@ class EventDispatcher:
|
|
|
166
166
|
# Check if blocking is enabled for this path and we have a client ID
|
|
167
167
|
lock = None
|
|
168
168
|
if is_blocking and client_id:
|
|
169
|
-
|
|
169
|
+
# Use the pattern string for parameterized paths so all dynamic
|
|
170
|
+
# paths sharing the same pattern (e.g. /slow/1, /slow/2 for
|
|
171
|
+
# /slow/<id>) share one lock per client.
|
|
172
|
+
lock_path = matched_pattern if matched_pattern else path
|
|
173
|
+
lock_key = (lock_path, client_id)
|
|
170
174
|
# Get or create lock for this client-path combination
|
|
171
175
|
if lock_key not in self._path_locks:
|
|
172
176
|
self._path_locks[lock_key] = threading.Lock()
|
|
@@ -33,6 +33,13 @@ class MessageReceivedData:
|
|
|
33
33
|
server_addr: Optional[Tuple[str, int]] = None
|
|
34
34
|
data_id: Optional[str] = None
|
|
35
35
|
params: Dict[str, str] = field(default_factory=dict)
|
|
36
|
+
direct_response: bool = False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class ResponseData:
|
|
41
|
+
data: Any
|
|
42
|
+
data_id: Optional[str] = None
|
|
36
43
|
|
|
37
44
|
|
|
38
45
|
@dataclass
|
|
@@ -13,6 +13,7 @@ from ..global_side.event import (
|
|
|
13
13
|
ErrorData,
|
|
14
14
|
EventType,
|
|
15
15
|
MessageReceivedData,
|
|
16
|
+
ResponseData,
|
|
16
17
|
ServerStartData,
|
|
17
18
|
ServerStopData,
|
|
18
19
|
)
|
|
@@ -86,14 +87,17 @@ class TcpServerProtocol:
|
|
|
86
87
|
elif msg_type == "__user__":
|
|
87
88
|
path = headers.get("path")
|
|
88
89
|
data_id = headers.get("id")
|
|
90
|
+
wait_response = headers.get("wait_response", False)
|
|
89
91
|
event_data = MessageReceivedData(
|
|
90
|
-
data=body, client_addr=self.client_addr, data_id=data_id
|
|
92
|
+
data=body, client_addr=self.client_addr, data_id=data_id,
|
|
93
|
+
direct_response=wait_response
|
|
91
94
|
)
|
|
92
95
|
|
|
96
|
+
# Resolve pending wait_response futures
|
|
93
97
|
if data_id and data_id in self.server.pending_responses:
|
|
94
98
|
future = self.server.pending_responses.pop(data_id)
|
|
95
99
|
if hasattr(future, "set_result") and not future.done():
|
|
96
|
-
future.set_result(body)
|
|
100
|
+
future.set_result(ResponseData(data=body, data_id=data_id))
|
|
97
101
|
continue
|
|
98
102
|
|
|
99
103
|
if path:
|
|
@@ -305,6 +309,7 @@ class TcpServer:
|
|
|
305
309
|
"type": "__user__",
|
|
306
310
|
"id": data_id,
|
|
307
311
|
"path": path,
|
|
312
|
+
"wait_response": wait_response,
|
|
308
313
|
}
|
|
309
314
|
|
|
310
315
|
if self.compress:
|
|
@@ -400,8 +405,8 @@ class TcpServer:
|
|
|
400
405
|
def event(self, event_type: str):
|
|
401
406
|
return self.dispatcher.event(event_type)
|
|
402
407
|
|
|
403
|
-
def path(self, path: str, middleware=None):
|
|
404
|
-
return self.dispatcher.path(path, middleware)
|
|
408
|
+
def path(self, path: str, middleware=None, block: bool = False):
|
|
409
|
+
return self.dispatcher.path(path, middleware, block)
|
|
405
410
|
|
|
406
411
|
def register_blueprint(self, blueprint):
|
|
407
412
|
blueprint._server = self # Associate blueprint with this server
|
|
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
|