hypern 0.3.0__cp312-cp312-win32.whl → 0.3.2__cp312-cp312-win32.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.
- hypern/application.py +47 -8
- hypern/args_parser.py +7 -0
- hypern/caching/__init__.py +6 -0
- hypern/caching/backend.py +31 -0
- hypern/caching/redis_backend.py +200 -2
- hypern/caching/strategies.py +208 -0
- hypern/gateway/__init__.py +6 -0
- hypern/gateway/aggregator.py +32 -0
- hypern/gateway/gateway.py +41 -0
- hypern/gateway/proxy.py +60 -0
- hypern/gateway/service.py +52 -0
- hypern/hypern.cp312-win32.pyd +0 -0
- hypern/hypern.pyi +27 -17
- hypern/middleware/__init__.py +14 -2
- hypern/middleware/base.py +9 -14
- hypern/middleware/cache.py +177 -0
- hypern/middleware/compress.py +78 -0
- hypern/middleware/cors.py +6 -3
- hypern/middleware/limit.py +5 -4
- hypern/middleware/security.py +184 -0
- hypern/processpool.py +41 -2
- hypern/reload.py +26 -40
- hypern/routing/__init__.py +2 -1
- hypern/routing/queue.py +175 -0
- hypern/ws/__init__.py +4 -0
- hypern/ws/channel.py +80 -0
- hypern/ws/heartbeat.py +74 -0
- hypern/ws/room.py +76 -0
- hypern/ws/route.py +26 -0
- {hypern-0.3.0.dist-info → hypern-0.3.2.dist-info}/METADATA +1 -1
- {hypern-0.3.0.dist-info → hypern-0.3.2.dist-info}/RECORD +33 -23
- {hypern-0.3.0.dist-info → hypern-0.3.2.dist-info}/WHEEL +1 -1
- hypern/caching/base/__init__.py +0 -8
- hypern/caching/base/backend.py +0 -3
- hypern/caching/base/key_maker.py +0 -8
- hypern/caching/cache_manager.py +0 -56
- hypern/caching/cache_tag.py +0 -10
- hypern/caching/custom_key_maker.py +0 -11
- {hypern-0.3.0.dist-info → hypern-0.3.2.dist-info}/licenses/LICENSE +0 -0
hypern/ws/heartbeat.py
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
import asyncio
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from time import time
|
4
|
+
from typing import Dict
|
5
|
+
|
6
|
+
from hypern.hypern import WebSocketSession
|
7
|
+
|
8
|
+
|
9
|
+
@dataclass
|
10
|
+
class HeartbeatConfig:
|
11
|
+
ping_interval: float = 30.0 # Send ping every 30 seconds
|
12
|
+
ping_timeout: float = 10.0 # Wait 10 seconds for pong response
|
13
|
+
max_missed_pings: int = 2 # Disconnect after 2 missed pings
|
14
|
+
|
15
|
+
|
16
|
+
class HeartbeatManager:
|
17
|
+
def __init__(self, config: HeartbeatConfig = None):
|
18
|
+
self.config = config or HeartbeatConfig()
|
19
|
+
self.active_sessions: Dict[WebSocketSession, float] = {}
|
20
|
+
self.ping_tasks: Dict[WebSocketSession, asyncio.Task] = {}
|
21
|
+
self.missed_pings: Dict[WebSocketSession, int] = {}
|
22
|
+
|
23
|
+
async def start_heartbeat(self, session: WebSocketSession):
|
24
|
+
"""Start heartbeat monitoring for a session"""
|
25
|
+
self.active_sessions[session] = time()
|
26
|
+
self.missed_pings[session] = 0
|
27
|
+
self.ping_tasks[session] = asyncio.create_task(self._heartbeat_loop(session))
|
28
|
+
|
29
|
+
async def stop_heartbeat(self, session: WebSocketSession):
|
30
|
+
"""Stop heartbeat monitoring for a session"""
|
31
|
+
if session in self.ping_tasks:
|
32
|
+
self.ping_tasks[session].cancel()
|
33
|
+
del self.ping_tasks[session]
|
34
|
+
self.active_sessions.pop(session, None)
|
35
|
+
self.missed_pings.pop(session, None)
|
36
|
+
|
37
|
+
async def handle_pong(self, session: WebSocketSession):
|
38
|
+
"""Handle pong response from client"""
|
39
|
+
if session in self.active_sessions:
|
40
|
+
self.active_sessions[session] = time()
|
41
|
+
self.missed_pings[session] = 0
|
42
|
+
|
43
|
+
async def _heartbeat_loop(self, session: WebSocketSession):
|
44
|
+
"""Main heartbeat loop for a session"""
|
45
|
+
try:
|
46
|
+
while True:
|
47
|
+
await asyncio.sleep(self.config.ping_interval)
|
48
|
+
|
49
|
+
if session not in self.active_sessions:
|
50
|
+
break
|
51
|
+
|
52
|
+
# Send ping frame
|
53
|
+
try:
|
54
|
+
await session.ping()
|
55
|
+
last_pong = self.active_sessions[session]
|
56
|
+
|
57
|
+
# Wait for pong timeout
|
58
|
+
await asyncio.sleep(self.config.ping_timeout)
|
59
|
+
|
60
|
+
# Check if we received a pong
|
61
|
+
if self.active_sessions[session] == last_pong:
|
62
|
+
self.missed_pings[session] += 1
|
63
|
+
|
64
|
+
# Check if we exceeded max missed pings
|
65
|
+
if self.missed_pings[session] >= self.config.max_missed_pings:
|
66
|
+
await session.close(1001, "Connection timeout")
|
67
|
+
break
|
68
|
+
|
69
|
+
except Exception as e:
|
70
|
+
await session.close(1001, f"Heartbeat failed: {str(e)}")
|
71
|
+
break
|
72
|
+
|
73
|
+
finally:
|
74
|
+
await self.stop_heartbeat(session)
|
hypern/ws/room.py
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
from dataclasses import dataclass, field
|
2
|
+
from typing import Dict, Set
|
3
|
+
|
4
|
+
from hypern.hypern import WebSocketSession
|
5
|
+
|
6
|
+
|
7
|
+
@dataclass
|
8
|
+
class Room:
|
9
|
+
name: str
|
10
|
+
clients: Set[WebSocketSession] = field(default_factory=set)
|
11
|
+
|
12
|
+
def broadcast(self, message: str, exclude: WebSocketSession = None):
|
13
|
+
"""Broadcast message to all clients in the room except excluded one"""
|
14
|
+
for client in self.clients:
|
15
|
+
if client != exclude:
|
16
|
+
client.send(message)
|
17
|
+
|
18
|
+
def add_client(self, client: WebSocketSession):
|
19
|
+
"""Add a client to the room"""
|
20
|
+
self.clients.add(client)
|
21
|
+
|
22
|
+
def remove_client(self, client: WebSocketSession):
|
23
|
+
"""Remove a client from the room"""
|
24
|
+
self.clients.discard(client)
|
25
|
+
|
26
|
+
@property
|
27
|
+
def client_count(self) -> int:
|
28
|
+
return len(self.clients)
|
29
|
+
|
30
|
+
|
31
|
+
class RoomManager:
|
32
|
+
def __init__(self):
|
33
|
+
self.rooms: Dict[str, Room] = {}
|
34
|
+
self.client_rooms: Dict[WebSocketSession, Set[str]] = {}
|
35
|
+
|
36
|
+
def create_room(self, room_name: str) -> Room:
|
37
|
+
"""Create a new room if it doesn't exist"""
|
38
|
+
if room_name not in self.rooms:
|
39
|
+
self.rooms[room_name] = Room(room_name)
|
40
|
+
return self.rooms[room_name]
|
41
|
+
|
42
|
+
def get_room(self, room_name: str) -> Room:
|
43
|
+
"""Get a room by name"""
|
44
|
+
return self.rooms.get(room_name)
|
45
|
+
|
46
|
+
def join_room(self, client: WebSocketSession, room_name: str):
|
47
|
+
"""Add a client to a room"""
|
48
|
+
room = self.create_room(room_name)
|
49
|
+
room.add_client(client)
|
50
|
+
|
51
|
+
if client not in self.client_rooms:
|
52
|
+
self.client_rooms[client] = set()
|
53
|
+
self.client_rooms[client].add(room_name)
|
54
|
+
|
55
|
+
room.broadcast(f"Client joined room: {room_name}", exclude=client)
|
56
|
+
|
57
|
+
def leave_room(self, client: WebSocketSession, room_name: str):
|
58
|
+
"""Remove a client from a room"""
|
59
|
+
room = self.get_room(room_name)
|
60
|
+
if room:
|
61
|
+
room.remove_client(client)
|
62
|
+
if client in self.client_rooms:
|
63
|
+
self.client_rooms[client].discard(room_name)
|
64
|
+
|
65
|
+
room.broadcast(f"Client left room: {room_name}", exclude=client)
|
66
|
+
|
67
|
+
if room.client_count == 0:
|
68
|
+
del self.rooms[room_name]
|
69
|
+
|
70
|
+
def leave_all_rooms(self, client: WebSocketSession):
|
71
|
+
"""Remove a client from all rooms"""
|
72
|
+
if client in self.client_rooms:
|
73
|
+
rooms = self.client_rooms[client].copy()
|
74
|
+
for room_name in rooms:
|
75
|
+
self.leave_room(client, room_name)
|
76
|
+
del self.client_rooms[client]
|
hypern/ws/route.py
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
from typing import Callable, Optional
|
2
|
+
|
3
|
+
from hypern.hypern import WebsocketRoute as WebsocketRouteInternal, WebSocketSession
|
4
|
+
|
5
|
+
|
6
|
+
class WebsocketRoute:
|
7
|
+
def __init__(self) -> None:
|
8
|
+
self.routes = []
|
9
|
+
self._disconnect_handler: Optional[Callable] = None
|
10
|
+
|
11
|
+
def on(self, path):
|
12
|
+
def wrapper(func):
|
13
|
+
self.routes.append(WebsocketRouteInternal(path, func))
|
14
|
+
return func
|
15
|
+
|
16
|
+
return wrapper
|
17
|
+
|
18
|
+
def on_disconnect(self, func):
|
19
|
+
"""Register a disconnect handler"""
|
20
|
+
self._disconnect_handler = func
|
21
|
+
return func
|
22
|
+
|
23
|
+
def handle_disconnect(self, session: WebSocketSession):
|
24
|
+
"""Internal method to handle disconnection"""
|
25
|
+
if self._disconnect_handler:
|
26
|
+
return self._disconnect_handler(session)
|
@@ -1,19 +1,15 @@
|
|
1
|
-
hypern-0.3.
|
2
|
-
hypern-0.3.
|
3
|
-
hypern-0.3.
|
4
|
-
hypern/application.py,sha256=
|
5
|
-
hypern/args_parser.py,sha256=
|
1
|
+
hypern-0.3.2.dist-info/METADATA,sha256=xbMB8V67yK1aLvRGbYrsjqoScFdSOZXs97zXg0yVVQ4,3754
|
2
|
+
hypern-0.3.2.dist-info/WHEEL,sha256=SK_cql1gpDHx6aBV-LOSvGbTt4TUC8AJJOzjOP2tdpI,92
|
3
|
+
hypern-0.3.2.dist-info/licenses/LICENSE,sha256=qbYKAIJLS6jYg5hYncKE7OtWmqOtpVTvKNkwOa0Iwwg,1328
|
4
|
+
hypern/application.py,sha256=yNlohWdSG0lpKfuTVX7N9gI3cmXl3IoEvP8WLH-yAiE,16251
|
5
|
+
hypern/args_parser.py,sha256=diz3Oq1PDNMBlG7ElqK01iokY5w_X3U1Ky1jikPVXRg,2020
|
6
6
|
hypern/auth/authorization.py,sha256=-NprZsI0np889ZN1fp-MiVFrPoMNzUtatBJaCMtkllM,32
|
7
7
|
hypern/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
hypern/background.py,sha256=xy38nQZSJsYFRXr3-uFJeNW9E1GiXXOC7lSe5pC0eyE,124
|
9
|
-
hypern/caching/
|
10
|
-
hypern/caching/
|
11
|
-
hypern/caching/
|
12
|
-
hypern/caching/
|
13
|
-
hypern/caching/cache_tag.py,sha256=bZcjivMNETAzAHAIobuLN0S2wHgPgLLL8Gg4uso_qbk,267
|
14
|
-
hypern/caching/custom_key_maker.py,sha256=88RIIJjpQYFnv857wOlCKgWWBbK_S23zNHsIrJz_4PY,394
|
15
|
-
hypern/caching/redis_backend.py,sha256=IgQToCnHYGpKEErq2CNZkR5woo01z456Ef3C-XRPRV8,70
|
16
|
-
hypern/caching/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
hypern/caching/backend.py,sha256=bfSEgJQxS3FDdj08CY4V9b9U3rwf4uy9gS46QmwA3Zc,829
|
10
|
+
hypern/caching/redis_backend.py,sha256=SWYlJvr8qi2kS_grhxhqQBLEEATpFremT2XyXkio8h0,5968
|
11
|
+
hypern/caching/strategies.py,sha256=qQjqgZLUX7KZjhwPD4SYUaMRewgCgsp6qa1FunK3Y0I,7288
|
12
|
+
hypern/caching/__init__.py,sha256=ODO7zMm4iFG8wcvrhKmukryG5wOTW0DnzFvNMfF57Cc,352
|
17
13
|
hypern/cli/commands.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
14
|
hypern/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
15
|
hypern/config.py,sha256=frZSdXBI8GaM0tkw1Rs-XydZ9-XjGLRPj6DL4d51-y4,4930
|
@@ -38,32 +34,46 @@ hypern/db/sql/__init__.py,sha256=1UoWQi2CIcUAbQj3FadR-8V0o_b286nI2wYvOsvtbFc,647
|
|
38
34
|
hypern/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
35
|
hypern/enum.py,sha256=KcVziJj7vWvyie0r2rtxhrLzdtkZAsf0DY58oJ4tQl4,360
|
40
36
|
hypern/exceptions.py,sha256=nHTkF0YdNBMKfSiNtjRMHMNKoY3RMUm68YYluuW15us,2428
|
41
|
-
hypern/
|
37
|
+
hypern/gateway/aggregator.py,sha256=N1onAp9gdzpCR-E5VubkVoUjjEmVNxG8gDZx9rhnbXc,1132
|
38
|
+
hypern/gateway/gateway.py,sha256=26K2qvJUR-0JnN4IlhwvSSt7EYcpYrBVDuzZ1ivQQ34,1475
|
39
|
+
hypern/gateway/proxy.py,sha256=w1wcTplDnVrfjn7hb0M0yBVth5TGl88irF-MUYHysQQ,2463
|
40
|
+
hypern/gateway/service.py,sha256=PkRaM08olqM_j_4wRjEJCR8X8ZysAF2WOcfhWjaX2eo,1701
|
41
|
+
hypern/gateway/__init__.py,sha256=TpFWtqnJerW1-jCWq5fjypJcw9Y6ytyrkvkzby1Eg0E,235
|
42
|
+
hypern/hypern.pyi,sha256=GiUjtY6tbV8d6KI1PDTTZK5zWyOD4hooahALnFd7Fl4,8197
|
42
43
|
hypern/i18n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
43
44
|
hypern/logging/logger.py,sha256=WACam_IJiCMXX0hGVKMGSxUQpY4DgAXy7M1dD3q-Z9s,3256
|
44
45
|
hypern/logging/__init__.py,sha256=6eVriyncsJ4J73fGYhoejv9MX7aGTkRezTpPxO4DX1I,52
|
45
|
-
hypern/middleware/base.py,sha256=
|
46
|
-
hypern/middleware/
|
46
|
+
hypern/middleware/base.py,sha256=3G7vxFXr0tDp28Bz3NeM76eo03qYGppm07N3yWoA_4U,369
|
47
|
+
hypern/middleware/cache.py,sha256=HFfghpnhS21DOsXLn6nt-TgRLCNNm6ZqTKPMgoXM0Mw,7583
|
48
|
+
hypern/middleware/compress.py,sha256=Zph3pQz15YrYB4dMUMbQnfWIFY8ovysgPMepbY_WV9k,3119
|
49
|
+
hypern/middleware/cors.py,sha256=pt5HyTd3J5L9Lvczo2xI8fxLmtntSbJq-CPU0vYXoAI,1800
|
47
50
|
hypern/middleware/i18n.py,sha256=jHzVzjTx1nnjbraZtIVOprrnSaeKMxZB8RuSqRp2I4s,16
|
48
|
-
hypern/middleware/limit.py,sha256=
|
49
|
-
hypern/middleware/
|
51
|
+
hypern/middleware/limit.py,sha256=eAYARPjqxq8Ue0TCpnxlVRB5hv7hwBF0PxeD-bG6Sl0,8252
|
52
|
+
hypern/middleware/security.py,sha256=d9Qf2UNMN8wz-MLnG2wRb0Vgf55_IGZAje5hbc2T_HQ,7539
|
53
|
+
hypern/middleware/__init__.py,sha256=V-Gnv-Jf-14BVuA28z7PN7GBVQ9BBiBdab6-QnTPCfY,493
|
50
54
|
hypern/openapi/schemas.py,sha256=YHfMlPUeP5DzDX5ao3YH8p_25Vvyaf616dh6XDCUZRc,1677
|
51
55
|
hypern/openapi/swagger.py,sha256=naqUY3rFAEYA1ZLIlmDsMYaol0yIm6TVebdkFa5cMTc,64
|
52
56
|
hypern/openapi/__init__.py,sha256=4rEVD8pa0kdSpsy7ZkJ5JY0Z2XF0NGSKDMwYAd7YZpE,141
|
53
|
-
hypern/processpool.py,sha256=
|
57
|
+
hypern/processpool.py,sha256=l6_PKRMFQ4GIMPLTMOEbIwWDsxER0NIj_wdxVWqA7zA,5042
|
54
58
|
hypern/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
55
|
-
hypern/reload.py,sha256=
|
59
|
+
hypern/reload.py,sha256=nfaZCoChrQetHNtIqN4Xzi-a0v-irxSCMhwCK3bCEq0,1569
|
56
60
|
hypern/response/response.py,sha256=-dnboAraPic8asf503PxwmDuxhNllUO5h97_DGmbER4,4582
|
57
61
|
hypern/response/__init__.py,sha256=_w3u3TDNuYx5ejnnN1unqnTY8NlBgUATQi6wepEB_FQ,226
|
58
62
|
hypern/routing/dispatcher.py,sha256=i2wLAAW1ZXgpi5K2heGXhTODnP1WdQzaR5WlUjs1o9c,2368
|
59
63
|
hypern/routing/endpoint.py,sha256=RKVhvqOEGL9IKBXQ3KJgPi9bgJj9gfWC5BdZc5U_atc,1026
|
60
64
|
hypern/routing/parser.py,sha256=R-4lcN9Ha1iMeAjlqDe8HwkjjMVG-c-ubQLZyWKXj6M,3554
|
65
|
+
hypern/routing/queue.py,sha256=NtFBbogU22ddyyX-CuQMip1XFDPZdMCVMIeUCQ-CR6Y,7176
|
61
66
|
hypern/routing/route.py,sha256=IUnWU5ra-0R9rrRDpxJiwiw7vaEefn-We2dZ4EocJGw,10403
|
62
|
-
hypern/routing/__init__.py,sha256=
|
67
|
+
hypern/routing/__init__.py,sha256=U4xW5fDRsn03z4cVLT4dJHHGGU6SVxyv2DL86LXodeE,162
|
63
68
|
hypern/scheduler.py,sha256=-k3tW2AGCnHYSthKXk-FOs_SCtWp3yIxQzwzUJMJsbo,67
|
64
69
|
hypern/security.py,sha256=3E86Yp_eOSVa1emUvBrDgoF0Sn6eNX0CfLnt87w5CPI,1773
|
65
70
|
hypern/worker.py,sha256=WQrhY_awR6zjMwY4Q7izXi4E4fFrDqt7jIblUW8Bzcg,924
|
71
|
+
hypern/ws/channel.py,sha256=0ns2qmeoFJOpGLXS_hqldhywDQm_DxHwj6KloQx4Q3I,3183
|
72
|
+
hypern/ws/heartbeat.py,sha256=sWMXzQm6cbDHHA2NHc-gFjv7G_E56XtxswHQ93_BueM,2861
|
73
|
+
hypern/ws/room.py,sha256=0_L6Nun0n007F0rfNY8yX5x_A8EuXuI67JqpMkJ4RNI,2598
|
74
|
+
hypern/ws/route.py,sha256=fGQ2RC708MPOiiIHPUo8aZ-oK379TTAyQYm4htNA5jM,803
|
75
|
+
hypern/ws/__init__.py,sha256=dhRoRY683_rfPfSPM5qUczfTuyYDeuLOCFxY4hIdKt8,131
|
66
76
|
hypern/ws.py,sha256=F6SA2Z1KVnqTEX8ssvOXqCtudUS4eo30JsiIsvfbHnE,394
|
67
77
|
hypern/__init__.py,sha256=9Ww_aUQ0vJls0tOq7Yw1_TVOCRsa5bHJ-RtnSeComwk,119
|
68
|
-
hypern/hypern.cp312-win32.pyd,sha256=
|
69
|
-
hypern-0.3.
|
78
|
+
hypern/hypern.cp312-win32.pyd,sha256=JxNOpTLC3EaBfc6d3TLY05BbTHHx5ciyj3wSbOKbWIM,6539264
|
79
|
+
hypern-0.3.2.dist-info/RECORD,,
|
hypern/caching/base/__init__.py
DELETED
hypern/caching/base/backend.py
DELETED
hypern/caching/base/key_maker.py
DELETED
hypern/caching/cache_manager.py
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
from functools import wraps
|
3
|
-
from typing import Callable, Dict, Type
|
4
|
-
|
5
|
-
from .base import BaseBackend, BaseKeyMaker
|
6
|
-
from .cache_tag import CacheTag
|
7
|
-
import orjson
|
8
|
-
|
9
|
-
|
10
|
-
class CacheManager:
|
11
|
-
def __init__(self):
|
12
|
-
self.backend = None
|
13
|
-
self.key_maker = None
|
14
|
-
|
15
|
-
def init(self, backend: BaseBackend, key_maker: BaseKeyMaker) -> None:
|
16
|
-
self.backend = backend
|
17
|
-
self.key_maker = key_maker
|
18
|
-
|
19
|
-
def cached(self, tag: CacheTag, ttl: int = 60, identify: Dict = {}) -> Type[Callable]:
|
20
|
-
def _cached(function):
|
21
|
-
@wraps(function)
|
22
|
-
async def __cached(*args, **kwargs):
|
23
|
-
if not self.backend or not self.key_maker:
|
24
|
-
raise ValueError("Backend or KeyMaker not initialized")
|
25
|
-
|
26
|
-
_identify_key = []
|
27
|
-
for key, values in identify.items():
|
28
|
-
_obj = kwargs.get(key, None)
|
29
|
-
if not _obj:
|
30
|
-
raise ValueError(f"Caching: Identify key {key} not found in kwargs")
|
31
|
-
for attr in values:
|
32
|
-
_identify_key.append(f"{attr}={getattr(_obj, attr)}")
|
33
|
-
_identify_key = ":".join(_identify_key)
|
34
|
-
|
35
|
-
key = await self.key_maker.make(function=function, prefix=tag.value, identify_key=_identify_key)
|
36
|
-
|
37
|
-
cached_response = self.backend.get(key=key)
|
38
|
-
if cached_response:
|
39
|
-
return orjson.loads(cached_response)
|
40
|
-
|
41
|
-
response = await function(*args, **kwargs)
|
42
|
-
self.backend.set(response=orjson.dumps(response).decode("utf-8"), key=key, ttl=ttl)
|
43
|
-
return response
|
44
|
-
|
45
|
-
return __cached
|
46
|
-
|
47
|
-
return _cached # type: ignore
|
48
|
-
|
49
|
-
async def remove_by_tag(self, tag: CacheTag) -> None:
|
50
|
-
await self.backend.delete_startswith(value=tag.value)
|
51
|
-
|
52
|
-
async def remove_by_prefix(self, prefix: str) -> None:
|
53
|
-
await self.backend.delete_startswith(value=prefix)
|
54
|
-
|
55
|
-
|
56
|
-
Cache = CacheManager()
|
hypern/caching/cache_tag.py
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
from typing import Callable
|
3
|
-
import inspect
|
4
|
-
|
5
|
-
from hypern.caching.base import BaseKeyMaker
|
6
|
-
|
7
|
-
|
8
|
-
class CustomKeyMaker(BaseKeyMaker):
|
9
|
-
async def make(self, function: Callable, prefix: str, identify_key: str = "") -> str:
|
10
|
-
path = f"{prefix}:{inspect.getmodule(function).__name__}.{function.__name__}:{identify_key}" # type: ignore
|
11
|
-
return str(path)
|
File without changes
|