aury-boot 0.0.4__py3-none-any.whl → 0.0.7__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.
Files changed (122) hide show
  1. aury/boot/__init__.py +2 -2
  2. aury/boot/_version.py +2 -2
  3. aury/boot/application/__init__.py +60 -36
  4. aury/boot/application/adapter/__init__.py +112 -0
  5. aury/boot/application/adapter/base.py +511 -0
  6. aury/boot/application/adapter/config.py +242 -0
  7. aury/boot/application/adapter/decorators.py +259 -0
  8. aury/boot/application/adapter/exceptions.py +202 -0
  9. aury/boot/application/adapter/http.py +325 -0
  10. aury/boot/application/app/__init__.py +12 -8
  11. aury/boot/application/app/base.py +12 -0
  12. aury/boot/application/app/components.py +137 -44
  13. aury/boot/application/app/middlewares.py +9 -4
  14. aury/boot/application/app/startup.py +249 -0
  15. aury/boot/application/config/__init__.py +36 -1
  16. aury/boot/application/config/multi_instance.py +216 -0
  17. aury/boot/application/config/settings.py +398 -149
  18. aury/boot/application/constants/components.py +6 -0
  19. aury/boot/application/errors/handlers.py +17 -3
  20. aury/boot/application/middleware/logging.py +21 -120
  21. aury/boot/application/rpc/__init__.py +2 -2
  22. aury/boot/commands/__init__.py +30 -10
  23. aury/boot/commands/app.py +131 -1
  24. aury/boot/commands/docs.py +104 -17
  25. aury/boot/commands/generate.py +22 -22
  26. aury/boot/commands/init.py +68 -17
  27. aury/boot/commands/server/app.py +2 -3
  28. aury/boot/commands/templates/project/AGENTS.md.tpl +221 -0
  29. aury/boot/commands/templates/project/README.md.tpl +2 -2
  30. aury/boot/commands/templates/project/aury_docs/00-overview.md.tpl +59 -0
  31. aury/boot/commands/templates/project/aury_docs/01-model.md.tpl +184 -0
  32. aury/boot/commands/templates/project/aury_docs/02-repository.md.tpl +206 -0
  33. aury/boot/commands/templates/project/aury_docs/03-service.md.tpl +398 -0
  34. aury/boot/commands/templates/project/aury_docs/04-schema.md.tpl +95 -0
  35. aury/boot/commands/templates/project/aury_docs/05-api.md.tpl +116 -0
  36. aury/boot/commands/templates/project/aury_docs/06-exception.md.tpl +118 -0
  37. aury/boot/commands/templates/project/aury_docs/07-cache.md.tpl +122 -0
  38. aury/boot/commands/templates/project/aury_docs/08-scheduler.md.tpl +32 -0
  39. aury/boot/commands/templates/project/aury_docs/09-tasks.md.tpl +38 -0
  40. aury/boot/commands/templates/project/aury_docs/10-storage.md.tpl +115 -0
  41. aury/boot/commands/templates/project/aury_docs/11-logging.md.tpl +131 -0
  42. aury/boot/commands/templates/project/aury_docs/12-admin.md.tpl +56 -0
  43. aury/boot/commands/templates/project/aury_docs/13-channel.md.tpl +104 -0
  44. aury/boot/commands/templates/project/aury_docs/14-mq.md.tpl +102 -0
  45. aury/boot/commands/templates/project/aury_docs/15-events.md.tpl +147 -0
  46. aury/boot/commands/templates/project/aury_docs/16-adapter.md.tpl +403 -0
  47. aury/boot/commands/templates/project/{CLI.md.tpl → aury_docs/99-cli.md.tpl} +19 -19
  48. aury/boot/commands/templates/project/config.py.tpl +10 -10
  49. aury/boot/commands/templates/project/env_templates/_header.tpl +10 -0
  50. aury/boot/commands/templates/project/env_templates/admin.tpl +49 -0
  51. aury/boot/commands/templates/project/env_templates/cache.tpl +14 -0
  52. aury/boot/commands/templates/project/env_templates/database.tpl +22 -0
  53. aury/boot/commands/templates/project/env_templates/log.tpl +18 -0
  54. aury/boot/commands/templates/project/env_templates/messaging.tpl +46 -0
  55. aury/boot/commands/templates/project/env_templates/rpc.tpl +28 -0
  56. aury/boot/commands/templates/project/env_templates/scheduler.tpl +18 -0
  57. aury/boot/commands/templates/project/env_templates/service.tpl +18 -0
  58. aury/boot/commands/templates/project/env_templates/storage.tpl +38 -0
  59. aury/boot/commands/templates/project/env_templates/third_party.tpl +43 -0
  60. aury/boot/commands/templates/project/modules/tasks.py.tpl +1 -1
  61. aury/boot/common/logging/__init__.py +26 -674
  62. aury/boot/common/logging/context.py +132 -0
  63. aury/boot/common/logging/decorators.py +118 -0
  64. aury/boot/common/logging/format.py +315 -0
  65. aury/boot/common/logging/setup.py +214 -0
  66. aury/boot/contrib/admin_console/auth.py +2 -3
  67. aury/boot/contrib/admin_console/install.py +1 -1
  68. aury/boot/domain/models/mixins.py +48 -1
  69. aury/boot/domain/pagination/__init__.py +94 -0
  70. aury/boot/domain/repository/impl.py +1 -1
  71. aury/boot/domain/repository/interface.py +1 -1
  72. aury/boot/domain/transaction/__init__.py +8 -9
  73. aury/boot/infrastructure/__init__.py +86 -29
  74. aury/boot/infrastructure/cache/backends.py +102 -18
  75. aury/boot/infrastructure/cache/base.py +12 -0
  76. aury/boot/infrastructure/cache/manager.py +153 -91
  77. aury/boot/infrastructure/channel/__init__.py +24 -0
  78. aury/boot/infrastructure/channel/backends/__init__.py +9 -0
  79. aury/boot/infrastructure/channel/backends/memory.py +83 -0
  80. aury/boot/infrastructure/channel/backends/redis.py +88 -0
  81. aury/boot/infrastructure/channel/base.py +92 -0
  82. aury/boot/infrastructure/channel/manager.py +203 -0
  83. aury/boot/infrastructure/clients/__init__.py +22 -0
  84. aury/boot/infrastructure/clients/rabbitmq/__init__.py +9 -0
  85. aury/boot/infrastructure/clients/rabbitmq/config.py +46 -0
  86. aury/boot/infrastructure/clients/rabbitmq/manager.py +288 -0
  87. aury/boot/infrastructure/clients/redis/__init__.py +28 -0
  88. aury/boot/infrastructure/clients/redis/config.py +51 -0
  89. aury/boot/infrastructure/clients/redis/manager.py +264 -0
  90. aury/boot/infrastructure/database/config.py +7 -16
  91. aury/boot/infrastructure/database/manager.py +16 -38
  92. aury/boot/infrastructure/events/__init__.py +18 -21
  93. aury/boot/infrastructure/events/backends/__init__.py +11 -0
  94. aury/boot/infrastructure/events/backends/memory.py +86 -0
  95. aury/boot/infrastructure/events/backends/rabbitmq.py +193 -0
  96. aury/boot/infrastructure/events/backends/redis.py +162 -0
  97. aury/boot/infrastructure/events/base.py +127 -0
  98. aury/boot/infrastructure/events/manager.py +224 -0
  99. aury/boot/infrastructure/mq/__init__.py +24 -0
  100. aury/boot/infrastructure/mq/backends/__init__.py +9 -0
  101. aury/boot/infrastructure/mq/backends/rabbitmq.py +179 -0
  102. aury/boot/infrastructure/mq/backends/redis.py +167 -0
  103. aury/boot/infrastructure/mq/base.py +143 -0
  104. aury/boot/infrastructure/mq/manager.py +239 -0
  105. aury/boot/infrastructure/scheduler/manager.py +7 -3
  106. aury/boot/infrastructure/storage/__init__.py +9 -9
  107. aury/boot/infrastructure/storage/base.py +17 -5
  108. aury/boot/infrastructure/storage/factory.py +0 -1
  109. aury/boot/infrastructure/tasks/__init__.py +2 -2
  110. aury/boot/infrastructure/tasks/config.py +5 -13
  111. aury/boot/infrastructure/tasks/manager.py +55 -33
  112. {aury_boot-0.0.4.dist-info → aury_boot-0.0.7.dist-info}/METADATA +20 -2
  113. aury_boot-0.0.7.dist-info/RECORD +197 -0
  114. aury/boot/commands/templates/project/DEVELOPMENT.md.tpl +0 -1397
  115. aury/boot/commands/templates/project/env.example.tpl +0 -213
  116. aury/boot/infrastructure/events/bus.py +0 -362
  117. aury/boot/infrastructure/events/config.py +0 -52
  118. aury/boot/infrastructure/events/consumer.py +0 -134
  119. aury/boot/infrastructure/events/models.py +0 -63
  120. aury_boot-0.0.4.dist-info/RECORD +0 -137
  121. {aury_boot-0.0.4.dist-info → aury_boot-0.0.7.dist-info}/WHEEL +0 -0
  122. {aury_boot-0.0.4.dist-info → aury_boot-0.0.7.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,104 @@
1
+ # 流式通道(Channel)
2
+
3
+ 用于 SSE(Server-Sent Events)和实时通信。支持 memory 和 redis 后端。
4
+
5
+ ## 核心概念
6
+
7
+ - **ChannelManager**:管理器,支持命名多实例(如 sse、notification 独立管理)
8
+ - **channel 参数**:通道名/Topic,用于区分不同的消息流(如 `user:123`、`order:456`)
9
+
10
+ ## 13.1 基本用法
11
+
12
+ ```python
13
+ from aury.boot.infrastructure.channel import ChannelManager
14
+
15
+ # 命名多实例(推荐)- 不同业务场景使用不同实例
16
+ sse_channel = ChannelManager.get_instance("sse")
17
+ notification_channel = ChannelManager.get_instance("notification")
18
+
19
+ # Memory 后端(单进程)
20
+ await sse_channel.initialize(backend="memory")
21
+
22
+ # Redis 后端(多进程/分布式)
23
+ from aury.boot.infrastructure.clients.redis import RedisClient
24
+ redis_client = RedisClient.get_instance()
25
+ await redis_client.initialize(url="redis://localhost:6379/0")
26
+ await notification_channel.initialize(backend="redis", redis_client=redis_client)
27
+ ```
28
+
29
+ ## 13.2 发布和订阅(Topic 管理)
30
+
31
+ ```python
32
+ # 发布消息到指定 Topic
33
+ await sse_channel.publish("user:123", {{"event": "message", "data": "hello"}})
34
+ await sse_channel.publish("order:456", {{"status": "shipped"}})
35
+
36
+ # 发布到多个用户
37
+ for user_id in user_ids:
38
+ await sse_channel.publish(f"user:{{user_id}}", notification)
39
+ ```
40
+
41
+ ## 13.3 SSE 端点示例
42
+
43
+ **文件**: `{package_name}/api/sse.py`
44
+
45
+ ```python
46
+ import json
47
+ from fastapi import APIRouter
48
+ from fastapi.responses import StreamingResponse
49
+ from aury.boot.infrastructure.channel import ChannelManager
50
+
51
+ router = APIRouter(tags=["SSE"])
52
+
53
+ # 获取命名实例(在 app 启动时已初始化)
54
+ sse_channel = ChannelManager.get_instance("sse")
55
+
56
+
57
+ @router.get("/sse/{{user_id}}")
58
+ async def sse_stream(user_id: str):
59
+ \"\"\"SSE 实时消息流。\"\"\"
60
+ async def event_generator():
61
+ # user_id 作为 Topic,区分不同用户的消息流
62
+ async for message in sse_channel.subscribe(f"user:{{user_id}}"):
63
+ yield f"data: {{json.dumps(message)}}\n\n"
64
+
65
+ return StreamingResponse(
66
+ event_generator(),
67
+ media_type="text/event-stream",
68
+ headers={{"Cache-Control": "no-cache", "Connection": "keep-alive"}}
69
+ )
70
+
71
+
72
+ @router.post("/notify/{{user_id}}")
73
+ async def send_notification(user_id: str, message: str):
74
+ \"\"\"\u53d1\u9001\u901a\u77e5\u3002\"\"\"
75
+ await sse_channel.publish(f"user:{{user_id}}", {{"message": message}})
76
+ return {{"status": "sent"}}
77
+ ```
78
+
79
+ ## 13.4 应用场景示例
80
+
81
+ ```python
82
+ # 不同业务场景使用不同的命名实例
83
+ sse_channel = ChannelManager.get_instance("sse") # 前端 SSE 推送
84
+ chat_channel = ChannelManager.get_instance("chat") # 聊天消息
85
+ notify_channel = ChannelManager.get_instance("notify") # 系统通知
86
+
87
+ # 分别初始化(可使用不同后端)
88
+ await sse_channel.initialize(backend="memory") # 单进程即可
89
+ await chat_channel.initialize(backend="redis", redis_client=redis_client) # 需要跨进程
90
+ await notify_channel.initialize(backend="redis", redis_client=redis_client)
91
+ ```
92
+
93
+ ## 13.5 环境变量
94
+
95
+ ```bash
96
+ # 默认实例
97
+ CHANNEL__BACKEND=memory
98
+
99
+ # 多实例(格式:CHANNEL__{{INSTANCE}}__{{FIELD}})
100
+ CHANNEL__DEFAULT__BACKEND=redis
101
+ CHANNEL__DEFAULT__URL=redis://localhost:6379/3
102
+ CHANNEL__NOTIFICATIONS__BACKEND=redis
103
+ CHANNEL__NOTIFICATIONS__URL=redis://localhost:6379/4
104
+ ```
@@ -0,0 +1,102 @@
1
+ # 消息队列(MQ)
2
+
3
+ 支持 `redis` 和 `rabbitmq` 后端的消息队列,用于异步任务解耦。
4
+
5
+ ## 14.1 基本用法
6
+
7
+ ```python
8
+ from aury.boot.infrastructure.mq import MQManager
9
+
10
+ # 获取实例
11
+ mq = MQManager.get_instance()
12
+
13
+ # Redis 后端
14
+ await mq.initialize(backend="redis", url="redis://localhost:6379/0")
15
+
16
+ # RabbitMQ 后端
17
+ await mq.initialize(backend="rabbitmq", url="amqp://guest:guest@localhost:5672/")
18
+ ```
19
+
20
+ ## 14.2 生产者
21
+
22
+ ```python
23
+ # 发送消息
24
+ await mq.publish(
25
+ queue="orders",
26
+ message={{"order_id": "123", "action": "created"}}
27
+ )
28
+
29
+ # 批量发送
30
+ await mq.publish_batch(
31
+ queue="orders",
32
+ messages=[
33
+ {{"order_id": "1", "action": "created"}},
34
+ {{"order_id": "2", "action": "updated"}},
35
+ ]
36
+ )
37
+ ```
38
+
39
+ ## 14.3 消费者
40
+
41
+ **文件**: `{package_name}/workers/order_worker.py`
42
+
43
+ ```python
44
+ from aury.boot.infrastructure.mq import MQManager
45
+ from aury.boot.common.logging import logger
46
+
47
+ mq = MQManager.get_instance()
48
+
49
+
50
+ async def process_order(message: dict):
51
+ \"\"\"处理订单消息。\"\"\"
52
+ logger.info(f"处理订单: {{message['order_id']}}")
53
+ # 业务逻辑...
54
+
55
+
56
+ async def start_consumer():
57
+ \"\"\"启动消费者。\"\"\"
58
+ await mq.consume("orders", process_order)
59
+
60
+
61
+ # 带确认的消费
62
+ async def process_with_ack(message: dict, ack, nack):
63
+ try:
64
+ await process_order(message)
65
+ await ack()
66
+ except Exception:
67
+ await nack(requeue=True)
68
+
69
+ await mq.consume("orders", process_with_ack, auto_ack=False)
70
+ ```
71
+
72
+ ## 14.4 多实例
73
+
74
+ ```python
75
+ # 不同用途的 MQ 实例
76
+ orders_mq = MQManager.get_instance("orders")
77
+ notifications_mq = MQManager.get_instance("notifications")
78
+
79
+ # 分别初始化
80
+ await orders_mq.initialize(backend="rabbitmq", url="amqp://localhost:5672/orders")
81
+ await notifications_mq.initialize(backend="redis", url="redis://localhost:6379/5")
82
+ ```
83
+
84
+ ## 14.5 环境变量
85
+
86
+ ```bash
87
+ # 默认实例
88
+ MQ__BACKEND=redis
89
+ MQ__URL=redis://localhost:6379/0
90
+
91
+ # 多实例(格式:MQ__{{INSTANCE}}__{{FIELD}})
92
+ MQ__DEFAULT__BACKEND=redis
93
+ MQ__DEFAULT__URL=redis://localhost:6379/4
94
+ MQ__ORDERS__BACKEND=rabbitmq
95
+ MQ__ORDERS__URL=amqp://guest:guest@localhost:5672/
96
+ MQ__ORDERS__PREFETCH_COUNT=10
97
+ ```
98
+
99
+ ## 14.6 与异步任务(Dramatiq)的区别
100
+
101
+ - **MQ**:轻量级消息传递,适合简单的生产者-消费者模式
102
+ - **Dramatiq(TaskManager)**:功能更丰富,支持重试、延迟、优先级等
@@ -0,0 +1,147 @@
1
+ # 事件总线(Events)
2
+
3
+ 支持 `memory`、`redis`、`rabbitmq` 后端的事件发布订阅系统。
4
+
5
+ ## 15.1 定义事件
6
+
7
+ **文件**: `{package_name}/events/__init__.py`
8
+
9
+ ```python
10
+ from aury.boot.infrastructure.events import Event
11
+
12
+
13
+ class OrderCreatedEvent(Event):
14
+ \"\"\"订单创建事件。\"\"\"
15
+ order_id: str
16
+ amount: float
17
+ user_id: str
18
+
19
+ @property
20
+ def event_name(self) -> str:
21
+ return "order.created"
22
+
23
+
24
+ class UserRegisteredEvent(Event):
25
+ \"\"\"用户注册事件。\"\"\"
26
+ user_id: str
27
+ email: str
28
+
29
+ @property
30
+ def event_name(self) -> str:
31
+ return "user.registered"
32
+ ```
33
+
34
+ ### 15.1.1 事件初始化
35
+
36
+ 事件类基于 Pydantic BaseModel,支持以下初始化方式:
37
+
38
+ ```python
39
+ # 方式 1:关键字参数(推荐)
40
+ event = OrderCreatedEvent(
41
+ order_id="order-123",
42
+ amount=99.99,
43
+ user_id="user-456",
44
+ )
45
+
46
+ # 方式 2:字典解包
47
+ event = OrderCreatedEvent(**{{
48
+ "order_id": "order-123",
49
+ "amount": 99.99,
50
+ "user_id": "user-456",
51
+ }})
52
+
53
+ # 方式 3:从实体创建
54
+ event = OrderCreatedEvent(
55
+ order_id=str(order.id),
56
+ amount=order.amount,
57
+ user_id=str(order.user_id),
58
+ )
59
+ ```
60
+
61
+ ## 15.2 订阅事件
62
+
63
+ ```python
64
+ from aury.boot.infrastructure.events import EventBusManager
65
+
66
+ bus = EventBusManager.get_instance()
67
+
68
+
69
+ @bus.subscribe(OrderCreatedEvent)
70
+ async def on_order_created(event: OrderCreatedEvent):
71
+ \"\"\"处理订单创建事件。\"\"\"
72
+ logger.info(f"订单创建: {{event.order_id}}, 金额: {{event.amount}}")
73
+ # 发送通知、更新统计等...
74
+
75
+
76
+ @bus.subscribe(UserRegisteredEvent)
77
+ async def send_welcome_email(event: UserRegisteredEvent):
78
+ \"\"\"发送欢迎邮件。\"\"\"
79
+ await email_service.send_welcome(event.email)
80
+ ```
81
+
82
+ ## 15.3 发布事件
83
+
84
+ ```python
85
+ from {package_name}.events import OrderCreatedEvent
86
+
87
+ @router.post("/orders")
88
+ async def create_order(request: OrderCreateRequest):
89
+ # 创建订单
90
+ order = await order_service.create(request)
91
+
92
+ # 发布事件
93
+ await bus.publish(OrderCreatedEvent(
94
+ order_id=order.id,
95
+ amount=order.amount,
96
+ user_id=order.user_id
97
+ ))
98
+
99
+ return BaseResponse(code=200, message="订单创建成功", data=order)
100
+ ```
101
+
102
+ ## 15.4 多实例(EventBusManager)
103
+
104
+ ```python
105
+ from aury.boot.infrastructure.events import EventBusManager
106
+
107
+ # 获取实例
108
+ bus = EventBusManager.get_instance()
109
+ domain_bus = EventBusManager.get_instance("domain")
110
+
111
+ # Memory 后端(单进程)
112
+ await bus.initialize(backend="memory")
113
+
114
+ # Redis Pub/Sub 后端
115
+ await bus.initialize(
116
+ backend="redis",
117
+ url="redis://localhost:6379/0",
118
+ channel_prefix="events:",
119
+ )
120
+
121
+ # RabbitMQ 后端
122
+ await bus.initialize(
123
+ backend="rabbitmq",
124
+ url="amqp://guest:guest@localhost:5672/",
125
+ exchange_name="app.events",
126
+ )
127
+ ```
128
+
129
+ ## 15.5 环境变量
130
+
131
+ ```bash
132
+ # 默认实例
133
+ EVENT__BACKEND=memory
134
+
135
+ # 多实例(格式:EVENT__{{INSTANCE}}__{{FIELD}})
136
+ EVENT__DEFAULT__BACKEND=redis
137
+ EVENT__DEFAULT__URL=redis://localhost:6379/5
138
+ EVENT__DOMAIN__BACKEND=rabbitmq
139
+ EVENT__DOMAIN__URL=amqp://guest:guest@localhost:5672/
140
+ EVENT__DOMAIN__EXCHANGE_NAME=domain.events
141
+ ```
142
+
143
+ ## 15.6 最佳实践
144
+
145
+ 1. **事件应该是不可变的** - 使用 Pydantic 的 `frozen=True`
146
+ 2. **订阅者应该快速完成** - 耗时操作使用任务队列
147
+ 3. **避免循环事件** - 不要在订阅者中发布相同类型的事件