aury-boot 0.0.21__py3-none-any.whl → 0.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.
aury/boot/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.0.21'
32
- __version_tuple__ = version_tuple = (0, 0, 21)
31
+ __version__ = version = '0.0.23'
32
+ __version_tuple__ = version_tuple = (0, 0, 23)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -11,10 +11,10 @@ from contextlib import asynccontextmanager
11
11
  import sys
12
12
  from typing import Any, ClassVar
13
13
 
14
- from fastapi import FastAPI, HTTPException, Request, status
14
+ from fastapi import FastAPI, Request, status
15
15
  from fastapi.exceptions import RequestValidationError
16
16
  from fastapi.responses import JSONResponse
17
- from starlette.exceptions import HTTPException as StarletteHTTPException
17
+ from starlette.exceptions import HTTPException
18
18
  from starlette.middleware import Middleware as StarletteMiddleware
19
19
 
20
20
  from aury.boot.application.config import BaseConfig
@@ -282,9 +282,8 @@ class FoundationApp(FastAPI):
282
282
  )
283
283
 
284
284
  # 异常处理:显式注册以覆盖 FastAPI/Starlette 默认处理器,确保统一响应格式
285
- self.add_exception_handler(RequestValidationError, global_exception_handler) # 422
286
- self.add_exception_handler(HTTPException, global_exception_handler) # 4xx/5xx
287
- self.add_exception_handler(StarletteHTTPException, global_exception_handler) # Starlette 异常
285
+ self.add_exception_handler(RequestValidationError, global_exception_handler) # 422 参数校验
286
+ self.add_exception_handler(HTTPException, global_exception_handler) # 4xx/5xx HTTP 异常
288
287
  self.add_exception_handler(Exception, global_exception_handler) # 其他未处理异常
289
288
 
290
289
  # 设置路由
@@ -8,11 +8,12 @@ from __future__ import annotations
8
8
  from abc import ABC, abstractmethod
9
9
  from typing import TYPE_CHECKING
10
10
 
11
- from fastapi import HTTPException, Request, status
11
+ from fastapi import Request, status
12
12
  from fastapi.exceptions import RequestValidationError
13
13
  from fastapi.responses import JSONResponse
14
14
  from pydantic import ValidationError
15
15
  from sqlalchemy.exc import IntegrityError, SQLAlchemyError
16
+ from starlette.exceptions import HTTPException
16
17
 
17
18
  from aury.boot.common.exceptions import FoundationError
18
19
  from aury.boot.common.logging import logger
@@ -149,23 +150,31 @@ class BaseErrorHandler(ErrorHandler):
149
150
 
150
151
 
151
152
  class HTTPExceptionHandler(ErrorHandler):
152
- """FastAPI HTTP异常处理器。"""
153
+ """HTTP 异常处理器。
154
+
155
+ 处理 FastAPI 和 Starlette 的 HTTPException(包括 404、401、403 等)。
156
+ """
153
157
 
154
158
  def can_handle(self, exception: Exception) -> bool:
155
- """判断是否为HTTP异常。"""
159
+ """判断是否为 HTTP 异常。"""
160
+ # Starlette HTTPException 是 FastAPI HTTPException 的基类
156
161
  return isinstance(exception, HTTPException)
157
162
 
158
163
  async def handle(self, exception: HTTPException, request: Request) -> JSONResponse:
159
- """处理HTTP异常。"""
160
- logger.warning(f"HTTP异常: {exception.status_code} - {exception.detail}")
164
+ """处理 HTTP 异常。"""
165
+ # 获取错误信息:Starlette detail,FastAPI 也用 detail
166
+ detail = getattr(exception, "detail", str(exception))
167
+ status_code = exception.status_code
168
+
169
+ logger.warning(f"HTTP 异常 [{request.method} {request.url.path}]: {status_code} - {detail}")
161
170
 
162
171
  response = ResponseBuilder.fail(
163
- message=exception.detail,
164
- code=exception.status_code,
172
+ message=detail if isinstance(detail, str) else str(detail),
173
+ code=status_code,
165
174
  )
166
175
 
167
176
  return JSONResponse(
168
- status_code=exception.status_code,
177
+ status_code=status_code,
169
178
  content=response.model_dump(mode="json"),
170
179
  )
171
180
 
@@ -71,12 +71,51 @@ async def sse_stream(user_id: str):
71
71
 
72
72
  @router.post("/notify/{{user_id}}")
73
73
  async def send_notification(user_id: str, message: str):
74
- \"\"\"\u53d1\u9001\u901a\u77e5\u3002\"\"\"
74
+ \"\"\"发送通知。\"\"\"
75
75
  await sse_channel.publish(f"user:{{user_id}}", {{"message": message}})
76
76
  return {{"status": "sent"}}
77
77
  ```
78
78
 
79
- ## 13.4 应用场景示例
79
+ ## 13.4 模式订阅(psubscribe)
80
+
81
+ 使用通配符订阅多个通道,适合一个 SSE 连接接收多种事件的场景。
82
+
83
+ ```python
84
+ @router.get("/spaces/{{space_id}}/events")
85
+ async def space_events(space_id: str):
86
+ \"\"\"订阅空间下所有事件。\"\"\"
87
+ async def event_generator():
88
+ # 使用 psubscribe 订阅 space:{id}:* 下所有事件
89
+ async for msg in sse_channel.psubscribe(f"space:{{space_id}}:*"):
90
+ yield msg.to_sse() # 自动转换为 SSE 格式
91
+
92
+ return StreamingResponse(
93
+ event_generator(),
94
+ media_type="text/event-stream"
95
+ )
96
+
97
+
98
+ # 后端发布不同类型的事件
99
+ await sse_channel.publish(f"space:{{space_id}}:file_analyzed", {{
100
+ "file_id": "abc",
101
+ "status": "done"
102
+ }}, event="file_analyzed")
103
+
104
+ await sse_channel.publish(f"space:{{space_id}}:comment_added", {{
105
+ "comment_id": "xyz",
106
+ "content": "..."
107
+ }}, event="comment_added")
108
+ ```
109
+
110
+ **通配符说明**:
111
+ - `*` 匹配任意字符
112
+ - `?` 匹配单个字符
113
+ - `[seq]` 匹配 seq 中的任意字符
114
+ - 示例:`space:123:*` 匹配 `space:123:file_analyzed`、`space:123:comment_added` 等
115
+
116
+ Redis 后端使用 Redis 原生 `PSUBSCRIBE`,内存后端使用 `fnmatch` 实现。
117
+
118
+ ## 13.5 应用场景示例
80
119
 
81
120
  ```python
82
121
  # 不同业务场景使用不同的命名实例
@@ -90,7 +129,7 @@ await chat_channel.initialize(backend="redis", redis_client=redis_client) # 需
90
129
  await notify_channel.initialize(backend="redis", redis_client=redis_client)
91
130
  ```
92
131
 
93
- ## 13.5 环境变量
132
+ ## 13.6 环境变量
94
133
 
95
134
  ```bash
96
135
  # 默认实例
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
  import asyncio
9
9
  from collections.abc import AsyncIterator
10
10
  import contextlib
11
+ import fnmatch
11
12
 
12
13
  from aury.boot.common.logging import logger
13
14
 
@@ -31,12 +32,15 @@ class MemoryChannel(IChannel):
31
32
  self._max_subscribers = max_subscribers
32
33
  # channel -> list of queues
33
34
  self._subscribers: dict[str, list[asyncio.Queue[ChannelMessage]]] = {}
35
+ # pattern -> list of queues (用于 psubscribe)
36
+ self._pattern_subscribers: dict[str, list[asyncio.Queue[ChannelMessage]]] = {}
34
37
  self._lock = asyncio.Lock()
35
38
 
36
39
  async def publish(self, channel: str, message: ChannelMessage) -> None:
37
40
  """发布消息到通道。"""
38
41
  message.channel = channel
39
42
  async with self._lock:
43
+ # 精确匹配订阅者
40
44
  subscribers = self._subscribers.get(channel, [])
41
45
  for queue in subscribers:
42
46
  try:
@@ -44,6 +48,15 @@ class MemoryChannel(IChannel):
44
48
  except asyncio.QueueFull:
45
49
  logger.warning(f"通道 [{channel}] 订阅者队列已满,消息被丢弃")
46
50
 
51
+ # 模式匹配订阅者
52
+ for pattern, queues in self._pattern_subscribers.items():
53
+ if fnmatch.fnmatch(channel, pattern):
54
+ for queue in queues:
55
+ try:
56
+ queue.put_nowait(message)
57
+ except asyncio.QueueFull:
58
+ logger.warning(f"模式 [{pattern}] 订阅者队列已满,消息被丢弃")
59
+
47
60
  async def subscribe(self, channel: str) -> AsyncIterator[ChannelMessage]:
48
61
  """订阅通道。"""
49
62
  queue: asyncio.Queue[ChannelMessage] = asyncio.Queue(maxsize=100)
@@ -67,6 +80,35 @@ class MemoryChannel(IChannel):
67
80
  if not self._subscribers[channel]:
68
81
  del self._subscribers[channel]
69
82
 
83
+ async def psubscribe(self, pattern: str) -> AsyncIterator[ChannelMessage]:
84
+ """模式订阅通道。
85
+
86
+ 使用 fnmatch 风格的通配符:
87
+ - `*` 匹配任意字符
88
+ - `?` 匹配单个字符
89
+ - `[seq]` 匹配 seq 中的任意字符
90
+ """
91
+ queue: asyncio.Queue[ChannelMessage] = asyncio.Queue(maxsize=100)
92
+
93
+ async with self._lock:
94
+ if pattern not in self._pattern_subscribers:
95
+ self._pattern_subscribers[pattern] = []
96
+ if len(self._pattern_subscribers[pattern]) >= self._max_subscribers:
97
+ raise RuntimeError(f"模式 [{pattern}] 订阅者数量已达上限")
98
+ self._pattern_subscribers[pattern].append(queue)
99
+
100
+ try:
101
+ while True:
102
+ message = await queue.get()
103
+ yield message
104
+ finally:
105
+ async with self._lock:
106
+ if pattern in self._pattern_subscribers:
107
+ with contextlib.suppress(ValueError):
108
+ self._pattern_subscribers[pattern].remove(queue)
109
+ if not self._pattern_subscribers[pattern]:
110
+ del self._pattern_subscribers[pattern]
111
+
70
112
  async def unsubscribe(self, channel: str) -> None:
71
113
  """取消订阅通道(清除所有订阅者)。"""
72
114
  async with self._lock:
@@ -77,6 +119,7 @@ class MemoryChannel(IChannel):
77
119
  """关闭通道,清理所有订阅。"""
78
120
  async with self._lock:
79
121
  self._subscribers.clear()
122
+ self._pattern_subscribers.clear()
80
123
  logger.debug("内存通道已关闭")
81
124
 
82
125
 
@@ -72,6 +72,48 @@ class RedisChannel(IChannel):
72
72
  await pubsub.unsubscribe(channel)
73
73
  await pubsub.close()
74
74
 
75
+ async def psubscribe(self, pattern: str) -> AsyncIterator[ChannelMessage]:
76
+ """模式订阅(通配符)。
77
+
78
+ Args:
79
+ pattern: 通道模式,支持 * 和 ? 通配符
80
+ - * 匹配任意字符
81
+ - ? 匹配单个字符
82
+ - 示例: "space:123:*" 订阅 space:123 下所有事件
83
+
84
+ Yields:
85
+ ChannelMessage: 接收到的消息
86
+ """
87
+ pubsub = self._client.connection.pubsub()
88
+ await pubsub.psubscribe(pattern)
89
+
90
+ try:
91
+ async for raw_message in pubsub.listen():
92
+ # psubscribe 的消息类型是 "pmessage"
93
+ if raw_message["type"] == "pmessage":
94
+ try:
95
+ data = json.loads(raw_message["data"])
96
+ # pmessage 包含实际匹配的通道名
97
+ actual_channel = raw_message.get("channel")
98
+ if isinstance(actual_channel, bytes):
99
+ actual_channel = actual_channel.decode("utf-8")
100
+
101
+ message = ChannelMessage(
102
+ data=data.get("data"),
103
+ event=data.get("event"),
104
+ id=data.get("id"),
105
+ channel=actual_channel or data.get("channel"),
106
+ timestamp=datetime.fromisoformat(data["timestamp"])
107
+ if data.get("timestamp")
108
+ else datetime.now(),
109
+ )
110
+ yield message
111
+ except (json.JSONDecodeError, KeyError) as e:
112
+ logger.warning(f"解析通道消息失败: {e}")
113
+ finally:
114
+ await pubsub.punsubscribe(pattern)
115
+ await pubsub.close()
116
+
75
117
  async def unsubscribe(self, channel: str) -> None:
76
118
  """取消订阅通道。"""
77
119
  if self._pubsub:
@@ -70,6 +70,21 @@ class IChannel(ABC):
70
70
  """
71
71
  ...
72
72
 
73
+ async def psubscribe(self, pattern: str) -> AsyncIterator[ChannelMessage]:
74
+ """模式订阅(通配符)。
75
+
76
+ Args:
77
+ pattern: 通道模式,如 "space:123:*" 订阅 space:123 下所有事件
78
+
79
+ Yields:
80
+ ChannelMessage: 接收到的消息
81
+
82
+ 注意:内存后端默认回退到普通 subscribe,Redis 后端支持真正的模式匹配。
83
+ """
84
+ # 默认实现:回退到普通订阅(子类可覆盖)
85
+ async for msg in self.subscribe(pattern):
86
+ yield msg
87
+
73
88
  @abstractmethod
74
89
  async def unsubscribe(self, channel: str) -> None:
75
90
  """取消订阅通道。
@@ -178,6 +178,29 @@ class ChannelManager:
178
178
  async for message in self.backend.subscribe(channel):
179
179
  yield message
180
180
 
181
+ async def psubscribe(self, pattern: str) -> AsyncIterator[ChannelMessage]:
182
+ """模式订阅(通配符)。
183
+
184
+ Args:
185
+ pattern: 通道模式,支持 * 和 ? 通配符
186
+ - "space:123:*" 订阅 space:123 下所有事件
187
+ - "user:*:notification" 订阅所有用户的通知
188
+
189
+ Yields:
190
+ ChannelMessage: 接收到的消息
191
+
192
+ 示例:
193
+ # SSE 路由中订阅某个空间的所有事件
194
+ async for msg in channel.psubscribe(f"space:{{space_id}}:*"):
195
+ yield msg.to_sse()
196
+
197
+ # 发布不同类型的事件
198
+ await channel.publish(f"space:{{space_id}}:file_analyzed", {{...}})
199
+ await channel.publish(f"space:{{space_id}}:comment_added", {{...}})
200
+ """
201
+ async for message in self.backend.psubscribe(pattern):
202
+ yield message
203
+
181
204
  async def unsubscribe(self, channel: str) -> None:
182
205
  """取消订阅通道。
183
206
 
@@ -17,10 +17,17 @@ if TYPE_CHECKING:
17
17
  from aury.boot.infrastructure.clients.redis import RedisClient
18
18
 
19
19
 
20
+ # 框架默认前缀
21
+ DEFAULT_CHANNEL_PREFIX = "aury:event:"
22
+
23
+
20
24
  class RedisEventBus(IEventBus):
21
25
  """Redis 事件总线实现。
22
26
 
23
27
  使用 Redis Pub/Sub 实现跨进程的事件发布/订阅。
28
+
29
+ 频道命名格式:{channel_prefix}{event_name}
30
+ 默认:aury:event:user.created
24
31
  """
25
32
 
26
33
  def __init__(
@@ -28,14 +35,14 @@ class RedisEventBus(IEventBus):
28
35
  url: str | None = None,
29
36
  *,
30
37
  redis_client: RedisClient | None = None,
31
- channel_prefix: str = "events:",
38
+ channel_prefix: str = DEFAULT_CHANNEL_PREFIX,
32
39
  ) -> None:
33
40
  """初始化 Redis 事件总线。
34
41
 
35
42
  Args:
36
43
  url: Redis 连接 URL(当 redis_client 为 None 时必须提供)
37
44
  redis_client: RedisClient 实例(可选,优先使用)
38
- channel_prefix: 频道名称前缀
45
+ channel_prefix: 频道名称前缀,默认 "aury:event:"
39
46
 
40
47
  Raises:
41
48
  ValueError: 当 url 和 redis_client 都为 None 时
@@ -97,8 +97,8 @@ class EventBusManager:
97
97
  config: EventInstanceConfig | None = None,
98
98
  redis_client: RedisClient | None = None,
99
99
  url: str | None = None,
100
- channel_prefix: str = "events:",
101
- exchange_name: str = "events",
100
+ channel_prefix: str | None = None,
101
+ exchange_name: str = "aury.events",
102
102
  ) -> EventBusManager:
103
103
  """初始化事件总线(链式调用)。
104
104
 
@@ -107,8 +107,8 @@ class EventBusManager:
107
107
  config: Event 实例配置(推荐,自动根据 backend 初始化)
108
108
  redis_client: Redis 客户端(当 backend=redis 且 config=None 时需要)
109
109
  url: 连接 URL(当 config=None 时需要)
110
- channel_prefix: Redis 频道前缀
111
- exchange_name: RabbitMQ 交换机名称
110
+ channel_prefix: Redis 频道前缀,默认 "aury:event:"
111
+ exchange_name: RabbitMQ 交换机名称,默认 "aury.events"
112
112
 
113
113
  Returns:
114
114
  self: 支持链式调用
@@ -136,7 +136,11 @@ class EventBusManager:
136
136
  if backend == EventBackend.MEMORY:
137
137
  self._backend = MemoryEventBus()
138
138
  elif backend == EventBackend.REDIS:
139
- self._backend = RedisEventBus(url=url, redis_client=redis_client, channel_prefix=channel_prefix)
139
+ # channel_prefix 为 None 时使用 RedisEventBus 的默认值
140
+ kwargs = {"url": url, "redis_client": redis_client}
141
+ if channel_prefix is not None:
142
+ kwargs["channel_prefix"] = channel_prefix
143
+ self._backend = RedisEventBus(**kwargs)
140
144
  elif backend == EventBackend.RABBITMQ:
141
145
  self._backend = RabbitMQEventBus(url=url, exchange_name=exchange_name)
142
146
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aury-boot
3
- Version: 0.0.21
3
+ Version: 0.0.23
4
4
  Summary: Aury Boot - 基于 FastAPI 生态的企业级 API 开发框架
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: alembic>=1.17.2
@@ -1,5 +1,5 @@
1
1
  aury/boot/__init__.py,sha256=pCno-EInnpIBa1OtxNYF-JWf9j95Cd2h6vmu0xqa_-4,1791
2
- aury/boot/_version.py,sha256=G-x3V64IYobhRYKCOse2hTj6uYLM7_2kyUMOZMY7cf4,706
2
+ aury/boot/_version.py,sha256=ibKwfdtUKJ8ftEJ-ANHeQVfItYjoZhYBzigrJx5AdJU,706
3
3
  aury/boot/application/__init__.py,sha256=0o_XmiwFCeAu06VHggS8I1e7_nSMoRq0Hcm0fYfCywU,3071
4
4
  aury/boot/application/adapter/__init__.py,sha256=e1bcSb1bxUMfofTwiCuHBZJk5-STkMCWPF2EJXHQ7UU,3976
5
5
  aury/boot/application/adapter/base.py,sha256=Ar_66fiHPDEmV-1DKnqXKwc53p3pozG31bgTJTEUriY,15763
@@ -8,7 +8,7 @@ aury/boot/application/adapter/decorators.py,sha256=yyGu_16bWWUiO36gxCeQWgG0DN19p
8
8
  aury/boot/application/adapter/exceptions.py,sha256=Kzm-ytRxdUnSMIcWCSOHPxo4Jh_A6YbyxlOVIUs-5F4,6183
9
9
  aury/boot/application/adapter/http.py,sha256=4TADsSzdSRU63307dmmo-2U_JpVP12mwTFy66B5Ps-w,10759
10
10
  aury/boot/application/app/__init__.py,sha256=I8FfCKDuDQsGzAK6BevyfdtAwieMUVYu6qgVQzBazpE,830
11
- aury/boot/application/app/base.py,sha256=PYYUC_Yz3U885aU2uG5EAbbKOj_oUB4VSYMD_KS5i1s,17789
11
+ aury/boot/application/app/base.py,sha256=MYfkrb2zZgumLrGWhtT71neGncUfVHyUeAHRnetoSXk,17668
12
12
  aury/boot/application/app/components.py,sha256=-blDjMF87GYFmFyk4DHm2KJDcm27HpMxGpNaEFluwEE,22403
13
13
  aury/boot/application/app/middlewares.py,sha256=BXe2H14FHzJUVpQM6DZUm-zfZRXSXIi1QIZ4_3izfHw,3306
14
14
  aury/boot/application/app/startup.py,sha256=DHKt3C2G7V5XfFr1SQMl14tNzcuDd9MqUVAxi274HDQ,7873
@@ -23,7 +23,7 @@ aury/boot/application/errors/__init__.py,sha256=aYhGqjHayYr7sv9kM22y0sOo9R-8RK0r
23
23
  aury/boot/application/errors/chain.py,sha256=DSLZvPH7oNcxE26j3hiXG_1W7-3fdKyu0QMEEi1c5CY,2306
24
24
  aury/boot/application/errors/codes.py,sha256=CBR8umCSNp1zUslwK9tboQ4s753qBwA1OpefaQTPdjE,1431
25
25
  aury/boot/application/errors/exceptions.py,sha256=5gHC9cQsuvNpO5V9GlFkb-QqH0xNqQaOKBmTBM5wYEI,7303
26
- aury/boot/application/errors/handlers.py,sha256=Q9U1YK_tzO2lWtLhJ4Tuq973vyuCm_zElYEO07DoYlk,11948
26
+ aury/boot/application/errors/handlers.py,sha256=K6bL-ktKgzB_VCdKIL4VmQw4Z5srYRy3NJbbfnmzh_g,12367
27
27
  aury/boot/application/errors/response.py,sha256=fqOO3bNTnRRjoN3gK0-6xBVAYfSqyPvUbONowAecq9k,3107
28
28
  aury/boot/application/interfaces/__init__.py,sha256=EGbiCL8IoGseylLVZO29Lkt3luygG7JknTgtAxeb48U,1438
29
29
  aury/boot/application/interfaces/egress.py,sha256=t8FK17V649rsm65uAeBruYr2mhfcqJiIzkS8UPsOzlc,5346
@@ -81,7 +81,7 @@ aury/boot/commands/templates/project/aury_docs/09-tasks.md.tpl,sha256=swHOQ_pWPt
81
81
  aury/boot/commands/templates/project/aury_docs/10-storage.md.tpl,sha256=mhe0j0S51ndPJLjaQ6yD8OPYBEO02NHumJVbBvz2qkw,4320
82
82
  aury/boot/commands/templates/project/aury_docs/11-logging.md.tpl,sha256=bwxFCGQsO9cTEbwqJF1xcjsZKP82HRWhIMRUS0c9_ZI,2435
83
83
  aury/boot/commands/templates/project/aury_docs/12-admin.md.tpl,sha256=6z3mN54qP2jtpTFOJBLVexvEv0ZHXYKjncvpZG4yOdw,1883
84
- aury/boot/commands/templates/project/aury_docs/13-channel.md.tpl,sha256=rdtlog3ajcSsT0fq9a_US3MPcZhTvDo72eT6hetg4aI,3376
84
+ aury/boot/commands/templates/project/aury_docs/13-channel.md.tpl,sha256=xdWsIO4vT-0V1BKvPgWiG7DaQwKQSFdv7CeS16iS0cQ,4578
85
85
  aury/boot/commands/templates/project/aury_docs/14-mq.md.tpl,sha256=4bxLQBbCi0Fue0VQWOPt6acZ5P00BoLkCoLPQe_8k4U,2396
86
86
  aury/boot/commands/templates/project/aury_docs/15-events.md.tpl,sha256=a4wQRgVPuYUGTGmw_lX1HJH_yFTbD30mBz7Arc4zgfs,3361
87
87
  aury/boot/commands/templates/project/aury_docs/16-adapter.md.tpl,sha256=pkmJkZw2Ca6_uYk2jZvAb8DozjBa2tWq_t3gtq1lFSk,11456
@@ -139,11 +139,11 @@ aury/boot/infrastructure/cache/exceptions.py,sha256=KZsFIHXW3_kOh_KB93EVZJKbiDvD
139
139
  aury/boot/infrastructure/cache/factory.py,sha256=aF74JoiiSKFgctqqh2Z8OtGRS2Am_ou-I40GyygLzC0,2489
140
140
  aury/boot/infrastructure/cache/manager.py,sha256=GGoOgYyIdWKMmhej5cRvEfpNeMN1GaSaU9hc0dy8_sA,12106
141
141
  aury/boot/infrastructure/channel/__init__.py,sha256=Ztcfn1-TomgV91qhePpFK-3_nKgBt862yEFYUzIwPlo,566
142
- aury/boot/infrastructure/channel/base.py,sha256=lBpP6vQB2AReoE7pJorkj9mAylXgC31B9Iwhyy2XKlk,2087
143
- aury/boot/infrastructure/channel/manager.py,sha256=aZ-5lVn2lVRnq_tyCcEgBjZngrt_B6tuoWxlDOf3ykw,6260
142
+ aury/boot/infrastructure/channel/base.py,sha256=kRjvoOQ0X5ilUAdz03BNBfbZJgdqcsjUviK4_dJatBs,2642
143
+ aury/boot/infrastructure/channel/manager.py,sha256=kHdeVzo7btivJs8TyGDu2QgucnAlLqr-hL1dJegD72U,7166
144
144
  aury/boot/infrastructure/channel/backends/__init__.py,sha256=zrOhrzkhEIgsO7Armhgda1ruJQ6a9ZK7GPZuzvEiuN8,151
145
- aury/boot/infrastructure/channel/backends/memory.py,sha256=bQuuCU1fHRYdzLRsGwtqObI6U6VYlfyfT_gEwsZcujQ,2808
146
- aury/boot/infrastructure/channel/backends/redis.py,sha256=lJEPyUxKazjcNa-RU5GyIT2BzyOPLAw3KBTijHslrEo,2810
145
+ aury/boot/infrastructure/channel/backends/memory.py,sha256=QQyZxIdYtA_pWqdKgUIMkvnbBwvv45-vX-qostDHyfg,4699
146
+ aury/boot/infrastructure/channel/backends/redis.py,sha256=_UL7wE-bO147CPXKDjJgYGjj09Lg9x9U2PLYa37q5yQ,4666
147
147
  aury/boot/infrastructure/clients/__init__.py,sha256=1ANMejb3RrBgaR-jq-dsxJ0kQDRHz5jV-QvdUNcf_ok,435
148
148
  aury/boot/infrastructure/clients/rabbitmq/__init__.py,sha256=cnU-W7jOcAgp_FvsY9EipNCeJzeA9gHLRuZ0yQZE2DI,200
149
149
  aury/boot/infrastructure/clients/rabbitmq/config.py,sha256=YmvNiISpqNt-LE2CrpzmxCgaEgYna7IbOfUSnA0B4T0,1239
@@ -161,12 +161,12 @@ aury/boot/infrastructure/di/__init__.py,sha256=qFYlk265d6_rS8OiX37_wOc7mBFw8hk3y
161
161
  aury/boot/infrastructure/di/container.py,sha256=14FVbafGXea-JEAYeOEBxB6zAwndLCZJvprKiD_1IOQ,12524
162
162
  aury/boot/infrastructure/events/__init__.py,sha256=D5JNFkGHCH79nYbqUil0Z8eW2p6Gx8P0vBbNnHqnTgM,698
163
163
  aury/boot/infrastructure/events/base.py,sha256=oS6aNUWRvpXlbh7L3_4vzlwUumYmg44HKS1S4m_zOFo,3019
164
- aury/boot/infrastructure/events/manager.py,sha256=HIHcTMs9lz9pFIcR7S1F2iKBUKGeLaD_4P5rlLjp1vw,7334
164
+ aury/boot/infrastructure/events/manager.py,sha256=Hnua9x_Ppmo99JUEmjuZcKIPv2IEZQ3Du9ziPg-C8Fo,7570
165
165
  aury/boot/infrastructure/events/middleware.py,sha256=Ck3qNMTtLuFFKsJuEUeOMG9nu3qK1N_aqt6wH5JoAtw,1336
166
166
  aury/boot/infrastructure/events/backends/__init__.py,sha256=V_hPtdjVUkYU4Uf8hTPVBUcnNYG9OfkjRPDnjp_5_zA,224
167
167
  aury/boot/infrastructure/events/backends/memory.py,sha256=Up7vAxdJvIqkcqpnKNCu81ec6iCfNIhcQ-jKM3M2hZc,2623
168
168
  aury/boot/infrastructure/events/backends/rabbitmq.py,sha256=XCuI9mc3GR-t0zht4yZ3e2nnyFl8UuTDir_0nsDbfxM,6495
169
- aury/boot/infrastructure/events/backends/redis.py,sha256=ZCcA6ZvJFvRuwW9IbBfEUy9yp1IKiIrhJ6eDnp2ikKs,5596
169
+ aury/boot/infrastructure/events/backends/redis.py,sha256=i8jPCtR7ITPVTl9DVFDbNbjypnWoeSpar6z4lJJlOD8,5790
170
170
  aury/boot/infrastructure/monitoring/__init__.py,sha256=VgElCdCVcgERTIn3oRoSNslR82W9gRX5vgJcYDeloak,16149
171
171
  aury/boot/infrastructure/mq/__init__.py,sha256=Q7kBk_GeQnxnqkyp29Bh1yFH3Q8xxxjs8oDYLeDj8C0,498
172
172
  aury/boot/infrastructure/mq/base.py,sha256=kHrWUysWflMj3qyOnioLZ90it8d9Alq1Wb4PYhpBW4k,3396
@@ -192,7 +192,7 @@ aury/boot/testing/client.py,sha256=KOg1EemuIVsBG68G5y0DjSxZGcIQVdWQ4ASaHE3o1R0,4
192
192
  aury/boot/testing/factory.py,sha256=8GvwX9qIDu0L65gzJMlrWB0xbmJ-7zPHuwk3eECULcg,5185
193
193
  aury/boot/toolkit/__init__.py,sha256=AcyVb9fDf3CaEmJPNkWC4iGv32qCPyk4BuFKSuNiJRQ,334
194
194
  aury/boot/toolkit/http/__init__.py,sha256=zIPmpIZ9Qbqe25VmEr7jixoY2fkRbLm7NkCB9vKpg6I,11039
195
- aury_boot-0.0.21.dist-info/METADATA,sha256=a7scICE4EqlEjn1ZsnemOzEscg8IySfO6WV6VQKO-_s,7695
196
- aury_boot-0.0.21.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
197
- aury_boot-0.0.21.dist-info/entry_points.txt,sha256=f9KXEkDIGc0BGkgBvsNx_HMz9VhDjNxu26q00jUpDwQ,49
198
- aury_boot-0.0.21.dist-info/RECORD,,
195
+ aury_boot-0.0.23.dist-info/METADATA,sha256=019uIaM7hlX1CuRtQZpXpEFzDNkBowKBsad1PRyXcBc,7695
196
+ aury_boot-0.0.23.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
197
+ aury_boot-0.0.23.dist-info/entry_points.txt,sha256=f9KXEkDIGc0BGkgBvsNx_HMz9VhDjNxu26q00jUpDwQ,49
198
+ aury_boot-0.0.23.dist-info/RECORD,,