jettask 0.2.18__py3-none-any.whl → 0.2.20__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 (165) hide show
  1. jettask/__init__.py +60 -2
  2. jettask/cli.py +314 -228
  3. jettask/config/__init__.py +9 -1
  4. jettask/config/config.py +245 -0
  5. jettask/config/env_loader.py +381 -0
  6. jettask/config/lua_scripts.py +158 -0
  7. jettask/config/nacos_config.py +132 -5
  8. jettask/core/__init__.py +1 -1
  9. jettask/core/app.py +1573 -666
  10. jettask/core/app_importer.py +33 -16
  11. jettask/core/container.py +532 -0
  12. jettask/core/task.py +1 -4
  13. jettask/core/unified_manager_base.py +2 -2
  14. jettask/executor/__init__.py +38 -0
  15. jettask/executor/core.py +625 -0
  16. jettask/executor/executor.py +338 -0
  17. jettask/executor/orchestrator.py +290 -0
  18. jettask/executor/process_entry.py +638 -0
  19. jettask/executor/task_executor.py +317 -0
  20. jettask/messaging/__init__.py +68 -0
  21. jettask/messaging/event_pool.py +2188 -0
  22. jettask/messaging/reader.py +519 -0
  23. jettask/messaging/registry.py +266 -0
  24. jettask/messaging/scanner.py +369 -0
  25. jettask/messaging/sender.py +312 -0
  26. jettask/persistence/__init__.py +118 -0
  27. jettask/persistence/backlog_monitor.py +567 -0
  28. jettask/{backend/data_access.py → persistence/base.py} +58 -57
  29. jettask/persistence/consumer.py +315 -0
  30. jettask/{core → persistence}/db_manager.py +23 -22
  31. jettask/persistence/maintenance.py +81 -0
  32. jettask/persistence/message_consumer.py +259 -0
  33. jettask/{backend/namespace_data_access.py → persistence/namespace.py} +66 -98
  34. jettask/persistence/offline_recovery.py +196 -0
  35. jettask/persistence/queue_discovery.py +215 -0
  36. jettask/persistence/task_persistence.py +218 -0
  37. jettask/persistence/task_updater.py +583 -0
  38. jettask/scheduler/__init__.py +2 -2
  39. jettask/scheduler/loader.py +6 -5
  40. jettask/scheduler/run_scheduler.py +1 -1
  41. jettask/scheduler/scheduler.py +7 -7
  42. jettask/scheduler/{unified_scheduler_manager.py → scheduler_coordinator.py} +18 -13
  43. jettask/task/__init__.py +16 -0
  44. jettask/{router.py → task/router.py} +26 -8
  45. jettask/task/task_center/__init__.py +9 -0
  46. jettask/task/task_executor.py +318 -0
  47. jettask/task/task_registry.py +291 -0
  48. jettask/test_connection_monitor.py +73 -0
  49. jettask/utils/__init__.py +31 -1
  50. jettask/{monitor/run_backlog_collector.py → utils/backlog_collector.py} +1 -1
  51. jettask/utils/db_connector.py +1629 -0
  52. jettask/{db_init.py → utils/db_init.py} +1 -1
  53. jettask/utils/rate_limit/__init__.py +30 -0
  54. jettask/utils/rate_limit/concurrency_limiter.py +665 -0
  55. jettask/utils/rate_limit/config.py +145 -0
  56. jettask/utils/rate_limit/limiter.py +41 -0
  57. jettask/utils/rate_limit/manager.py +269 -0
  58. jettask/utils/rate_limit/qps_limiter.py +154 -0
  59. jettask/utils/rate_limit/task_limiter.py +384 -0
  60. jettask/utils/serializer.py +3 -0
  61. jettask/{monitor/stream_backlog_monitor.py → utils/stream_backlog.py} +14 -6
  62. jettask/utils/time_sync.py +173 -0
  63. jettask/webui/__init__.py +27 -0
  64. jettask/{api/v1 → webui/api}/alerts.py +1 -1
  65. jettask/{api/v1 → webui/api}/analytics.py +2 -2
  66. jettask/{api/v1 → webui/api}/namespaces.py +1 -1
  67. jettask/{api/v1 → webui/api}/overview.py +1 -1
  68. jettask/{api/v1 → webui/api}/queues.py +3 -3
  69. jettask/{api/v1 → webui/api}/scheduled.py +1 -1
  70. jettask/{api/v1 → webui/api}/settings.py +1 -1
  71. jettask/{api.py → webui/app.py} +253 -145
  72. jettask/webui/namespace_manager/__init__.py +10 -0
  73. jettask/{multi_namespace_consumer.py → webui/namespace_manager/multi.py} +69 -22
  74. jettask/{unified_consumer_manager.py → webui/namespace_manager/unified.py} +1 -1
  75. jettask/{run.py → webui/run.py} +2 -2
  76. jettask/{services → webui/services}/__init__.py +1 -3
  77. jettask/{services → webui/services}/overview_service.py +34 -16
  78. jettask/{services → webui/services}/queue_service.py +1 -1
  79. jettask/{backend → webui/services}/queue_stats_v2.py +1 -1
  80. jettask/{services → webui/services}/settings_service.py +1 -1
  81. jettask/worker/__init__.py +53 -0
  82. jettask/worker/lifecycle.py +1507 -0
  83. jettask/worker/manager.py +583 -0
  84. jettask/{core/offline_worker_recovery.py → worker/recovery.py} +268 -175
  85. {jettask-0.2.18.dist-info → jettask-0.2.20.dist-info}/METADATA +2 -71
  86. jettask-0.2.20.dist-info/RECORD +145 -0
  87. jettask/__main__.py +0 -140
  88. jettask/api/__init__.py +0 -103
  89. jettask/backend/__init__.py +0 -1
  90. jettask/backend/api/__init__.py +0 -3
  91. jettask/backend/api/v1/__init__.py +0 -17
  92. jettask/backend/api/v1/monitoring.py +0 -431
  93. jettask/backend/api/v1/namespaces.py +0 -504
  94. jettask/backend/api/v1/queues.py +0 -342
  95. jettask/backend/api/v1/tasks.py +0 -367
  96. jettask/backend/core/__init__.py +0 -3
  97. jettask/backend/core/cache.py +0 -221
  98. jettask/backend/core/database.py +0 -200
  99. jettask/backend/core/exceptions.py +0 -102
  100. jettask/backend/dependencies.py +0 -261
  101. jettask/backend/init_meta_db.py +0 -158
  102. jettask/backend/main.py +0 -1426
  103. jettask/backend/main_unified.py +0 -78
  104. jettask/backend/main_v2.py +0 -394
  105. jettask/backend/models/__init__.py +0 -3
  106. jettask/backend/models/requests.py +0 -236
  107. jettask/backend/models/responses.py +0 -230
  108. jettask/backend/namespace_api_old.py +0 -267
  109. jettask/backend/services/__init__.py +0 -3
  110. jettask/backend/start.py +0 -42
  111. jettask/backend/unified_api_router.py +0 -1541
  112. jettask/cleanup_deprecated_tables.sql +0 -16
  113. jettask/core/consumer_manager.py +0 -1695
  114. jettask/core/delay_scanner.py +0 -256
  115. jettask/core/event_pool.py +0 -1700
  116. jettask/core/heartbeat_process.py +0 -222
  117. jettask/core/task_batch.py +0 -153
  118. jettask/core/worker_scanner.py +0 -271
  119. jettask/executors/__init__.py +0 -5
  120. jettask/executors/asyncio.py +0 -876
  121. jettask/executors/base.py +0 -30
  122. jettask/executors/common.py +0 -148
  123. jettask/executors/multi_asyncio.py +0 -309
  124. jettask/gradio_app.py +0 -570
  125. jettask/integrated_gradio_app.py +0 -1088
  126. jettask/main.py +0 -0
  127. jettask/monitoring/__init__.py +0 -3
  128. jettask/pg_consumer.py +0 -1896
  129. jettask/run_monitor.py +0 -22
  130. jettask/run_webui.py +0 -148
  131. jettask/scheduler/multi_namespace_scheduler.py +0 -294
  132. jettask/scheduler/unified_manager.py +0 -450
  133. jettask/task_center_client.py +0 -150
  134. jettask/utils/serializer_optimized.py +0 -33
  135. jettask/webui_exceptions.py +0 -67
  136. jettask-0.2.18.dist-info/RECORD +0 -150
  137. /jettask/{constants.py → config/constants.py} +0 -0
  138. /jettask/{backend/config.py → config/task_center.py} +0 -0
  139. /jettask/{pg_consumer → messaging/pg_consumer}/pg_consumer_v2.py +0 -0
  140. /jettask/{pg_consumer → messaging/pg_consumer}/sql/add_execution_time_field.sql +0 -0
  141. /jettask/{pg_consumer → messaging/pg_consumer}/sql/create_new_tables.sql +0 -0
  142. /jettask/{pg_consumer → messaging/pg_consumer}/sql/create_tables_v3.sql +0 -0
  143. /jettask/{pg_consumer → messaging/pg_consumer}/sql/migrate_to_new_structure.sql +0 -0
  144. /jettask/{pg_consumer → messaging/pg_consumer}/sql/modify_time_fields.sql +0 -0
  145. /jettask/{pg_consumer → messaging/pg_consumer}/sql_utils.py +0 -0
  146. /jettask/{models.py → persistence/models.py} +0 -0
  147. /jettask/scheduler/{manager.py → task_crud.py} +0 -0
  148. /jettask/{schema.sql → schemas/schema.sql} +0 -0
  149. /jettask/{task_center.py → task/task_center/client.py} +0 -0
  150. /jettask/{monitoring → utils}/file_watcher.py +0 -0
  151. /jettask/{services/redis_monitor_service.py → utils/redis_monitor.py} +0 -0
  152. /jettask/{api/v1 → webui/api}/__init__.py +0 -0
  153. /jettask/{webui_config.py → webui/config.py} +0 -0
  154. /jettask/{webui_models → webui/models}/__init__.py +0 -0
  155. /jettask/{webui_models → webui/models}/namespace.py +0 -0
  156. /jettask/{services → webui/services}/alert_service.py +0 -0
  157. /jettask/{services → webui/services}/analytics_service.py +0 -0
  158. /jettask/{services → webui/services}/scheduled_task_service.py +0 -0
  159. /jettask/{services → webui/services}/task_service.py +0 -0
  160. /jettask/{webui_sql → webui/sql}/batch_upsert_functions.sql +0 -0
  161. /jettask/{webui_sql → webui/sql}/verify_database.sql +0 -0
  162. {jettask-0.2.18.dist-info → jettask-0.2.20.dist-info}/WHEEL +0 -0
  163. {jettask-0.2.18.dist-info → jettask-0.2.20.dist-info}/entry_points.txt +0 -0
  164. {jettask-0.2.18.dist-info → jettask-0.2.20.dist-info}/licenses/LICENSE +0 -0
  165. {jettask-0.2.18.dist-info → jettask-0.2.20.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,317 @@
1
+ """
2
+ 任务执行器
3
+
4
+ 职责:
5
+ 1. 从事件队列获取消息
6
+ 2. 执行任务并管理生命周期
7
+ 3. 限流控制和批处理
8
+ """
9
+
10
+ import asyncio
11
+ import logging
12
+ import time
13
+ import os
14
+ from typing import Set
15
+ from collections import deque
16
+
17
+ from .core import ExecutorCore
18
+ from ..worker.lifecycle import WorkerStateManager
19
+ from ..utils.rate_limit.manager import RateLimiterManager
20
+
21
+ logger = logging.getLogger('app')
22
+
23
+
24
+ class TaskExecutor:
25
+ """
26
+ 任务执行器 - 负责单个任务类型的执行
27
+
28
+ 这是真正执行任务的核心组件,无论是在单进程还是多进程模式下。
29
+
30
+ 职责:
31
+ 1. 从 event_queue 获取消息
32
+ 2. 应用限流控制
33
+ 3. 执行任务
34
+ 4. 批处理管道优化
35
+ """
36
+
37
+ def __init__(self, event_queue, app, task_name: str, concurrency: int = 100):
38
+ """
39
+ 初始化任务执行器
40
+
41
+ Args:
42
+ event_queue: asyncio.Queue,接收待执行的消息
43
+ app: Application 实例(或 MinimalApp)
44
+ task_name: 任务名称
45
+ concurrency: 并发数(实际由限流器控制)
46
+ """
47
+ self.event_queue = event_queue
48
+ self.app = app
49
+ self.task_name = task_name
50
+ self.concurrency = concurrency
51
+
52
+ # 核心组件
53
+ self.executor_core = ExecutorCore(
54
+ app=app,
55
+ task_name=task_name,
56
+ concurrency=concurrency
57
+ )
58
+
59
+ # 活动任务集合
60
+ self._active_tasks: Set[asyncio.Task] = set()
61
+
62
+ # Pipeline 配置
63
+ self.max_buffer_size = 5000
64
+
65
+ logger.debug(f"TaskExecutor initialized for task '{task_name}'")
66
+
67
+ async def initialize(self):
68
+ """
69
+ 初始化执行器组件
70
+
71
+ 在开始执行前调用,初始化限流器、WorkerState 等
72
+ """
73
+ # 确保有 consumer_id
74
+ self.app.consumer_manager._heartbeat_strategy._ensure_consumer_id()
75
+ worker_id = self.app.consumer_manager._heartbeat_strategy.consumer_id
76
+ registry_manager = self.app.consumer_manager
77
+
78
+ # 初始化 WorkerStateManager(如果尚未初始化)
79
+ if not self.app.worker_state_manager:
80
+ self.app.worker_state_manager = WorkerStateManager(
81
+ redis_client=self.app.ep.async_redis_client,
82
+ redis_prefix=self.executor_core.prefix,
83
+ event_pool=self.app.ep
84
+ )
85
+ await self.app.worker_state_manager.start_listener()
86
+ logger.debug(f"WorkerStateManager started for worker {worker_id}")
87
+
88
+ # 初始化时间同步
89
+ from jettask.utils.time_sync import init_time_sync
90
+ time_sync = await init_time_sync(self.app.ep.async_redis_client)
91
+ logger.debug(f"TimeSync initialized, offset={time_sync.get_offset():.6f}s")
92
+
93
+ # 初始化限流器
94
+ self.executor_core.rate_limiter_manager = RateLimiterManager(
95
+ redis_client=self.app.ep.async_redis_client,
96
+ worker_id=worker_id,
97
+ redis_prefix=self.executor_core.prefix,
98
+ registry_manager=registry_manager,
99
+ worker_state_manager=self.app.worker_state_manager
100
+ )
101
+ logger.debug(f"RateLimiterManager initialized for worker {worker_id}")
102
+
103
+ # 加载限流配置
104
+ await self.executor_core.rate_limiter_manager.load_config_from_redis()
105
+
106
+ async def run(self):
107
+ """
108
+ 执行主循环
109
+
110
+ 持续从 event_queue 获取消息并执行,直到收到停止信号
111
+ """
112
+ logger.info(f"TaskExecutor started for task '{self.task_name}'")
113
+
114
+ tasks_batch = []
115
+
116
+ try:
117
+ while True:
118
+ # 检查退出信号
119
+ if hasattr(self.app, '_should_exit') and self.app._should_exit:
120
+ logger.debug(f"TaskExecutor[{self.task_name}] detected shutdown signal")
121
+ break
122
+
123
+ # 检查父进程(防止孤儿进程)
124
+ if hasattr(os, 'getppid') and os.getppid() == 1:
125
+ logger.warning(f"TaskExecutor[{self.task_name}] parent died, exiting")
126
+ break
127
+
128
+ current_time = time.time()
129
+
130
+ # 获取事件(带超时)
131
+ event = None
132
+ try:
133
+ event = await asyncio.wait_for(self.event_queue.get(), timeout=0.1)
134
+ except asyncio.TimeoutError:
135
+ pass
136
+
137
+ if event:
138
+ event.pop("execute_time", None)
139
+ tasks_batch.append(event)
140
+ logger.debug(
141
+ f"[{self.task_name}] Got event: {event.get('event_id', 'unknown')}"
142
+ )
143
+
144
+ # 批量处理任务
145
+ if tasks_batch:
146
+ await self._process_batch(tasks_batch)
147
+ tasks_batch.clear()
148
+
149
+ # 智能缓冲区管理
150
+ if self._should_flush_buffers(current_time):
151
+ asyncio.create_task(self.executor_core._flush_all_buffers())
152
+
153
+ # 智能休眠
154
+ await self._smart_sleep()
155
+
156
+ except asyncio.CancelledError:
157
+ logger.info(f"TaskExecutor[{self.task_name}] cancelled")
158
+ except Exception as e:
159
+ logger.error(f"TaskExecutor[{self.task_name}] error: {e}", exc_info=True)
160
+ finally:
161
+ await self.cleanup()
162
+
163
+ async def _process_batch(self, tasks_batch):
164
+ """处理一批任务"""
165
+ for event in tasks_batch:
166
+ event_data = event.get('event_data', {})
167
+ event_task_name = event_data.get("_task_name") or event_data.get("name")
168
+
169
+ if not event_task_name:
170
+ logger.error(f"No task_name in event {event.get('event_id')}")
171
+ continue
172
+
173
+ # 验证任务名称
174
+ if event_task_name != self.task_name:
175
+ logger.error(
176
+ f"Task name mismatch: {event_task_name} != {self.task_name}"
177
+ )
178
+ continue
179
+
180
+ # 限流控制
181
+ logger.debug(
182
+ f"[{self.task_name}] Acquiring rate limit, event_id={event.get('event_id')}"
183
+ )
184
+
185
+ rate_limit_token = await self.executor_core.rate_limiter_manager.acquire(
186
+ task_name=self.task_name,
187
+ timeout=None
188
+ )
189
+
190
+ if not rate_limit_token:
191
+ logger.error(f"Failed to acquire token for {self.task_name}")
192
+ continue
193
+
194
+ logger.debug(
195
+ f"[{self.task_name}] Acquired token={rate_limit_token}, starting execution"
196
+ )
197
+
198
+ self.executor_core.batch_counter += 1
199
+
200
+ # 创建任务并自动释放限流许可
201
+ async def execute_with_release(event_data, token):
202
+ try:
203
+ await self.executor_core.execute_task(**event_data)
204
+ finally:
205
+ await self.executor_core.rate_limiter_manager.release(
206
+ self.task_name, task_id=token
207
+ )
208
+
209
+ task = asyncio.create_task(execute_with_release(event, rate_limit_token))
210
+ self._active_tasks.add(task)
211
+ task.add_done_callback(self._active_tasks.discard)
212
+
213
+ def _should_flush_buffers(self, current_time: float) -> bool:
214
+ """判断是否需要刷新缓冲区"""
215
+ # 检查缓冲区是否满
216
+ buffer_full = (
217
+ len(self.executor_core.pending_acks) >= self.max_buffer_size or
218
+ len(self.executor_core.status_updates) >= self.max_buffer_size or
219
+ len(self.executor_core.data_updates) >= self.max_buffer_size or
220
+ len(self.executor_core.task_info_updates) >= self.max_buffer_size
221
+ )
222
+
223
+ if buffer_full:
224
+ return True
225
+
226
+ # 检查是否有待处理数据
227
+ has_pending_data = (
228
+ self.executor_core.pending_acks or
229
+ self.executor_core.status_updates or
230
+ self.executor_core.data_updates or
231
+ self.executor_core.task_info_updates
232
+ )
233
+
234
+ if not has_pending_data:
235
+ return False
236
+
237
+ # 检查是否超时
238
+ for data_type, config in self.executor_core.pipeline_config.items():
239
+ time_since_flush = current_time - self.executor_core.last_pipeline_flush[data_type]
240
+
241
+ if data_type == 'ack' and self.executor_core.pending_acks:
242
+ if time_since_flush >= config['max_delay']:
243
+ return True
244
+ elif data_type == 'task_info' and self.executor_core.task_info_updates:
245
+ if time_since_flush >= config['max_delay']:
246
+ return True
247
+ elif data_type == 'status' and self.executor_core.status_updates:
248
+ if time_since_flush >= config['max_delay']:
249
+ return True
250
+ elif data_type == 'data' and self.executor_core.data_updates:
251
+ if time_since_flush >= config['max_delay']:
252
+ return True
253
+
254
+ return False
255
+
256
+ async def _smart_sleep(self):
257
+ """智能休眠 - 根据队列状态决定休眠时间"""
258
+ has_events = False
259
+
260
+ if isinstance(self.event_queue, deque):
261
+ has_events = bool(self.event_queue)
262
+ elif isinstance(self.event_queue, asyncio.Queue):
263
+ has_events = not self.event_queue.empty()
264
+
265
+ if has_events:
266
+ # 有待处理事件,立即继续
267
+ await asyncio.sleep(0)
268
+ else:
269
+ # 无事件,稍作休眠
270
+ has_pending = (
271
+ self.executor_core.pending_acks or
272
+ self.executor_core.status_updates or
273
+ self.executor_core.data_updates or
274
+ self.executor_core.task_info_updates
275
+ )
276
+
277
+ if has_pending:
278
+ # 有待刷新的数据,先刷新
279
+ await self.executor_core._flush_all_buffers()
280
+
281
+ await asyncio.sleep(0.001)
282
+
283
+ async def cleanup(self):
284
+ """清理资源"""
285
+ logger.info(f"TaskExecutor[{self.task_name}] cleaning up")
286
+
287
+ # 设置停止标志
288
+ if hasattr(self.app.ep, '_stop_reading'):
289
+ self.app.ep._stop_reading = True
290
+
291
+ # 取消活动任务
292
+ if self._active_tasks:
293
+ logger.debug(
294
+ f"TaskExecutor[{self.task_name}] cancelling {len(self._active_tasks)} active tasks"
295
+ )
296
+ for task in self._active_tasks:
297
+ if not task.done():
298
+ task.cancel()
299
+
300
+ if self._active_tasks:
301
+ try:
302
+ await asyncio.wait_for(
303
+ asyncio.gather(*self._active_tasks, return_exceptions=True),
304
+ timeout=0.2
305
+ )
306
+ except asyncio.TimeoutError:
307
+ logger.warning(
308
+ f"TaskExecutor[{self.task_name}] some tasks did not complete in time"
309
+ )
310
+
311
+ # 清理 ExecutorCore
312
+ await self.executor_core.cleanup()
313
+
314
+ logger.info(f"TaskExecutor[{self.task_name}] stopped")
315
+
316
+
317
+ __all__ = ['TaskExecutor']
@@ -0,0 +1,68 @@
1
+ """
2
+ Messaging Module - 消息传递模块
3
+ ================================
4
+
5
+ 提供统一的消息队列管理、事件池和任务分发功能。
6
+
7
+ 核心组件
8
+ --------
9
+ - **EventPool**: 事件池核心,负责任务队列管理和消息分发
10
+ - **MessageSender**: 消息发送器,支持普通、延迟、优先级消息
11
+ - **MessageReader**: 消息读取器,支持消费者组和消息确认
12
+ - **DelayedMessageScanner**: 延迟消息扫描器,处理延迟任务
13
+ - **QueueRegistry**: 队列注册管理,提供队列发现功能
14
+
15
+ 使用示例
16
+ --------
17
+ ```python
18
+ from jettask.messaging import EventPool, MessageSender, MessageReader
19
+
20
+ # 创建事件池
21
+ event_pool = EventPool(
22
+ redis_client=redis_client,
23
+ async_redis_client=async_redis_client,
24
+ queues=['task_queue'],
25
+ redis_prefix='jettask'
26
+ )
27
+
28
+ # 发送消息
29
+ sender = MessageSender(async_redis_client, redis_prefix='jettask')
30
+ await sender.send_messages('task_queue', [{'task': 'example'}])
31
+
32
+ # 读取消息
33
+ reader = MessageReader(async_redis_client, binary_redis_client, redis_prefix='jettask')
34
+ messages = await reader.read_messages('task_queue', 'group1', 'worker1')
35
+ ```
36
+
37
+ 模块重构历史
38
+ ------------
39
+ - 2025-10-15: Phase 1 & 2 重构完成
40
+ - 从11个文件简化到6个文件
41
+ - 删除未使用的queue_manager、queue_monitor、queue_router等
42
+ - 统一命名:queue_registry → registry, delayed_scanner → scanner
43
+ - 代码量减少29%
44
+ """
45
+
46
+ from .event_pool import EventPool
47
+ from .sender import MessageSender
48
+ from .reader import MessageReader
49
+ from .scanner import DelayedMessageScanner
50
+ from .registry import QueueRegistry
51
+
52
+ # 向后兼容的别名
53
+ DelayQueueScanner = DelayedMessageScanner
54
+
55
+ __all__ = [
56
+ # 核心组件
57
+ 'EventPool',
58
+ 'MessageSender',
59
+ 'MessageReader',
60
+ 'DelayedMessageScanner',
61
+ 'QueueRegistry',
62
+ # 向后兼容别名
63
+ 'DelayQueueScanner',
64
+ ]
65
+
66
+ # 模块版本信息
67
+ __version__ = '2.0.0' # 重构后的新版本
68
+ __author__ = 'JetTask Team'