toms-fast 0.2.1__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 (60) hide show
  1. toms_fast-0.2.1.dist-info/METADATA +467 -0
  2. toms_fast-0.2.1.dist-info/RECORD +60 -0
  3. toms_fast-0.2.1.dist-info/WHEEL +4 -0
  4. toms_fast-0.2.1.dist-info/entry_points.txt +2 -0
  5. tomskit/__init__.py +0 -0
  6. tomskit/celery/README.md +693 -0
  7. tomskit/celery/__init__.py +4 -0
  8. tomskit/celery/celery.py +306 -0
  9. tomskit/celery/config.py +377 -0
  10. tomskit/cli/__init__.py +207 -0
  11. tomskit/cli/__main__.py +8 -0
  12. tomskit/cli/scaffold.py +123 -0
  13. tomskit/cli/templates/__init__.py +42 -0
  14. tomskit/cli/templates/base.py +348 -0
  15. tomskit/cli/templates/celery.py +101 -0
  16. tomskit/cli/templates/extensions.py +213 -0
  17. tomskit/cli/templates/fastapi.py +400 -0
  18. tomskit/cli/templates/migrations.py +281 -0
  19. tomskit/cli/templates_config.py +122 -0
  20. tomskit/logger/README.md +466 -0
  21. tomskit/logger/__init__.py +4 -0
  22. tomskit/logger/config.py +106 -0
  23. tomskit/logger/logger.py +290 -0
  24. tomskit/py.typed +0 -0
  25. tomskit/redis/README.md +462 -0
  26. tomskit/redis/__init__.py +6 -0
  27. tomskit/redis/config.py +85 -0
  28. tomskit/redis/redis_pool.py +87 -0
  29. tomskit/redis/redis_sync.py +66 -0
  30. tomskit/server/__init__.py +47 -0
  31. tomskit/server/config.py +117 -0
  32. tomskit/server/exceptions.py +412 -0
  33. tomskit/server/middleware.py +371 -0
  34. tomskit/server/parser.py +312 -0
  35. tomskit/server/resource.py +464 -0
  36. tomskit/server/server.py +276 -0
  37. tomskit/server/type.py +263 -0
  38. tomskit/sqlalchemy/README.md +590 -0
  39. tomskit/sqlalchemy/__init__.py +20 -0
  40. tomskit/sqlalchemy/config.py +125 -0
  41. tomskit/sqlalchemy/database.py +125 -0
  42. tomskit/sqlalchemy/pagination.py +359 -0
  43. tomskit/sqlalchemy/property.py +19 -0
  44. tomskit/sqlalchemy/sqlalchemy.py +131 -0
  45. tomskit/sqlalchemy/types.py +32 -0
  46. tomskit/task/README.md +67 -0
  47. tomskit/task/__init__.py +4 -0
  48. tomskit/task/task_manager.py +124 -0
  49. tomskit/tools/README.md +63 -0
  50. tomskit/tools/__init__.py +18 -0
  51. tomskit/tools/config.py +70 -0
  52. tomskit/tools/warnings.py +37 -0
  53. tomskit/tools/woker.py +81 -0
  54. tomskit/utils/README.md +666 -0
  55. tomskit/utils/README_SERIALIZER.md +644 -0
  56. tomskit/utils/__init__.py +35 -0
  57. tomskit/utils/fields.py +434 -0
  58. tomskit/utils/marshal_utils.py +137 -0
  59. tomskit/utils/response_utils.py +13 -0
  60. tomskit/utils/serializers.py +447 -0
@@ -0,0 +1,693 @@
1
+ # Celery Module Guide
2
+
3
+ 该模块提供了基于 Celery 的异步任务执行框架,支持在 Celery 任务中运行异步函数,并自动管理数据库会话。
4
+
5
+ ## 模块概述
6
+
7
+ Celery 模块扩展了标准 Celery 应用,提供了完整的异步任务支持。主要特性包括:
8
+
9
+ - ⚡ **异步任务支持**:在 Celery 任务中运行异步函数
10
+ - 🔄 **自动会话管理**:自动创建和关闭数据库会话
11
+ - 🛠️ **配置管理**:支持通过 `from_mapping` 方法配置 Celery
12
+ - 🔧 **上下文管理**:使用 `ContextVar` 管理 Celery 应用上下文
13
+ - 📦 **资源初始化**:在 worker 启动时初始化数据库连接池和 Redis 客户端
14
+
15
+ **Import Path:**
16
+ ```python
17
+ from tomskit.celery import (
18
+ AsyncCelery,
19
+ AsyncTaskRunner,
20
+ CeleryConfig
21
+ )
22
+ ```
23
+
24
+ ## 核心类和函数
25
+
26
+ ### AsyncCelery
27
+
28
+ 异步 Celery 应用类,继承自 `Celery`,负责配置管理。该类不自动初始化资源,资源初始化应该由业务代码在 worker 启动时完成。
29
+
30
+ ```python
31
+ class AsyncCelery(Celery):
32
+ def __init__(self, *args: Any, **kwargs: Any) -> None: ...
33
+
34
+ config: dict[str, Any]
35
+ app_root_path: Optional[str] = None
36
+
37
+ def set_app_root_path(self, app_root_path: str) -> None: ...
38
+
39
+ def from_mapping(
40
+ self,
41
+ mapping: Mapping[str, Any] | None = None,
42
+ **kwargs: Any
43
+ ) -> bool: ...
44
+ ```
45
+
46
+ **功能特性:**
47
+ - 继承自标准 Celery 类,兼容所有 Celery 功能
48
+ - 使用 `ContextVar` 管理应用上下文,确保线程安全
49
+ - 支持通过 `from_mapping` 方法配置 Celery(自动提取大写配置项)
50
+ - 不自动初始化资源,需要在 worker 启动时手动初始化
51
+
52
+ **属性说明:**
53
+ - `config`: 配置字典,存储所有大写配置项
54
+ - `app_root_path`: 应用根路径
55
+
56
+ **使用示例:**
57
+ ```python
58
+ from tomskit.celery import AsyncCelery
59
+
60
+ # 创建 AsyncCelery 实例
61
+ celery_app = AsyncCelery(
62
+ 'myapp',
63
+ broker='redis://localhost:6379/0',
64
+ backend='redis://localhost:6379/0'
65
+ )
66
+
67
+ # 配置 Celery(只提取大写配置项)
68
+ celery_app.from_mapping(
69
+ # Celery 配置
70
+ CELERY_TASK_SERIALIZER='json',
71
+ CELERY_RESULT_SERIALIZER='json',
72
+ CELERY_ACCEPT_CONTENT=['json'],
73
+ CELERY_TIMEZONE='UTC',
74
+ CELERY_ENABLE_UTC=True,
75
+
76
+ # 数据库配置(用于 worker 初始化)
77
+ SQLALCHEMY_DATABASE_URI='mysql+aiomysql://user:pass@localhost/db',
78
+ SQLALCHEMY_ENGINE_OPTIONS={
79
+ 'pool_size': 300,
80
+ 'max_overflow': 10,
81
+ 'pool_recycle': 3600,
82
+ },
83
+
84
+ # Redis 配置(用于 worker 初始化)
85
+ REDIS_HOST='localhost',
86
+ REDIS_PORT=6379,
87
+ REDIS_DB=0,
88
+ REDIS_PASSWORD='',
89
+ )
90
+
91
+ # 设置应用根路径
92
+ celery_app.set_app_root_path('/path/to/app')
93
+ ```
94
+
95
+ ### AsyncTaskRunner
96
+
97
+ 异步任务运行器,用于在 Celery 任务中执行异步函数。只负责运行异步函数和自动创建/关闭数据库 session。前提是数据库连接池和 Redis 客户端应该由业务代码在 worker 启动时初始化。
98
+
99
+ ```python
100
+ class AsyncTaskRunner:
101
+ def __init__(
102
+ self,
103
+ async_task: Callable[..., Awaitable[Any]],
104
+ use_db: bool = True,
105
+ use_redis: bool = False
106
+ ) -> None: ...
107
+
108
+ def run(self, *args: Any, **kwargs: Any) -> Any: ...
109
+ ```
110
+
111
+ **功能特性:**
112
+ - 在 Celery 任务中运行异步函数
113
+ - 自动创建和关闭数据库会话(如果启用)
114
+ - 检查 Redis 客户端是否已初始化(如果启用)
115
+ - 使用 `asyncio.run` 执行异步任务
116
+ - 确保资源正确释放,即使发生异常
117
+
118
+ **参数说明:**
119
+ - `async_task`: 要执行的异步任务函数(必须是协程函数)
120
+ - `use_db`: 是否启用数据库 session 管理,默认为 `True`
121
+ - `use_redis`: 是否检查 Redis 客户端,默认为 `False`(仅检查,不管理)
122
+
123
+ **使用场景:**
124
+ 在需要执行异步数据库操作或其他异步 I/O 操作的 Celery 任务中使用。
125
+
126
+ **使用示例:**
127
+ ```python
128
+ from celery import shared_task
129
+ from tomskit.celery import AsyncTaskRunner
130
+ from tomskit.sqlalchemy.database import db
131
+ from tomskit.sqlalchemy import User
132
+
133
+ @shared_task(name="user_task_created", queue="mail", ignore_result=False)
134
+ def user_task_created():
135
+ task = AsyncTaskRunner(async_user_task_created)
136
+ return task.run()
137
+
138
+ async def async_user_task_created():
139
+ print("user_task_created running.")
140
+ new_user = User(
141
+ name="username",
142
+ email="username@gmail.com"
143
+ )
144
+ try:
145
+ db.session.add(new_user)
146
+ await db.session.commit()
147
+ print(f"add new user_id = {new_user.name}")
148
+ await db.session.refresh(new_user)
149
+ return f"This is new user id {new_user.id}"
150
+ except Exception as e:
151
+ await db.session.rollback()
152
+ return f"This task is fail. {str(e)}"
153
+ ```
154
+
155
+ ## 完整使用示例
156
+
157
+ ### 初始化 Celery 应用和 Worker
158
+
159
+ ```python
160
+ from celery.signals import worker_process_init
161
+ from tomskit.celery import AsyncCelery, AsyncTaskRunner
162
+ from tomskit.sqlalchemy.database import db
163
+ from tomskit.redis.redis_pool import RedisClientWrapper
164
+ from tomskit.redis.config import RedisConfig
165
+
166
+ # 创建 AsyncCelery 实例
167
+ celery_app = AsyncCelery(
168
+ 'myapp',
169
+ broker='redis://localhost:6379/0',
170
+ backend='redis://localhost:6379/0'
171
+ )
172
+
173
+ # 配置 Celery
174
+ celery_app.from_mapping(
175
+ # Celery 配置
176
+ CELERY_TASK_SERIALIZER='json',
177
+ CELERY_RESULT_SERIALIZER='json',
178
+ CELERY_ACCEPT_CONTENT=['json'],
179
+ CELERY_TIMEZONE='UTC',
180
+ CELERY_ENABLE_UTC=True,
181
+ CELERY_TASK_TRACK_STARTED=True,
182
+ CELERY_TASK_TIME_LIMIT=30 * 60, # 30 分钟
183
+ CELERY_TASK_SOFT_TIME_LIMIT=25 * 60, # 25 分钟
184
+
185
+ # 数据库配置
186
+ SQLALCHEMY_DATABASE_URI='mysql+aiomysql://user:pass@localhost/db',
187
+ SQLALCHEMY_ENGINE_OPTIONS={
188
+ 'pool_size': 300,
189
+ 'max_overflow': 10,
190
+ 'pool_recycle': 3600,
191
+ },
192
+
193
+ # Redis 配置
194
+ REDIS_HOST='localhost',
195
+ REDIS_PORT=6379,
196
+ REDIS_DB=0,
197
+ REDIS_PASSWORD='',
198
+ )
199
+
200
+ # Worker 启动时初始化资源
201
+ @worker_process_init.connect
202
+ def init_worker(sender=None, **kwargs):
203
+ """在 worker 进程启动时初始化数据库连接池和 Redis 客户端"""
204
+ # 初始化数据库连接池
205
+ db.initialize_session_pool(
206
+ celery_app.config["SQLALCHEMY_DATABASE_URI"],
207
+ celery_app.config.get("SQLALCHEMY_ENGINE_OPTIONS", {})
208
+ )
209
+
210
+ # 初始化 Redis 客户端
211
+ redis_config = RedisConfig(
212
+ REDIS_HOST=celery_app.config.get("REDIS_HOST", "localhost"),
213
+ REDIS_PORT=celery_app.config.get("REDIS_PORT", 6379),
214
+ REDIS_DB=celery_app.config.get("REDIS_DB", 0),
215
+ REDIS_PASSWORD=celery_app.config.get("REDIS_PASSWORD", ""),
216
+ )
217
+ RedisClientWrapper.initialize(redis_config.model_dump())
218
+ ```
219
+
220
+ ### 定义异步任务
221
+
222
+ ```python
223
+ from celery import shared_task
224
+ from tomskit.celery import AsyncTaskRunner
225
+ from tomskit.sqlalchemy.database import db
226
+ from tomskit.sqlalchemy import User
227
+
228
+ @celery_app.task(name="create_user", queue="default")
229
+ def create_user_task(name: str, email: str):
230
+ """创建用户的 Celery 任务"""
231
+ task = AsyncTaskRunner(async_create_user)
232
+ return task.run(name, email)
233
+
234
+ async def async_create_user(name: str, email: str):
235
+ """异步创建用户函数"""
236
+ new_user = User(name=name, email=email)
237
+ try:
238
+ db.session.add(new_user)
239
+ await db.session.commit()
240
+ await db.session.refresh(new_user)
241
+ return {
242
+ "success": True,
243
+ "user_id": new_user.id,
244
+ "message": f"User {name} created successfully"
245
+ }
246
+ except Exception as e:
247
+ await db.session.rollback()
248
+ return {
249
+ "success": False,
250
+ "error": str(e)
251
+ }
252
+ ```
253
+
254
+ ### 使用 Redis 的任务
255
+
256
+ ```python
257
+ from celery import shared_task
258
+ from tomskit.celery import AsyncTaskRunner
259
+ from tomskit.redis.redis_pool import redis_client
260
+ from tomskit.sqlalchemy.database import db
261
+ from tomskit.sqlalchemy import User
262
+
263
+ @celery_app.task(name="cache_user_data", queue="cache")
264
+ def cache_user_data_task(user_id: int):
265
+ """缓存用户数据的 Celery 任务"""
266
+ # 启用 Redis 检查
267
+ task = AsyncTaskRunner(async_cache_user_data, use_db=True, use_redis=True)
268
+ return task.run(user_id)
269
+
270
+ async def async_cache_user_data(user_id: int):
271
+ """异步缓存用户数据函数"""
272
+ # 从数据库获取用户
273
+ user = await db.session.get(User, user_id)
274
+ if user:
275
+ # 缓存到 Redis
276
+ await redis_client.setex(
277
+ f"user:{user_id}",
278
+ 3600, # 1 小时过期
279
+ str(user.id) # 需要序列化
280
+ )
281
+ return f"User {user_id} cached successfully"
282
+ return f"User {user_id} not found"
283
+ ```
284
+
285
+ ### 不使用数据库的任务
286
+
287
+ ```python
288
+ @celery_app.task(name="simple_task", queue="default")
289
+ def simple_task(message: str):
290
+ """简单的异步任务,不使用数据库"""
291
+ task = AsyncTaskRunner(async_simple_task, use_db=False)
292
+ return task.run(message)
293
+
294
+ async def async_simple_task(message: str):
295
+ """简单的异步函数"""
296
+ # 只使用 Redis,不使用数据库
297
+ await redis_client.set("message", message)
298
+ return f"Message '{message}' stored"
299
+ ```
300
+
301
+ ### 带参数和返回值的任务
302
+
303
+ ```python
304
+ @celery_app.task(name="process_data", queue="processing")
305
+ def process_data_task(data_id: int, options: dict = None):
306
+ """处理数据的 Celery 任务"""
307
+ task = AsyncTaskRunner(async_process_data)
308
+ return task.run(data_id, options=options or {})
309
+
310
+ async def async_process_data(data_id: int, options: dict):
311
+ """异步处理数据函数"""
312
+ # 处理逻辑
313
+ processed_count = 0
314
+
315
+ # 查询数据
316
+ result = await db.session.execute(
317
+ db.select(DataItem).where(DataItem.data_id == data_id)
318
+ )
319
+ items = result.scalars().all()
320
+
321
+ for item in items:
322
+ # 处理每个项目
323
+ await process_item(item, options)
324
+ processed_count += 1
325
+
326
+ return {
327
+ "data_id": data_id,
328
+ "processed_count": processed_count,
329
+ "status": "completed"
330
+ }
331
+ ```
332
+
333
+ ### 使用环境变量配置
334
+
335
+ ```python
336
+ import os
337
+ from tomskit.celery import AsyncCelery
338
+ from tomskit.sqlalchemy.config import DatabaseConfig
339
+ from tomskit.redis.config import RedisConfig
340
+
341
+ # 从环境变量创建配置
342
+ db_config = DatabaseConfig()
343
+ redis_config = RedisConfig()
344
+
345
+ # 创建 Celery 应用
346
+ celery_app = AsyncCelery(
347
+ 'myapp',
348
+ broker=os.getenv('CELERY_BROKER_URL', 'redis://localhost:6379/0'),
349
+ backend=os.getenv('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0')
350
+ )
351
+
352
+ # 配置 Celery
353
+ celery_app.from_mapping(
354
+ CELERY_TASK_SERIALIZER='json',
355
+ CELERY_RESULT_SERIALIZER='json',
356
+ CELERY_ACCEPT_CONTENT=['json'],
357
+ CELERY_TIMEZONE='UTC',
358
+ CELERY_ENABLE_UTC=True,
359
+
360
+ # 使用配置对象
361
+ SQLALCHEMY_DATABASE_URI=db_config.SQLALCHEMY_DATABASE_URI,
362
+ SQLALCHEMY_ENGINE_OPTIONS=db_config.SQLALCHEMY_ENGINE_OPTIONS,
363
+
364
+ REDIS_HOST=redis_config.REDIS_HOST,
365
+ REDIS_PORT=redis_config.REDIS_PORT,
366
+ REDIS_DB=redis_config.REDIS_DB,
367
+ REDIS_PASSWORD=redis_config.REDIS_PASSWORD,
368
+ )
369
+ ```
370
+
371
+ ## 配置说明
372
+
373
+ ### Celery 配置项
374
+
375
+ 通过 `from_mapping` 方法可以配置所有标准的 Celery 配置项:
376
+
377
+ - `CELERY_TASK_SERIALIZER`: 任务序列化格式(如 'json', 'pickle')
378
+ - `CELERY_RESULT_SERIALIZER`: 结果序列化格式
379
+ - `CELERY_ACCEPT_CONTENT`: 接受的内容类型
380
+ - `CELERY_TIMEZONE`: 时区设置
381
+ - `CELERY_ENABLE_UTC`: 是否启用 UTC
382
+ - `CELERY_TASK_TRACK_STARTED`: 是否跟踪任务开始
383
+ - `CELERY_TASK_TIME_LIMIT`: 任务硬时间限制(秒)
384
+ - `CELERY_TASK_SOFT_TIME_LIMIT`: 任务软时间限制(秒)
385
+ - `CELERY_BROKER_URL`: Broker URL(如果未在初始化时指定)
386
+ - `CELERY_RESULT_BACKEND`: 结果后端 URL(如果未在初始化时指定)
387
+
388
+ ### 数据库配置项
389
+
390
+ 用于在 worker 启动时初始化数据库连接池:
391
+
392
+ - `SQLALCHEMY_DATABASE_URI`: 数据库连接 URI
393
+ - `SQLALCHEMY_ENGINE_OPTIONS`: SQLAlchemy 引擎选项字典
394
+
395
+ ### Redis 配置项
396
+
397
+ 用于在 worker 启动时初始化 Redis 客户端:
398
+
399
+ - `REDIS_HOST`: Redis 主机地址
400
+ - `REDIS_PORT`: Redis 端口
401
+ - `REDIS_DB`: Redis 数据库编号
402
+ - `REDIS_PASSWORD`: Redis 密码
403
+
404
+ **配置示例:**
405
+ ```python
406
+ celery_app.from_mapping(
407
+ # 序列化配置
408
+ CELERY_TASK_SERIALIZER='json',
409
+ CELERY_RESULT_SERIALIZER='json',
410
+ CELERY_ACCEPT_CONTENT=['json'],
411
+
412
+ # 时区配置
413
+ CELERY_TIMEZONE='Asia/Shanghai',
414
+ CELERY_ENABLE_UTC=True,
415
+
416
+ # 任务配置
417
+ CELERY_TASK_TRACK_STARTED=True,
418
+ CELERY_TASK_TIME_LIMIT=30 * 60,
419
+ CELERY_TASK_SOFT_TIME_LIMIT=25 * 60,
420
+
421
+ # 路由配置
422
+ CELERY_TASK_ROUTES={
423
+ 'tasks.send_email': {'queue': 'mail'},
424
+ 'tasks.process_data': {'queue': 'processing'},
425
+ },
426
+
427
+ # 数据库配置
428
+ SQLALCHEMY_DATABASE_URI='mysql+aiomysql://user:pass@localhost/db',
429
+ SQLALCHEMY_ENGINE_OPTIONS={
430
+ 'pool_size': 300,
431
+ 'max_overflow': 10,
432
+ 'pool_recycle': 3600,
433
+ },
434
+
435
+ # Redis 配置
436
+ REDIS_HOST='localhost',
437
+ REDIS_PORT=6379,
438
+ REDIS_DB=0,
439
+ )
440
+ ```
441
+
442
+ ## 注意事项
443
+
444
+ 1. **资源初始化**:
445
+ - 数据库连接池和 Redis 客户端必须在 worker 启动时初始化
446
+ - 使用 `worker_process_init` 信号处理器来初始化资源
447
+ - 不要在任务中初始化资源,这会导致性能问题和资源泄漏
448
+
449
+ 2. **会话管理**:
450
+ - `AsyncTaskRunner` 会自动创建和关闭数据库会话
451
+ - 在异步函数中直接使用 `db.session`,不需要手动创建会话
452
+ - 会话会在任务完成后自动关闭,即使发生异常也会正确清理
453
+
454
+ 3. **异步函数要求**:
455
+ - `AsyncTaskRunner` 的 `async_task` 参数必须是协程函数(使用 `async def` 定义)
456
+ - 在异步函数中必须使用 `await` 调用异步操作
457
+
458
+ 4. **上下文管理**:
459
+ - `AsyncCelery` 使用 `ContextVar` 管理应用上下文
460
+ - 确保在创建 `AsyncTaskRunner` 之前已经初始化了 `AsyncCelery` 实例
461
+
462
+ 5. **性能考虑**:
463
+ - `AsyncTaskRunner.run()` 使用 `asyncio.run()` 执行异步任务
464
+ - 每个任务都会创建新的事件循环,适合在 Celery worker 中使用
465
+ - 数据库连接池在 worker 启动时创建,所有任务共享连接池
466
+
467
+ 6. **错误处理**:
468
+ - 如果 Celery 应用未初始化,会抛出 `RuntimeError`
469
+ - 如果数据库连接池未初始化,会抛出 `RuntimeError`
470
+ - 如果 Redis 客户端未初始化且 `use_redis=True`,会抛出 `RuntimeError`
471
+ - 建议在任务函数中捕获和处理异常,返回错误信息而不是抛出异常
472
+
473
+ 7. **配置项提取**:
474
+ - `from_mapping` 方法只提取大写的配置项
475
+ - 小写配置项会被忽略,确保配置项名称使用大写
476
+
477
+ 8. **Redis 使用**:
478
+ - `use_redis` 参数仅用于检查 Redis 客户端是否已初始化
479
+ - Redis 客户端本身不需要在任务中管理,它在 worker 启动时初始化
480
+ - 在异步函数中直接使用 `redis_client` 进行操作
481
+
482
+ ## 工作流程
483
+
484
+ 1. **应用启动**:创建 `AsyncCelery` 实例并配置
485
+ 2. **Worker 启动**:在 `worker_process_init` 信号处理器中初始化数据库连接池和 Redis 客户端
486
+ 3. **任务执行**:创建 `AsyncTaskRunner` 实例并调用 `run()` 方法
487
+ 4. **资源管理**:`AsyncTaskRunner` 自动创建数据库会话,执行异步函数,然后关闭会话
488
+ 5. **Worker 关闭**:资源会在进程结束时自动清理
489
+
490
+ ## 相关文档
491
+
492
+ - [Async Task Guide](../../docs/specs/async_task_guide.md) - 详细的异步任务使用指南
493
+ - [Celery 官方文档](https://docs.celeryq.dev/) - Celery 官方文档
494
+ - [Database Guide](../../docs/specs/database_guide.md) - 数据库使用指南
495
+ - [Redis Guide](../../docs/specs/redis_guide.md) - Redis 使用指南
496
+
497
+
498
+ ## Celery 配置
499
+
500
+ ### CeleryConfig
501
+
502
+ Celery 配置类,继承自 `pydantic_settings.BaseSettings`,用于管理 Celery 应用的完整配置。支持 Redis 作为 broker 和 backend,以及将结果存储到数据库。
503
+
504
+ ```python
505
+ class CeleryConfig(BaseSettings):
506
+ # Redis Broker 配置
507
+ CELERY_BROKER_REDIS_HOST: str = Field(default="localhost", ...)
508
+ CELERY_BROKER_REDIS_PORT: PositiveInt = Field(default=6379, ...)
509
+ CELERY_BROKER_REDIS_USERNAME: Optional[str] = Field(default=None, ...)
510
+ CELERY_BROKER_REDIS_PASSWORD: Optional[str] = Field(default=None, ...)
511
+ CELERY_BROKER_REDIS_DB: NonNegativeInt = Field(default=0, ...)
512
+
513
+ # Result Backend 配置
514
+ CELERY_RESULT_BACKEND_TYPE: str = Field(default="redis", ...) # 'redis' 或 'database'
515
+
516
+ # Redis Backend 配置(当 CELERY_RESULT_BACKEND_TYPE='redis' 时使用)
517
+ CELERY_RESULT_BACKEND_REDIS_HOST: str = Field(default="localhost", ...)
518
+ CELERY_RESULT_BACKEND_REDIS_PORT: PositiveInt = Field(default=6379, ...)
519
+ CELERY_RESULT_BACKEND_REDIS_USERNAME: Optional[str] = Field(default=None, ...)
520
+ CELERY_RESULT_BACKEND_REDIS_PASSWORD: Optional[str] = Field(default=None, ...)
521
+ CELERY_RESULT_BACKEND_REDIS_DB: NonNegativeInt = Field(default=1, ...)
522
+
523
+ # Database Backend 配置(当 CELERY_RESULT_BACKEND_TYPE='database' 时使用)
524
+ CELERY_RESULT_BACKEND_DATABASE_URI_SCHEME: str = Field(default="mysql", ...)
525
+
526
+ # Celery 任务配置
527
+ CELERY_TASK_SERIALIZER: str = Field(default="json", ...)
528
+ CELERY_RESULT_SERIALIZER: str = Field(default="json", ...)
529
+ CELERY_ACCEPT_CONTENT: list[str] = Field(default=["json"], ...)
530
+ CELERY_TIMEZONE: str = Field(default="UTC", ...)
531
+ CELERY_ENABLE_UTC: bool = Field(default=True, ...)
532
+ CELERY_TASK_TRACK_STARTED: bool = Field(default=True, ...)
533
+ CELERY_TASK_TIME_LIMIT: Optional[NonNegativeInt] = Field(default=None, ...)
534
+ CELERY_TASK_SOFT_TIME_LIMIT: Optional[NonNegativeInt] = Field(default=None, ...)
535
+ CELERY_TASK_IGNORE_RESULT: bool = Field(default=False, ...)
536
+ CELERY_RESULT_EXPIRES: Optional[NonNegativeInt] = Field(default=None, ...)
537
+
538
+ # 数据库配置(用于 worker 和结果存储)
539
+ DB_HOST: str = Field(default="localhost", ...)
540
+ DB_PORT: PositiveInt = Field(default=5432, ...)
541
+ DB_USERNAME: str = Field(default="", ...)
542
+ DB_PASSWORD: str = Field(default="", ...)
543
+ DB_DATABASE: str = Field(default="tomskitdb", ...)
544
+ # ... 更多数据库配置项
545
+
546
+ # Redis 配置(用于 worker)
547
+ REDIS_HOST: str = Field(default="localhost", ...)
548
+ REDIS_PORT: PositiveInt = Field(default=6379, ...)
549
+ # ... 更多 Redis 配置项
550
+
551
+ @computed_field
552
+ @property
553
+ def CELERY_BROKER_URL(self) -> str: ...
554
+
555
+ @computed_field
556
+ @property
557
+ def CELERY_RESULT_BACKEND(self) -> str: ...
558
+
559
+ @computed_field
560
+ @property
561
+ def SQLALCHEMY_DATABASE_URI(self) -> str: ...
562
+
563
+ def get_celery_config_dict(self) -> dict[str, Any]: ...
564
+ ```
565
+
566
+ **功能特性:**
567
+ - 支持 Redis 作为 broker 和 backend
568
+ - 支持数据库作为结果后端(将结果存储到数据库)
569
+ - 自动生成 broker 和 backend URL
570
+ - 提供完整的 Celery 配置字典
571
+ - 支持通过环境变量配置
572
+
573
+ **使用示例:**
574
+
575
+ **使用 Redis 作为结果后端:**
576
+ ```python
577
+ from tomskit.celery import AsyncCelery, CeleryConfig
578
+
579
+ # 创建配置
580
+ config = CeleryConfig(
581
+ # Redis Broker
582
+ CELERY_BROKER_REDIS_HOST='localhost',
583
+ CELERY_BROKER_REDIS_PORT=6379,
584
+ CELERY_BROKER_REDIS_DB=0,
585
+
586
+ # Redis Backend
587
+ CELERY_RESULT_BACKEND_TYPE='redis',
588
+ CELERY_RESULT_BACKEND_REDIS_HOST='localhost',
589
+ CELERY_RESULT_BACKEND_REDIS_PORT=6379,
590
+ CELERY_RESULT_BACKEND_REDIS_DB=1,
591
+
592
+ # 数据库配置(用于 worker)
593
+ DB_USERNAME='user',
594
+ DB_PASSWORD='password',
595
+ DB_HOST='localhost',
596
+ DB_PORT=3306,
597
+ DB_DATABASE='mydb',
598
+ )
599
+
600
+ # 创建 Celery 应用
601
+ celery_app = AsyncCelery(
602
+ 'myapp',
603
+ broker=config.CELERY_BROKER_URL,
604
+ backend=config.CELERY_RESULT_BACKEND
605
+ )
606
+
607
+ # 应用配置
608
+ celery_app.from_mapping(config.get_celery_config_dict())
609
+ ```
610
+
611
+ **使用数据库作为结果后端:**
612
+ ```python
613
+ from tomskit.celery import AsyncCelery, CeleryConfig
614
+
615
+ # 创建配置
616
+ config = CeleryConfig(
617
+ # Redis Broker
618
+ CELERY_BROKER_REDIS_HOST='localhost',
619
+ CELERY_BROKER_REDIS_PORT=6379,
620
+ CELERY_BROKER_REDIS_DB=0,
621
+
622
+ # Database Backend(将结果存储到数据库)
623
+ CELERY_RESULT_BACKEND_TYPE='database',
624
+ CELERY_RESULT_BACKEND_DATABASE_URI_SCHEME='mysql',
625
+
626
+ # 数据库配置
627
+ DB_USERNAME='user',
628
+ DB_PASSWORD='password',
629
+ DB_HOST='localhost',
630
+ DB_PORT=3306,
631
+ DB_DATABASE='mydb',
632
+ )
633
+
634
+ # 创建 Celery 应用
635
+ celery_app = AsyncCelery(
636
+ 'myapp',
637
+ broker=config.CELERY_BROKER_URL,
638
+ backend=config.CELERY_RESULT_BACKEND # 自动生成 db+mysql://...
639
+ )
640
+
641
+ # 应用配置
642
+ celery_app.from_mapping(config.get_celery_config_dict())
643
+ ```
644
+
645
+ **使用环境变量配置:**
646
+ ```python
647
+ from tomskit.celery import AsyncCelery, CeleryConfig
648
+
649
+ # 从环境变量加载配置
650
+ config = CeleryConfig()
651
+
652
+ # 创建 Celery 应用
653
+ celery_app = AsyncCelery(
654
+ 'myapp',
655
+ broker=config.CELERY_BROKER_URL,
656
+ backend=config.CELERY_RESULT_BACKEND
657
+ )
658
+
659
+ # 应用配置
660
+ celery_app.from_mapping(config.get_celery_config_dict())
661
+ ```
662
+
663
+ **配置属性说明:**
664
+
665
+ **Redis Broker 配置:**
666
+ - `CELERY_BROKER_REDIS_HOST`: Redis broker 主机地址
667
+ - `CELERY_BROKER_REDIS_PORT`: Redis broker 端口
668
+ - `CELERY_BROKER_REDIS_USERNAME`: Redis broker 用户名(可选)
669
+ - `CELERY_BROKER_REDIS_PASSWORD`: Redis broker 密码(可选)
670
+ - `CELERY_BROKER_REDIS_DB`: Redis broker 数据库编号
671
+
672
+ **Result Backend 配置:**
673
+ - `CELERY_RESULT_BACKEND_TYPE`: 结果后端类型,`'redis'` 或 `'database'`
674
+ - Redis Backend 相关配置(当 `CELERY_RESULT_BACKEND_TYPE='redis'` 时)
675
+ - Database Backend 相关配置(当 `CELERY_RESULT_BACKEND_TYPE='database'` 时)
676
+
677
+ **Celery 任务配置:**
678
+ - `CELERY_TASK_SERIALIZER`: 任务序列化格式
679
+ - `CELERY_RESULT_SERIALIZER`: 结果序列化格式
680
+ - `CELERY_ACCEPT_CONTENT`: 接受的内容类型
681
+ - `CELERY_TIMEZONE`: 时区设置
682
+ - `CELERY_ENABLE_UTC`: 是否启用 UTC
683
+ - `CELERY_TASK_TRACK_STARTED`: 是否跟踪任务开始
684
+ - `CELERY_TASK_TIME_LIMIT`: 任务硬时间限制(秒)
685
+ - `CELERY_TASK_SOFT_TIME_LIMIT`: 任务软时间限制(秒)
686
+ - `CELERY_TASK_IGNORE_RESULT`: 是否忽略任务结果
687
+ - `CELERY_RESULT_EXPIRES`: 结果过期时间(秒)
688
+
689
+ **注意事项:**
690
+ 1. 使用数据库作为结果后端时,Celery 会自动创建 `celery_taskmeta` 表来存储任务结果
691
+ 2. 确保数据库用户有创建表的权限
692
+ 3. Redis broker 和 backend 可以使用不同的 Redis 实例和数据库
693
+ 4. 所有配置项都支持通过环境变量设置
@@ -0,0 +1,4 @@
1
+ from tomskit.celery.celery import AsyncCelery, AsyncTaskRunner, celery_context
2
+ from tomskit.celery.config import CeleryConfig
3
+
4
+ __all__ = ["AsyncCelery", "AsyncTaskRunner", "celery_context", "CeleryConfig"]