aury-boot 0.0.5__py3-none-any.whl → 0.0.8__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 +2 -2
- aury/boot/application/__init__.py +15 -0
- aury/boot/application/adapter/__init__.py +112 -0
- aury/boot/application/adapter/base.py +511 -0
- aury/boot/application/adapter/config.py +242 -0
- aury/boot/application/adapter/decorators.py +259 -0
- aury/boot/application/adapter/exceptions.py +202 -0
- aury/boot/application/adapter/http.py +325 -0
- aury/boot/application/app/middlewares.py +7 -4
- aury/boot/application/config/multi_instance.py +42 -26
- aury/boot/application/config/settings.py +111 -191
- aury/boot/application/middleware/logging.py +14 -1
- aury/boot/commands/generate.py +22 -22
- aury/boot/commands/init.py +41 -9
- aury/boot/commands/templates/project/AGENTS.md.tpl +8 -4
- aury/boot/commands/templates/project/aury_docs/01-model.md.tpl +17 -16
- aury/boot/commands/templates/project/aury_docs/11-logging.md.tpl +82 -43
- aury/boot/commands/templates/project/aury_docs/12-admin.md.tpl +14 -14
- aury/boot/commands/templates/project/aury_docs/13-channel.md.tpl +40 -28
- aury/boot/commands/templates/project/aury_docs/14-mq.md.tpl +9 -9
- aury/boot/commands/templates/project/aury_docs/15-events.md.tpl +8 -8
- aury/boot/commands/templates/project/aury_docs/16-adapter.md.tpl +403 -0
- aury/boot/commands/templates/project/aury_docs/99-cli.md.tpl +19 -19
- aury/boot/commands/templates/project/config.py.tpl +10 -10
- aury/boot/commands/templates/project/env_templates/_header.tpl +10 -0
- aury/boot/commands/templates/project/env_templates/admin.tpl +49 -0
- aury/boot/commands/templates/project/env_templates/cache.tpl +14 -0
- aury/boot/commands/templates/project/env_templates/database.tpl +22 -0
- aury/boot/commands/templates/project/env_templates/log.tpl +18 -0
- aury/boot/commands/templates/project/env_templates/messaging.tpl +46 -0
- aury/boot/commands/templates/project/env_templates/rpc.tpl +28 -0
- aury/boot/commands/templates/project/env_templates/scheduler.tpl +18 -0
- aury/boot/commands/templates/project/env_templates/service.tpl +18 -0
- aury/boot/commands/templates/project/env_templates/storage.tpl +38 -0
- aury/boot/commands/templates/project/env_templates/third_party.tpl +43 -0
- aury/boot/common/logging/__init__.py +26 -674
- aury/boot/common/logging/context.py +132 -0
- aury/boot/common/logging/decorators.py +118 -0
- aury/boot/common/logging/format.py +315 -0
- aury/boot/common/logging/setup.py +214 -0
- aury/boot/infrastructure/database/config.py +6 -14
- aury/boot/infrastructure/tasks/config.py +5 -13
- aury/boot/infrastructure/tasks/manager.py +8 -4
- aury/boot/testing/base.py +2 -2
- {aury_boot-0.0.5.dist-info → aury_boot-0.0.8.dist-info}/METADATA +2 -1
- {aury_boot-0.0.5.dist-info → aury_boot-0.0.8.dist-info}/RECORD +48 -27
- aury/boot/commands/templates/project/env.example.tpl +0 -281
- {aury_boot-0.0.5.dist-info → aury_boot-0.0.8.dist-info}/WHEEL +0 -0
- {aury_boot-0.0.5.dist-info → aury_boot-0.0.8.dist-info}/entry_points.txt +0 -0
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
|
12
12
|
from typing import Any, Literal
|
|
13
13
|
|
|
14
14
|
from dotenv import load_dotenv
|
|
15
|
-
from pydantic import Field
|
|
15
|
+
from pydantic import BaseModel, Field
|
|
16
16
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
17
17
|
|
|
18
18
|
from .multi_instance import MultiInstanceConfigLoader, MultiInstanceSettings
|
|
@@ -31,11 +31,11 @@ def _load_env_file(env_file: str | Path) -> bool:
|
|
|
31
31
|
class DatabaseInstanceConfig(MultiInstanceSettings):
|
|
32
32
|
"""数据库实例配置。
|
|
33
33
|
|
|
34
|
-
环境变量格式:
|
|
34
|
+
环境变量格式: DATABASE__{INSTANCE}__{FIELD}
|
|
35
35
|
示例:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
DATABASE__DEFAULT__URL=postgresql://main...
|
|
37
|
+
DATABASE__DEFAULT__POOL_SIZE=10
|
|
38
|
+
DATABASE__ANALYTICS__URL=postgresql://analytics...
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
41
|
url: str = Field(
|
|
@@ -71,12 +71,12 @@ class DatabaseInstanceConfig(MultiInstanceSettings):
|
|
|
71
71
|
class CacheInstanceConfig(MultiInstanceSettings):
|
|
72
72
|
"""缓存实例配置。
|
|
73
73
|
|
|
74
|
-
环境变量格式:
|
|
74
|
+
环境变量格式: CACHE__{INSTANCE}__{FIELD}
|
|
75
75
|
示例:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
CACHE__DEFAULT__BACKEND=redis
|
|
77
|
+
CACHE__DEFAULT__URL=redis://localhost:6379/0
|
|
78
|
+
CACHE__LOCAL__BACKEND=memory
|
|
79
|
+
CACHE__LOCAL__MAX_SIZE=5000
|
|
80
80
|
"""
|
|
81
81
|
|
|
82
82
|
backend: str = Field(
|
|
@@ -96,12 +96,12 @@ class CacheInstanceConfig(MultiInstanceSettings):
|
|
|
96
96
|
class StorageInstanceConfig(MultiInstanceSettings):
|
|
97
97
|
"""对象存储实例配置。
|
|
98
98
|
|
|
99
|
-
环境变量格式:
|
|
99
|
+
环境变量格式: STORAGE__{INSTANCE}__{FIELD}
|
|
100
100
|
示例:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
STORAGE__DEFAULT__BACKEND=s3
|
|
102
|
+
STORAGE__DEFAULT__BUCKET=main-bucket
|
|
103
|
+
STORAGE__BACKUP__BACKEND=local
|
|
104
|
+
STORAGE__BACKUP__BASE_PATH=/backup
|
|
105
105
|
"""
|
|
106
106
|
|
|
107
107
|
backend: Literal["local", "s3", "oss", "cos"] = Field(
|
|
@@ -121,11 +121,11 @@ class StorageInstanceConfig(MultiInstanceSettings):
|
|
|
121
121
|
class ChannelInstanceConfig(MultiInstanceSettings):
|
|
122
122
|
"""通道实例配置。
|
|
123
123
|
|
|
124
|
-
环境变量格式:
|
|
124
|
+
环境变量格式: CHANNEL__{INSTANCE}__{FIELD}
|
|
125
125
|
示例:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
CHANNEL__DEFAULT__BACKEND=memory
|
|
127
|
+
CHANNEL__SHARED__BACKEND=redis
|
|
128
|
+
CHANNEL__SHARED__URL=redis://localhost:6379/3
|
|
129
129
|
"""
|
|
130
130
|
|
|
131
131
|
backend: str = Field(
|
|
@@ -141,10 +141,10 @@ class ChannelInstanceConfig(MultiInstanceSettings):
|
|
|
141
141
|
class MQInstanceConfig(MultiInstanceSettings):
|
|
142
142
|
"""消息队列实例配置。
|
|
143
143
|
|
|
144
|
-
环境变量格式:
|
|
144
|
+
环境变量格式: MQ__{INSTANCE}__{FIELD}
|
|
145
145
|
示例:
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
MQ__DEFAULT__BACKEND=redis
|
|
147
|
+
MQ__DEFAULT__URL=redis://localhost:6379/4
|
|
148
148
|
"""
|
|
149
149
|
|
|
150
150
|
backend: str = Field(
|
|
@@ -160,11 +160,11 @@ class MQInstanceConfig(MultiInstanceSettings):
|
|
|
160
160
|
class EventInstanceConfig(MultiInstanceSettings):
|
|
161
161
|
"""事件总线实例配置。
|
|
162
162
|
|
|
163
|
-
环境变量格式:
|
|
163
|
+
环境变量格式: EVENT__{INSTANCE}__{FIELD}
|
|
164
164
|
示例:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
EVENT__DEFAULT__BACKEND=memory
|
|
166
|
+
EVENT__DISTRIBUTED__BACKEND=redis
|
|
167
|
+
EVENT__DISTRIBUTED__URL=redis://localhost:6379/5
|
|
168
168
|
"""
|
|
169
169
|
|
|
170
170
|
backend: str = Field(
|
|
@@ -182,10 +182,12 @@ class EventInstanceConfig(MultiInstanceSettings):
|
|
|
182
182
|
# =============================================================================
|
|
183
183
|
|
|
184
184
|
|
|
185
|
-
class DatabaseSettings(
|
|
185
|
+
class DatabaseSettings(BaseModel):
|
|
186
186
|
"""数据库配置(单实例)。
|
|
187
187
|
|
|
188
|
-
|
|
188
|
+
环境变量格式: DATABASE__{FIELD}
|
|
189
|
+
示例: DATABASE__URL, DATABASE__POOL_SIZE
|
|
190
|
+
多实例格式: DATABASE__{INSTANCE}__{FIELD}
|
|
189
191
|
"""
|
|
190
192
|
|
|
191
193
|
url: str = Field(
|
|
@@ -216,23 +218,18 @@ class DatabaseSettings(BaseSettings):
|
|
|
216
218
|
default=True,
|
|
217
219
|
description="是否在获取连接前进行 PING"
|
|
218
220
|
)
|
|
219
|
-
|
|
220
|
-
model_config = SettingsConfigDict(
|
|
221
|
-
env_prefix="DATABASE_",
|
|
222
|
-
case_sensitive=False,
|
|
223
|
-
)
|
|
224
221
|
|
|
225
222
|
|
|
226
|
-
class CacheSettings(
|
|
223
|
+
class CacheSettings(BaseModel):
|
|
227
224
|
"""缓存配置。
|
|
228
225
|
|
|
229
|
-
|
|
230
|
-
示例:
|
|
226
|
+
环境变量格式: CACHE__{FIELD}
|
|
227
|
+
示例: CACHE__TYPE, CACHE__URL, CACHE__MAX_SIZE
|
|
231
228
|
|
|
232
229
|
支持的缓存类型:
|
|
233
230
|
- memory: 内存缓存(默认,无需 URL)
|
|
234
|
-
- redis: Redis 缓存(需要设置
|
|
235
|
-
- memcached: Memcached 缓存(需要设置
|
|
231
|
+
- redis: Redis 缓存(需要设置 CACHE__URL)
|
|
232
|
+
- memcached: Memcached 缓存(需要设置 CACHE__URL)
|
|
236
233
|
"""
|
|
237
234
|
|
|
238
235
|
cache_type: str = Field(
|
|
@@ -247,22 +244,14 @@ class CacheSettings(BaseSettings):
|
|
|
247
244
|
default=1000,
|
|
248
245
|
description="内存缓存最大大小"
|
|
249
246
|
)
|
|
250
|
-
|
|
251
|
-
model_config = SettingsConfigDict(
|
|
252
|
-
env_prefix="CACHE_",
|
|
253
|
-
case_sensitive=False,
|
|
254
|
-
)
|
|
255
247
|
|
|
256
248
|
|
|
257
|
-
class StorageSettings(
|
|
249
|
+
class StorageSettings(BaseModel):
|
|
258
250
|
"""对象存储组件接入配置(Application 层)。
|
|
259
251
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
环境变量前缀:STORAGE_
|
|
265
|
-
"""
|
|
252
|
+
环境变量格式: STORAGE__{FIELD}
|
|
253
|
+
示例: STORAGE__TYPE, STORAGE__BUCKET_NAME
|
|
254
|
+
"""
|
|
266
255
|
|
|
267
256
|
enabled: bool = Field(default=True, description="是否启用存储组件")
|
|
268
257
|
|
|
@@ -289,22 +278,16 @@ class StorageSettings(BaseSettings):
|
|
|
289
278
|
# local
|
|
290
279
|
base_path: str = Field(default="./storage", description="本地存储基础目录")
|
|
291
280
|
|
|
292
|
-
model_config = SettingsConfigDict(
|
|
293
|
-
env_prefix="STORAGE_",
|
|
294
|
-
case_sensitive=False,
|
|
295
|
-
extra="ignore",
|
|
296
|
-
)
|
|
297
281
|
|
|
298
|
-
|
|
299
|
-
class ServerSettings(BaseSettings):
|
|
282
|
+
class ServerSettings(BaseModel):
|
|
300
283
|
"""服务器配置。
|
|
301
284
|
|
|
302
|
-
|
|
303
|
-
示例:
|
|
285
|
+
环境变量格式: SERVER__{FIELD}
|
|
286
|
+
示例: SERVER__HOST, SERVER__PORT, SERVER__RELOAD
|
|
304
287
|
"""
|
|
305
288
|
|
|
306
289
|
host: str = Field(
|
|
307
|
-
default="
|
|
290
|
+
default="0.0.0.0",
|
|
308
291
|
description="服务器监听地址"
|
|
309
292
|
)
|
|
310
293
|
port: int = Field(
|
|
@@ -319,18 +302,13 @@ class ServerSettings(BaseSettings):
|
|
|
319
302
|
default=1,
|
|
320
303
|
description="工作进程数"
|
|
321
304
|
)
|
|
322
|
-
|
|
323
|
-
model_config = SettingsConfigDict(
|
|
324
|
-
env_prefix="SERVER_",
|
|
325
|
-
case_sensitive=False,
|
|
326
|
-
)
|
|
327
305
|
|
|
328
306
|
|
|
329
|
-
class CORSSettings(
|
|
307
|
+
class CORSSettings(BaseModel):
|
|
330
308
|
"""CORS配置。
|
|
331
309
|
|
|
332
|
-
|
|
333
|
-
示例:
|
|
310
|
+
环境变量格式: CORS__{FIELD}
|
|
311
|
+
示例: CORS__ORIGINS, CORS__ALLOW_CREDENTIALS, CORS__ALLOW_METHODS
|
|
334
312
|
"""
|
|
335
313
|
|
|
336
314
|
origins: list[str] = Field(
|
|
@@ -349,18 +327,13 @@ class CORSSettings(BaseSettings):
|
|
|
349
327
|
default=["*"],
|
|
350
328
|
description="允许的CORS头"
|
|
351
329
|
)
|
|
352
|
-
|
|
353
|
-
model_config = SettingsConfigDict(
|
|
354
|
-
env_prefix="CORS_",
|
|
355
|
-
case_sensitive=False,
|
|
356
|
-
)
|
|
357
330
|
|
|
358
331
|
|
|
359
|
-
class LogSettings(
|
|
332
|
+
class LogSettings(BaseModel):
|
|
360
333
|
"""日志配置。
|
|
361
334
|
|
|
362
|
-
|
|
363
|
-
示例:
|
|
335
|
+
环境变量格式: LOG__{FIELD}
|
|
336
|
+
示例: LOG__LEVEL, LOG__DIR, LOG__ROTATION_TIME, LOG__RETENTION_DAYS
|
|
364
337
|
"""
|
|
365
338
|
|
|
366
339
|
level: str = Field(
|
|
@@ -399,24 +372,19 @@ class LogSettings(BaseSettings):
|
|
|
399
372
|
default=False,
|
|
400
373
|
description="是否记录 WebSocket 消息内容(注意性能和敏感数据)"
|
|
401
374
|
)
|
|
402
|
-
|
|
403
|
-
model_config = SettingsConfigDict(
|
|
404
|
-
env_prefix="LOG_",
|
|
405
|
-
case_sensitive=False,
|
|
406
|
-
)
|
|
407
375
|
|
|
408
376
|
|
|
409
|
-
class ServiceSettings(
|
|
377
|
+
class ServiceSettings(BaseModel):
|
|
410
378
|
"""服务配置。
|
|
411
379
|
|
|
412
|
-
|
|
413
|
-
示例:
|
|
380
|
+
环境变量格式: SERVICE__{FIELD}
|
|
381
|
+
示例: SERVICE__NAME, SERVICE__TYPE
|
|
414
382
|
|
|
415
383
|
服务类型说明:
|
|
416
|
-
- api: 运行 API 服务(
|
|
384
|
+
- api: 运行 API 服务(SCHEDULER__ENABLED 决定是否同时运行调度器)
|
|
417
385
|
- worker: 运行任务队列 Worker(处理异步任务)
|
|
418
386
|
|
|
419
|
-
独立调度器通过 `aury scheduler` 命令运行,不需要配置
|
|
387
|
+
独立调度器通过 `aury scheduler` 命令运行,不需要配置 SERVICE__TYPE。
|
|
420
388
|
"""
|
|
421
389
|
|
|
422
390
|
name: str = Field(
|
|
@@ -428,21 +396,16 @@ class ServiceSettings(BaseSettings):
|
|
|
428
396
|
description="服务类型(api/worker)"
|
|
429
397
|
)
|
|
430
398
|
|
|
431
|
-
model_config = SettingsConfigDict(
|
|
432
|
-
env_prefix="SERVICE_",
|
|
433
|
-
case_sensitive=False,
|
|
434
|
-
)
|
|
435
399
|
|
|
436
|
-
|
|
437
|
-
class SchedulerSettings(BaseSettings):
|
|
400
|
+
class SchedulerSettings(BaseModel):
|
|
438
401
|
"""调度器配置。
|
|
439
402
|
|
|
440
|
-
|
|
441
|
-
示例:
|
|
403
|
+
环境变量格式: SCHEDULER__{FIELD}
|
|
404
|
+
示例: SCHEDULER__ENABLED, SCHEDULER__SCHEDULE_MODULES
|
|
442
405
|
|
|
443
|
-
仅在
|
|
444
|
-
-
|
|
445
|
-
-
|
|
406
|
+
仅在 SERVICE__TYPE=api 时有效:
|
|
407
|
+
- SCHEDULER__ENABLED=true: API 服务同时运行内嵌调度器(默认)
|
|
408
|
+
- SCHEDULER__ENABLED=false: 只运行 API,不启动调度器
|
|
446
409
|
|
|
447
410
|
独立调度器通过 `aury scheduler` 命令运行,不需要此配置。
|
|
448
411
|
"""
|
|
@@ -455,18 +418,13 @@ class SchedulerSettings(BaseSettings):
|
|
|
455
418
|
default_factory=list,
|
|
456
419
|
description="定时任务模块列表。为空时自动发现 schedules 模块"
|
|
457
420
|
)
|
|
458
|
-
|
|
459
|
-
model_config = SettingsConfigDict(
|
|
460
|
-
env_prefix="SCHEDULER_",
|
|
461
|
-
case_sensitive=False,
|
|
462
|
-
)
|
|
463
421
|
|
|
464
422
|
|
|
465
|
-
class TaskSettings(
|
|
423
|
+
class TaskSettings(BaseModel):
|
|
466
424
|
"""任务队列配置。
|
|
467
425
|
|
|
468
|
-
|
|
469
|
-
示例:
|
|
426
|
+
环境变量格式: TASK__{FIELD}
|
|
427
|
+
示例: TASK__BROKER_URL, TASK__MAX_RETRIES
|
|
470
428
|
"""
|
|
471
429
|
|
|
472
430
|
broker_url: str | None = Field(
|
|
@@ -481,18 +439,13 @@ class TaskSettings(BaseSettings):
|
|
|
481
439
|
default=3600,
|
|
482
440
|
description="任务超时时间(秒)"
|
|
483
441
|
)
|
|
484
|
-
|
|
485
|
-
model_config = SettingsConfigDict(
|
|
486
|
-
env_prefix="TASK_",
|
|
487
|
-
case_sensitive=False,
|
|
488
|
-
)
|
|
489
442
|
|
|
490
443
|
|
|
491
|
-
class EventSettings(
|
|
444
|
+
class EventSettings(BaseModel):
|
|
492
445
|
"""事件总线配置。
|
|
493
446
|
|
|
494
|
-
|
|
495
|
-
示例:
|
|
447
|
+
环境变量格式: EVENT__{FIELD}
|
|
448
|
+
示例: EVENT__BROKER_URL, EVENT__EXCHANGE_NAME
|
|
496
449
|
"""
|
|
497
450
|
|
|
498
451
|
broker_url: str | None = Field(
|
|
@@ -503,18 +456,13 @@ class EventSettings(BaseSettings):
|
|
|
503
456
|
default="aury.events",
|
|
504
457
|
description="事件交换机名称"
|
|
505
458
|
)
|
|
506
|
-
|
|
507
|
-
model_config = SettingsConfigDict(
|
|
508
|
-
env_prefix="EVENT_",
|
|
509
|
-
case_sensitive=False,
|
|
510
|
-
)
|
|
511
459
|
|
|
512
460
|
|
|
513
|
-
class MessageQueueSettings(
|
|
461
|
+
class MessageQueueSettings(BaseModel):
|
|
514
462
|
"""消息队列配置。
|
|
515
463
|
|
|
516
|
-
|
|
517
|
-
示例:
|
|
464
|
+
环境变量格式: MQ__{FIELD}
|
|
465
|
+
示例: MQ__BROKER_URL, MQ__DEFAULT_QUEUE, MQ__SERIALIZER
|
|
518
466
|
|
|
519
467
|
与 Task(任务队列)的区别:
|
|
520
468
|
- Task: 基于 Dramatiq,用于异步任务处理(API + Worker 模式)
|
|
@@ -546,18 +494,13 @@ class MessageQueueSettings(BaseSettings):
|
|
|
546
494
|
default=1,
|
|
547
495
|
description="预取消息数量"
|
|
548
496
|
)
|
|
549
|
-
|
|
550
|
-
model_config = SettingsConfigDict(
|
|
551
|
-
env_prefix="MQ_",
|
|
552
|
-
case_sensitive=False,
|
|
553
|
-
)
|
|
554
497
|
|
|
555
498
|
|
|
556
|
-
class MigrationSettings(
|
|
499
|
+
class MigrationSettings(BaseModel):
|
|
557
500
|
"""数据库迁移配置。
|
|
558
501
|
|
|
559
|
-
|
|
560
|
-
示例:
|
|
502
|
+
环境变量格式: MIGRATION__{FIELD}
|
|
503
|
+
示例: MIGRATION__CONFIG_PATH, MIGRATION__SCRIPT_LOCATION, MIGRATION__MODEL_MODULES
|
|
561
504
|
"""
|
|
562
505
|
|
|
563
506
|
config_path: str = Field(
|
|
@@ -580,20 +523,15 @@ class MigrationSettings(BaseSettings):
|
|
|
580
523
|
default=True,
|
|
581
524
|
description="是否自动创建迁移配置和目录"
|
|
582
525
|
)
|
|
583
|
-
|
|
584
|
-
model_config = SettingsConfigDict(
|
|
585
|
-
env_prefix="MIGRATION_",
|
|
586
|
-
case_sensitive=False,
|
|
587
|
-
)
|
|
588
526
|
|
|
589
527
|
|
|
590
|
-
class RPCClientSettings(
|
|
528
|
+
class RPCClientSettings(BaseModel):
|
|
591
529
|
"""RPC 客户端调用配置。
|
|
592
530
|
|
|
593
531
|
用于配置客户端调用其他服务时的行为。
|
|
594
532
|
|
|
595
|
-
|
|
596
|
-
示例:
|
|
533
|
+
环境变量格式: RPC_CLIENT__{FIELD}
|
|
534
|
+
示例: RPC_CLIENT__SERVICES, RPC_CLIENT__TIMEOUT, RPC_CLIENT__RETRY_TIMES
|
|
597
535
|
"""
|
|
598
536
|
|
|
599
537
|
services: dict[str, str] = Field(
|
|
@@ -620,20 +558,15 @@ class RPCClientSettings(BaseSettings):
|
|
|
620
558
|
default=True,
|
|
621
559
|
description="是否在配置中找不到时使用 DNS 解析(K8s/Docker Compose 自动 DNS)"
|
|
622
560
|
)
|
|
623
|
-
|
|
624
|
-
model_config = SettingsConfigDict(
|
|
625
|
-
env_prefix="RPC_CLIENT_",
|
|
626
|
-
case_sensitive=False,
|
|
627
|
-
)
|
|
628
561
|
|
|
629
562
|
|
|
630
|
-
class RPCServiceSettings(
|
|
563
|
+
class RPCServiceSettings(BaseModel):
|
|
631
564
|
"""RPC 服务注册配置。
|
|
632
565
|
|
|
633
566
|
用于配置当前服务注册到服务注册中心时的信息。
|
|
634
567
|
|
|
635
|
-
|
|
636
|
-
示例:
|
|
568
|
+
环境变量格式: RPC_SERVICE__{FIELD}
|
|
569
|
+
示例: RPC_SERVICE__NAME, RPC_SERVICE__URL, RPC_SERVICE__HEALTH_CHECK_URL
|
|
637
570
|
"""
|
|
638
571
|
|
|
639
572
|
name: str | None = Field(
|
|
@@ -656,21 +589,16 @@ class RPCServiceSettings(BaseSettings):
|
|
|
656
589
|
default=None,
|
|
657
590
|
description="服务注册中心地址(如果使用外部注册中心)"
|
|
658
591
|
)
|
|
659
|
-
|
|
660
|
-
model_config = SettingsConfigDict(
|
|
661
|
-
env_prefix="RPC_SERVICE_",
|
|
662
|
-
case_sensitive=False,
|
|
663
|
-
)
|
|
664
592
|
|
|
665
593
|
|
|
666
|
-
class HealthCheckSettings(
|
|
594
|
+
class HealthCheckSettings(BaseModel):
|
|
667
595
|
"""健康检查配置。
|
|
668
596
|
|
|
669
597
|
用于配置 Aury 框架的默认健康检查端点。
|
|
670
598
|
注意:此配置仅用于框架内置的健康检查端点,不影响服务自身的健康检查端点。
|
|
671
599
|
|
|
672
|
-
|
|
673
|
-
示例:
|
|
600
|
+
环境变量格式: HEALTH_CHECK__{FIELD}
|
|
601
|
+
示例: HEALTH_CHECK__PATH, HEALTH_CHECK__ENABLED
|
|
674
602
|
"""
|
|
675
603
|
|
|
676
604
|
path: str = Field(
|
|
@@ -681,22 +609,17 @@ class HealthCheckSettings(BaseSettings):
|
|
|
681
609
|
default=True,
|
|
682
610
|
description="是否启用 Aury 默认健康检查端点"
|
|
683
611
|
)
|
|
684
|
-
|
|
685
|
-
model_config = SettingsConfigDict(
|
|
686
|
-
env_prefix="HEALTH_CHECK_",
|
|
687
|
-
case_sensitive=False,
|
|
688
|
-
)
|
|
689
612
|
|
|
690
613
|
|
|
691
|
-
class AdminAuthSettings(
|
|
614
|
+
class AdminAuthSettings(BaseModel):
|
|
692
615
|
"""管理后台认证配置。
|
|
693
616
|
|
|
694
|
-
|
|
695
|
-
示例:
|
|
617
|
+
作为 ADMIN 配置的子配置,环境变量格式: ADMIN__AUTH__{FIELD}
|
|
618
|
+
示例: ADMIN__AUTH__MODE, ADMIN__AUTH__SECRET_KEY, ADMIN__AUTH__BASIC_USERNAME
|
|
696
619
|
|
|
697
620
|
说明:
|
|
698
621
|
- 内置模式仅保证 basic / bearer 开箱即用
|
|
699
|
-
- jwt/custom 推荐由用户自定义 backend
|
|
622
|
+
- jwt/custom 推荐由用户自定义 backend 实现
|
|
700
623
|
"""
|
|
701
624
|
|
|
702
625
|
mode: Literal["none", "basic", "bearer", "jwt", "custom"] = Field(
|
|
@@ -723,17 +646,13 @@ class AdminAuthSettings(BaseSettings):
|
|
|
723
646
|
description='自定义认证后端导入路径,如 "yourpkg.admin_auth:backend"',
|
|
724
647
|
)
|
|
725
648
|
|
|
726
|
-
model_config = SettingsConfigDict(
|
|
727
|
-
env_prefix="ADMIN_AUTH_",
|
|
728
|
-
case_sensitive=False,
|
|
729
|
-
)
|
|
730
|
-
|
|
731
649
|
|
|
732
|
-
class AdminConsoleSettings(
|
|
650
|
+
class AdminConsoleSettings(BaseModel):
|
|
733
651
|
"""SQLAdmin 管理后台配置。
|
|
734
652
|
|
|
735
|
-
|
|
736
|
-
示例:
|
|
653
|
+
环境变量格式: ADMIN__{FIELD}
|
|
654
|
+
示例: ADMIN__ENABLED, ADMIN__PATH, ADMIN__DATABASE_URL
|
|
655
|
+
嵌套配置: ADMIN__AUTH__{FIELD}
|
|
737
656
|
"""
|
|
738
657
|
|
|
739
658
|
enabled: bool = Field(default=False, description="是否启用管理后台")
|
|
@@ -757,11 +676,6 @@ class AdminConsoleSettings(BaseSettings):
|
|
|
757
676
|
|
|
758
677
|
auth: AdminAuthSettings = Field(default_factory=AdminAuthSettings, description="管理后台认证配置")
|
|
759
678
|
|
|
760
|
-
model_config = SettingsConfigDict(
|
|
761
|
-
env_prefix="ADMIN_",
|
|
762
|
-
case_sensitive=False,
|
|
763
|
-
)
|
|
764
|
-
|
|
765
679
|
|
|
766
680
|
class BaseConfig(BaseSettings):
|
|
767
681
|
"""基础配置类。
|
|
@@ -769,17 +683,22 @@ class BaseConfig(BaseSettings):
|
|
|
769
683
|
所有应用配置的基类,提供通用配置项。
|
|
770
684
|
初始化时自动从 .env 文件加载环境变量,然后由 pydantic-settings 读取环境变量。
|
|
771
685
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
{
|
|
686
|
+
环境变量格式:
|
|
687
|
+
使用双下划线 (__) 作为层级分隔符:
|
|
688
|
+
{SECTION}__{FIELD}=value
|
|
689
|
+
{SECTION}__{NESTED}__{FIELD}=value
|
|
775
690
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
691
|
+
单实例示例:
|
|
692
|
+
SERVER__HOST=0.0.0.0
|
|
693
|
+
SERVER__PORT=8000
|
|
694
|
+
DATABASE__URL=postgresql://...
|
|
695
|
+
LOG__LEVEL=INFO
|
|
696
|
+
|
|
697
|
+
多实例示例:
|
|
698
|
+
DATABASE__DEFAULT__URL=postgresql://main...
|
|
699
|
+
DATABASE__ANALYTICS__URL=postgresql://analytics...
|
|
700
|
+
CACHE__DEFAULT__BACKEND=redis
|
|
701
|
+
CACHE__REDIS__URL=redis://localhost:6379/1
|
|
783
702
|
|
|
784
703
|
注意:Application 层配置完全独立,不依赖 Infrastructure 层。
|
|
785
704
|
"""
|
|
@@ -848,6 +767,7 @@ class BaseConfig(BaseSettings):
|
|
|
848
767
|
model_config = SettingsConfigDict(
|
|
849
768
|
case_sensitive=False,
|
|
850
769
|
extra="ignore",
|
|
770
|
+
env_nested_delimiter="__",
|
|
851
771
|
)
|
|
852
772
|
|
|
853
773
|
# ========== 多实例配置访问方法 ==========
|
|
@@ -855,7 +775,7 @@ class BaseConfig(BaseSettings):
|
|
|
855
775
|
def get_databases(self) -> dict[str, DatabaseInstanceConfig]:
|
|
856
776
|
"""获取所有数据库实例配置。
|
|
857
777
|
|
|
858
|
-
从环境变量解析
|
|
778
|
+
从环境变量解析 DATABASE__{INSTANCE}__{FIELD} 格式的配置。
|
|
859
779
|
如果没有配置多实例,返回从单实例配置转换的 default 实例。
|
|
860
780
|
"""
|
|
861
781
|
if self._databases is None:
|
|
@@ -878,7 +798,7 @@ class BaseConfig(BaseSettings):
|
|
|
878
798
|
def get_caches(self) -> dict[str, CacheInstanceConfig]:
|
|
879
799
|
"""获取所有缓存实例配置。
|
|
880
800
|
|
|
881
|
-
从环境变量解析
|
|
801
|
+
从环境变量解析 CACHE__{INSTANCE}__{FIELD} 格式的配置。
|
|
882
802
|
如果没有配置多实例,返回从单实例配置转换的 default 实例。
|
|
883
803
|
"""
|
|
884
804
|
if self._caches is None:
|
|
@@ -897,7 +817,7 @@ class BaseConfig(BaseSettings):
|
|
|
897
817
|
def get_storages(self) -> dict[str, StorageInstanceConfig]:
|
|
898
818
|
"""获取所有存储实例配置。
|
|
899
819
|
|
|
900
|
-
从环境变量解析
|
|
820
|
+
从环境变量解析 STORAGE__{INSTANCE}__{FIELD} 格式的配置。
|
|
901
821
|
如果没有配置多实例,返回从单实例配置转换的 default 实例。
|
|
902
822
|
"""
|
|
903
823
|
if self._storages is None:
|
|
@@ -920,7 +840,7 @@ class BaseConfig(BaseSettings):
|
|
|
920
840
|
def get_channels(self) -> dict[str, ChannelInstanceConfig]:
|
|
921
841
|
"""获取所有通道实例配置。
|
|
922
842
|
|
|
923
|
-
从环境变量解析
|
|
843
|
+
从环境变量解析 CHANNEL__{INSTANCE}__{FIELD} 格式的配置。
|
|
924
844
|
"""
|
|
925
845
|
if self._channels is None:
|
|
926
846
|
loader = MultiInstanceConfigLoader("CHANNEL", ChannelInstanceConfig)
|
|
@@ -930,7 +850,7 @@ class BaseConfig(BaseSettings):
|
|
|
930
850
|
def get_mqs(self) -> dict[str, MQInstanceConfig]:
|
|
931
851
|
"""获取所有消息队列实例配置。
|
|
932
852
|
|
|
933
|
-
从环境变量解析
|
|
853
|
+
从环境变量解析 MQ__{INSTANCE}__{FIELD} 格式的配置。
|
|
934
854
|
"""
|
|
935
855
|
if self._mqs is None:
|
|
936
856
|
loader = MultiInstanceConfigLoader("MQ", MQInstanceConfig)
|
|
@@ -940,7 +860,7 @@ class BaseConfig(BaseSettings):
|
|
|
940
860
|
def get_events(self) -> dict[str, EventInstanceConfig]:
|
|
941
861
|
"""获取所有事件总线实例配置。
|
|
942
862
|
|
|
943
|
-
从环境变量解析
|
|
863
|
+
从环境变量解析 EVENT__{INSTANCE}__{FIELD} 格式的配置。
|
|
944
864
|
如果没有配置多实例,返回从单实例配置转换的 default 实例。
|
|
945
865
|
"""
|
|
946
866
|
if self._events is None:
|
|
@@ -17,7 +17,7 @@ from starlette.requests import Request
|
|
|
17
17
|
from starlette.responses import Response
|
|
18
18
|
|
|
19
19
|
from aury.boot.application.errors import global_exception_handler
|
|
20
|
-
from aury.boot.common.logging import logger, set_trace_id
|
|
20
|
+
from aury.boot.common.logging import get_request_contexts, logger, set_trace_id
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def log_request[T](func: Callable[..., T]) -> Callable[..., T]:
|
|
@@ -187,6 +187,12 @@ class RequestLoggingMiddleware(BaseHTTPMiddleware):
|
|
|
187
187
|
)
|
|
188
188
|
logger.log(log_level.upper(), response_log)
|
|
189
189
|
|
|
190
|
+
# 记录请求上下文(user_id, tenant_id 等用户注册的字段)
|
|
191
|
+
request_contexts = get_request_contexts()
|
|
192
|
+
if request_contexts:
|
|
193
|
+
ctx_str = " | ".join(f"{k}: {v}" for k, v in request_contexts.items())
|
|
194
|
+
logger.info(f"[REQUEST_CONTEXT] Trace-ID: {trace_id} | {ctx_str}")
|
|
195
|
+
|
|
190
196
|
# 写入 access 日志(简洁格式)
|
|
191
197
|
logger.bind(access=True).info(
|
|
192
198
|
f"{request.method} {request.url.path} {status_code} {duration:.3f}s"
|
|
@@ -209,6 +215,13 @@ class RequestLoggingMiddleware(BaseHTTPMiddleware):
|
|
|
209
215
|
f"请求处理失败: {request.method} {request.url.path} | "
|
|
210
216
|
f"耗时: {duration:.3f}s | Trace-ID: {trace_id}"
|
|
211
217
|
)
|
|
218
|
+
|
|
219
|
+
# 记录请求上下文(即使异常也要记录,便于追踪问题)
|
|
220
|
+
request_contexts = get_request_contexts()
|
|
221
|
+
if request_contexts:
|
|
222
|
+
ctx_str = " | ".join(f"{k}: {v}" for k, v in request_contexts.items())
|
|
223
|
+
logger.info(f"[REQUEST_CONTEXT] Trace-ID: {trace_id} | {ctx_str}")
|
|
224
|
+
|
|
212
225
|
# 使用全局异常处理器生成响应,而不是直接抛出异常
|
|
213
226
|
# BaseHTTPMiddleware 中直接 raise 会绕过 FastAPI 的异常处理器
|
|
214
227
|
response = await global_exception_handler(request, exc)
|