jettask 0.2.20__py3-none-any.whl → 0.2.24__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.
- jettask/__init__.py +4 -0
- jettask/cli.py +12 -8
- jettask/config/lua_scripts.py +37 -0
- jettask/config/nacos_config.py +1 -1
- jettask/core/app.py +313 -340
- jettask/core/container.py +4 -4
- jettask/{persistence → core}/namespace.py +93 -27
- jettask/core/task.py +16 -9
- jettask/core/unified_manager_base.py +136 -26
- jettask/db/__init__.py +67 -0
- jettask/db/base.py +137 -0
- jettask/{utils/db_connector.py → db/connector.py} +130 -26
- jettask/db/models/__init__.py +16 -0
- jettask/db/models/scheduled_task.py +196 -0
- jettask/db/models/task.py +77 -0
- jettask/db/models/task_run.py +85 -0
- jettask/executor/__init__.py +0 -15
- jettask/executor/core.py +76 -31
- jettask/executor/process_entry.py +29 -114
- jettask/executor/task_executor.py +4 -0
- jettask/messaging/event_pool.py +928 -685
- jettask/messaging/scanner.py +30 -0
- jettask/persistence/__init__.py +28 -103
- jettask/persistence/buffer.py +170 -0
- jettask/persistence/consumer.py +330 -249
- jettask/persistence/manager.py +304 -0
- jettask/persistence/persistence.py +391 -0
- jettask/scheduler/__init__.py +15 -3
- jettask/scheduler/{task_crud.py → database.py} +61 -57
- jettask/scheduler/loader.py +2 -2
- jettask/scheduler/{scheduler_coordinator.py → manager.py} +23 -6
- jettask/scheduler/models.py +14 -10
- jettask/scheduler/schedule.py +166 -0
- jettask/scheduler/scheduler.py +12 -11
- jettask/schemas/__init__.py +50 -1
- jettask/schemas/backlog.py +43 -6
- jettask/schemas/namespace.py +70 -19
- jettask/schemas/queue.py +19 -3
- jettask/schemas/responses.py +493 -0
- jettask/task/__init__.py +0 -2
- jettask/task/router.py +3 -0
- jettask/test_connection_monitor.py +1 -1
- jettask/utils/__init__.py +7 -5
- jettask/utils/db_init.py +8 -4
- jettask/utils/namespace_dep.py +167 -0
- jettask/utils/queue_matcher.py +186 -0
- jettask/utils/rate_limit/concurrency_limiter.py +7 -1
- jettask/utils/stream_backlog.py +1 -1
- jettask/webui/__init__.py +0 -1
- jettask/webui/api/__init__.py +4 -4
- jettask/webui/api/alerts.py +806 -71
- jettask/webui/api/example_refactored.py +400 -0
- jettask/webui/api/namespaces.py +390 -45
- jettask/webui/api/overview.py +300 -54
- jettask/webui/api/queues.py +971 -267
- jettask/webui/api/scheduled.py +1249 -56
- jettask/webui/api/settings.py +129 -7
- jettask/webui/api/workers.py +442 -0
- jettask/webui/app.py +46 -2329
- jettask/webui/middleware/__init__.py +6 -0
- jettask/webui/middleware/namespace_middleware.py +135 -0
- jettask/webui/services/__init__.py +146 -0
- jettask/webui/services/heartbeat_service.py +251 -0
- jettask/webui/services/overview_service.py +60 -51
- jettask/webui/services/queue_monitor_service.py +426 -0
- jettask/webui/services/redis_monitor_service.py +87 -0
- jettask/webui/services/settings_service.py +174 -111
- jettask/webui/services/task_monitor_service.py +222 -0
- jettask/webui/services/timeline_pg_service.py +452 -0
- jettask/webui/services/timeline_service.py +189 -0
- jettask/webui/services/worker_monitor_service.py +467 -0
- jettask/webui/utils/__init__.py +11 -0
- jettask/webui/utils/time_utils.py +122 -0
- jettask/worker/lifecycle.py +8 -2
- {jettask-0.2.20.dist-info → jettask-0.2.24.dist-info}/METADATA +1 -1
- jettask-0.2.24.dist-info/RECORD +142 -0
- jettask/executor/executor.py +0 -338
- jettask/persistence/backlog_monitor.py +0 -567
- jettask/persistence/base.py +0 -2334
- jettask/persistence/db_manager.py +0 -516
- jettask/persistence/maintenance.py +0 -81
- jettask/persistence/message_consumer.py +0 -259
- jettask/persistence/models.py +0 -49
- jettask/persistence/offline_recovery.py +0 -196
- jettask/persistence/queue_discovery.py +0 -215
- jettask/persistence/task_persistence.py +0 -218
- jettask/persistence/task_updater.py +0 -583
- jettask/scheduler/add_execution_count.sql +0 -11
- jettask/scheduler/add_priority_field.sql +0 -26
- jettask/scheduler/add_scheduler_id.sql +0 -25
- jettask/scheduler/add_scheduler_id_index.sql +0 -10
- jettask/scheduler/make_scheduler_id_required.sql +0 -28
- jettask/scheduler/migrate_interval_seconds.sql +0 -9
- jettask/scheduler/performance_optimization.sql +0 -45
- jettask/scheduler/run_scheduler.py +0 -186
- jettask/scheduler/schema.sql +0 -84
- jettask/task/task_executor.py +0 -318
- jettask/webui/api/analytics.py +0 -323
- jettask/webui/config.py +0 -90
- jettask/webui/models/__init__.py +0 -3
- jettask/webui/models/namespace.py +0 -63
- jettask/webui/namespace_manager/__init__.py +0 -10
- jettask/webui/namespace_manager/multi.py +0 -593
- jettask/webui/namespace_manager/unified.py +0 -193
- jettask/webui/run.py +0 -46
- jettask-0.2.20.dist-info/RECORD +0 -145
- {jettask-0.2.20.dist-info → jettask-0.2.24.dist-info}/WHEEL +0 -0
- {jettask-0.2.20.dist-info → jettask-0.2.24.dist-info}/entry_points.txt +0 -0
- {jettask-0.2.20.dist-info → jettask-0.2.24.dist-info}/licenses/LICENSE +0 -0
- {jettask-0.2.20.dist-info → jettask-0.2.24.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
"""
|
2
|
+
命名空间依赖注入工具
|
3
|
+
提供统一的命名空间参数处理和数据库连接管理
|
4
|
+
"""
|
5
|
+
import logging
|
6
|
+
from typing import Optional
|
7
|
+
from fastapi import Depends, HTTPException, Path, Request
|
8
|
+
from jettask.core.namespace import NamespaceConnection, NamespaceDataAccessManager
|
9
|
+
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
|
13
|
+
class NamespaceContext:
|
14
|
+
"""
|
15
|
+
命名空间上下文对象
|
16
|
+
封装命名空间的所有信息和数据库连接
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(
|
20
|
+
self,
|
21
|
+
namespace_name: str,
|
22
|
+
connection: NamespaceConnection,
|
23
|
+
manager: NamespaceDataAccessManager
|
24
|
+
):
|
25
|
+
self.namespace_name = namespace_name
|
26
|
+
self.connection = connection
|
27
|
+
self.manager = manager
|
28
|
+
|
29
|
+
async def get_redis_client(self, decode: bool = True):
|
30
|
+
"""获取 Redis 客户端"""
|
31
|
+
return await self.connection.get_redis_client(decode=decode)
|
32
|
+
|
33
|
+
async def get_pg_session(self):
|
34
|
+
"""获取 PostgreSQL 会话"""
|
35
|
+
return await self.connection.get_pg_session()
|
36
|
+
|
37
|
+
@property
|
38
|
+
def redis_prefix(self) -> str:
|
39
|
+
"""获取 Redis 键前缀"""
|
40
|
+
return self.connection.redis_prefix
|
41
|
+
|
42
|
+
@property
|
43
|
+
def redis_config(self) -> dict:
|
44
|
+
"""获取 Redis 配置"""
|
45
|
+
return self.connection.redis_config
|
46
|
+
|
47
|
+
@property
|
48
|
+
def pg_config(self) -> dict:
|
49
|
+
"""获取 PostgreSQL 配置"""
|
50
|
+
return self.connection.pg_config
|
51
|
+
|
52
|
+
|
53
|
+
def get_namespace_manager(request: Request) -> NamespaceDataAccessManager:
|
54
|
+
"""
|
55
|
+
获取命名空间数据访问管理器
|
56
|
+
从 app.state 中获取全局实例
|
57
|
+
"""
|
58
|
+
if not hasattr(request.app.state, 'namespace_data_access'):
|
59
|
+
raise HTTPException(
|
60
|
+
status_code=500,
|
61
|
+
detail="Namespace data access not initialized"
|
62
|
+
)
|
63
|
+
|
64
|
+
# namespace_data_access 是 NamespaceJetTaskDataAccess 实例
|
65
|
+
# 它包含一个 manager 属性
|
66
|
+
return request.app.state.namespace_data_access.manager
|
67
|
+
|
68
|
+
|
69
|
+
async def get_namespace_context(
|
70
|
+
namespace: str = Path(..., description="命名空间名称", example="default"),
|
71
|
+
manager: NamespaceDataAccessManager = Depends(get_namespace_manager)
|
72
|
+
) -> NamespaceContext:
|
73
|
+
"""
|
74
|
+
获取命名空间上下文(依赖注入函数)
|
75
|
+
|
76
|
+
这个函数会:
|
77
|
+
1. 从路径参数中提取 namespace 名称
|
78
|
+
2. 从任务中心API或Nacos获取命名空间配置
|
79
|
+
3. 建立数据库连接(Redis + PostgreSQL)
|
80
|
+
4. 返回封装好的命名空间上下文对象
|
81
|
+
|
82
|
+
使用示例:
|
83
|
+
```python
|
84
|
+
@router.get("/{namespace}/queues")
|
85
|
+
async def get_queues(
|
86
|
+
ns: NamespaceContext = Depends(get_namespace_context)
|
87
|
+
):
|
88
|
+
# 直接使用 ns 对象访问数据库
|
89
|
+
redis_client = await ns.get_redis_client()
|
90
|
+
# ... 执行操作
|
91
|
+
return {"namespace": ns.namespace_name}
|
92
|
+
```
|
93
|
+
|
94
|
+
Args:
|
95
|
+
namespace: 从路径参数中提取的命名空间名称
|
96
|
+
manager: 命名空间数据访问管理器(自动注入)
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
NamespaceContext: 命名空间上下文对象
|
100
|
+
|
101
|
+
Raises:
|
102
|
+
HTTPException: 当命名空间不存在或配置错误时
|
103
|
+
"""
|
104
|
+
try:
|
105
|
+
# 获取命名空间的数据库连接
|
106
|
+
connection = await manager.get_connection(namespace)
|
107
|
+
|
108
|
+
# 创建并返回上下文对象
|
109
|
+
return NamespaceContext(
|
110
|
+
namespace_name=namespace,
|
111
|
+
connection=connection,
|
112
|
+
manager=manager
|
113
|
+
)
|
114
|
+
|
115
|
+
except ValueError as e:
|
116
|
+
logger.error(f"命名空间 '{namespace}' 配置错误: {e}")
|
117
|
+
raise HTTPException(
|
118
|
+
status_code=404,
|
119
|
+
detail=f"命名空间 '{namespace}' 不存在或配置错误"
|
120
|
+
)
|
121
|
+
except Exception as e:
|
122
|
+
logger.error(f"获取命名空间 '{namespace}' 上下文失败: {e}", exc_info=True)
|
123
|
+
raise HTTPException(
|
124
|
+
status_code=500,
|
125
|
+
detail=f"获取命名空间连接失败: {str(e)}"
|
126
|
+
)
|
127
|
+
|
128
|
+
|
129
|
+
# 为了向后兼容,提供一个简化的依赖函数
|
130
|
+
async def get_namespace_connection(
|
131
|
+
namespace: str = Path(..., description="命名空间名称", example="default"),
|
132
|
+
manager: NamespaceDataAccessManager = Depends(get_namespace_manager)
|
133
|
+
) -> NamespaceConnection:
|
134
|
+
"""
|
135
|
+
获取命名空间数据库连接(简化版本)
|
136
|
+
|
137
|
+
直接返回 NamespaceConnection 对象,适用于简单场景
|
138
|
+
|
139
|
+
Args:
|
140
|
+
namespace: 命名空间名称
|
141
|
+
manager: 命名空间数据访问管理器
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
NamespaceConnection: 数据库连接对象
|
145
|
+
"""
|
146
|
+
try:
|
147
|
+
return await manager.get_connection(namespace)
|
148
|
+
except ValueError as e:
|
149
|
+
logger.error(f"命名空间 '{namespace}' 配置错误: {e}")
|
150
|
+
raise HTTPException(
|
151
|
+
status_code=404,
|
152
|
+
detail=f"命名空间 '{namespace}' 不存在或配置错误"
|
153
|
+
)
|
154
|
+
except Exception as e:
|
155
|
+
logger.error(f"获取命名空间 '{namespace}' 连接失败: {e}", exc_info=True)
|
156
|
+
raise HTTPException(
|
157
|
+
status_code=500,
|
158
|
+
detail=f"获取命名空间连接失败: {str(e)}"
|
159
|
+
)
|
160
|
+
|
161
|
+
|
162
|
+
__all__ = [
|
163
|
+
'NamespaceContext',
|
164
|
+
'get_namespace_context',
|
165
|
+
'get_namespace_connection',
|
166
|
+
'get_namespace_manager'
|
167
|
+
]
|
@@ -0,0 +1,186 @@
|
|
1
|
+
"""
|
2
|
+
队列通配符匹配工具
|
3
|
+
|
4
|
+
提供队列名称的通配符匹配功能,支持动态队列发现场景。
|
5
|
+
"""
|
6
|
+
|
7
|
+
import fnmatch
|
8
|
+
from typing import List, Dict, Set, Tuple
|
9
|
+
|
10
|
+
|
11
|
+
def is_wildcard_pattern(queue: str) -> bool:
|
12
|
+
"""
|
13
|
+
检查队列名是否包含通配符
|
14
|
+
|
15
|
+
Args:
|
16
|
+
queue: 队列名称
|
17
|
+
|
18
|
+
Returns:
|
19
|
+
bool: 如果包含 * 或 ? 通配符则返回 True
|
20
|
+
|
21
|
+
Examples:
|
22
|
+
>>> is_wildcard_pattern('robust_*')
|
23
|
+
True
|
24
|
+
>>> is_wildcard_pattern('test?')
|
25
|
+
True
|
26
|
+
>>> is_wildcard_pattern('normal_queue')
|
27
|
+
False
|
28
|
+
"""
|
29
|
+
return '*' in queue or '?' in queue
|
30
|
+
|
31
|
+
|
32
|
+
def separate_wildcard_and_static_queues(queues: List[str]) -> Tuple[List[str], List[str]]:
|
33
|
+
"""
|
34
|
+
分离通配符队列和静态队列
|
35
|
+
|
36
|
+
Args:
|
37
|
+
queues: 队列列表
|
38
|
+
|
39
|
+
Returns:
|
40
|
+
tuple: (wildcard_patterns, static_queues)
|
41
|
+
- wildcard_patterns: 包含通配符的队列模式列表
|
42
|
+
- static_queues: 不包含通配符的静态队列列表
|
43
|
+
|
44
|
+
Examples:
|
45
|
+
>>> separate_wildcard_and_static_queues(['test*', 'robot', 'data?'])
|
46
|
+
(['test*', 'data?'], ['robot'])
|
47
|
+
"""
|
48
|
+
wildcard_patterns = []
|
49
|
+
static_queues = []
|
50
|
+
|
51
|
+
for queue in queues:
|
52
|
+
if is_wildcard_pattern(queue):
|
53
|
+
wildcard_patterns.append(queue)
|
54
|
+
else:
|
55
|
+
static_queues.append(queue)
|
56
|
+
|
57
|
+
return wildcard_patterns, static_queues
|
58
|
+
|
59
|
+
|
60
|
+
def match_queue_to_pattern(queue: str, patterns: List[str]) -> str:
|
61
|
+
"""
|
62
|
+
将实际队列名匹配到通配符模式
|
63
|
+
|
64
|
+
Args:
|
65
|
+
queue: 实际队列名,如 'robust_bench2'
|
66
|
+
patterns: 通配符模式列表,如 ['robust_*', 'test*']
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
str: 匹配到的模式,如果没有匹配则返回 None
|
70
|
+
|
71
|
+
Examples:
|
72
|
+
>>> match_queue_to_pattern('robust_bench2', ['robust_*', 'test*'])
|
73
|
+
'robust_*'
|
74
|
+
>>> match_queue_to_pattern('robot', ['robust_*', 'test*'])
|
75
|
+
None
|
76
|
+
"""
|
77
|
+
for pattern in patterns:
|
78
|
+
if fnmatch.fnmatch(queue, pattern):
|
79
|
+
return pattern
|
80
|
+
return None
|
81
|
+
|
82
|
+
|
83
|
+
def find_matching_tasks(
|
84
|
+
queue: str,
|
85
|
+
tasks_by_queue: Dict[str, List[str]],
|
86
|
+
wildcard_mode: bool = False
|
87
|
+
) -> List[str]:
|
88
|
+
"""
|
89
|
+
为实际队列名查找对应的任务列表
|
90
|
+
|
91
|
+
支持两种方式:
|
92
|
+
1. 直接匹配:queue 在 tasks_by_queue 的键中
|
93
|
+
2. 通配符匹配:使用通配符模式匹配 tasks_by_queue 的键
|
94
|
+
|
95
|
+
Args:
|
96
|
+
queue: 实际队列名,如 'robust_bench2'
|
97
|
+
tasks_by_queue: 任务映射字典,键可能是通配符,如 {'robust_*': ['task1']}
|
98
|
+
wildcard_mode: 是否启用通配符匹配模式
|
99
|
+
|
100
|
+
Returns:
|
101
|
+
List[str]: 匹配到的任务名称列表
|
102
|
+
|
103
|
+
Examples:
|
104
|
+
>>> tasks_by_queue = {'robust_*': ['benchmark_task'], 'robot': ['clean_task']}
|
105
|
+
>>> find_matching_tasks('robust_bench2', tasks_by_queue, wildcard_mode=True)
|
106
|
+
['benchmark_task']
|
107
|
+
>>> find_matching_tasks('robot', tasks_by_queue, wildcard_mode=True)
|
108
|
+
['clean_task']
|
109
|
+
"""
|
110
|
+
# 先尝试直接匹配
|
111
|
+
task_names = tasks_by_queue.get(queue, [])
|
112
|
+
|
113
|
+
# 如果没有直接匹配且启用了通配符模式,尝试通配符匹配
|
114
|
+
if not task_names and wildcard_mode:
|
115
|
+
for pattern, pattern_tasks in tasks_by_queue.items():
|
116
|
+
# 检查实际队列名是否匹配 tasks_by_queue 中的通配符模式
|
117
|
+
if fnmatch.fnmatch(queue, pattern):
|
118
|
+
task_names.extend(pattern_tasks)
|
119
|
+
|
120
|
+
return task_names
|
121
|
+
|
122
|
+
|
123
|
+
def match_task_queue_to_patterns(
|
124
|
+
task_queue: str,
|
125
|
+
queue_patterns: List[str]
|
126
|
+
) -> bool:
|
127
|
+
"""
|
128
|
+
检查任务的队列名是否匹配任何队列模式
|
129
|
+
|
130
|
+
Args:
|
131
|
+
task_queue: 任务的队列名(可能是通配符),如 'robust_*'
|
132
|
+
queue_patterns: 队列模式列表(可能包含通配符),如 ['robust_*', 'test']
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
bool: 如果匹配则返回 True
|
136
|
+
|
137
|
+
Examples:
|
138
|
+
>>> match_task_queue_to_patterns('robust_*', ['robust_*'])
|
139
|
+
True
|
140
|
+
>>> match_task_queue_to_patterns('robust_*', ['test*'])
|
141
|
+
True # 'robust_*' 匹配 'test*' 的模式
|
142
|
+
>>> match_task_queue_to_patterns('robot', ['robust_*'])
|
143
|
+
False
|
144
|
+
"""
|
145
|
+
for queue_pattern in queue_patterns:
|
146
|
+
# 如果队列模式包含通配符
|
147
|
+
if is_wildcard_pattern(queue_pattern):
|
148
|
+
# 检查 task_queue 是否匹配这个通配符模式
|
149
|
+
if fnmatch.fnmatch(task_queue, queue_pattern) or task_queue == queue_pattern:
|
150
|
+
return True
|
151
|
+
else:
|
152
|
+
# 精确匹配
|
153
|
+
if task_queue == queue_pattern:
|
154
|
+
return True
|
155
|
+
|
156
|
+
return False
|
157
|
+
|
158
|
+
|
159
|
+
def discover_matching_queues(
|
160
|
+
wildcard_patterns: List[str],
|
161
|
+
all_queues: Set[str]
|
162
|
+
) -> Set[str]:
|
163
|
+
"""
|
164
|
+
从所有队列中发现匹配通配符模式的队列
|
165
|
+
|
166
|
+
Args:
|
167
|
+
wildcard_patterns: 通配符模式列表,如 ['test*', 'robust_*']
|
168
|
+
all_queues: 所有可用的队列集合
|
169
|
+
|
170
|
+
Returns:
|
171
|
+
Set[str]: 匹配到的队列集合
|
172
|
+
|
173
|
+
Examples:
|
174
|
+
>>> all_queues = {'test1', 'test2', 'robust_bench', 'robot'}
|
175
|
+
>>> discover_matching_queues(['test*'], all_queues)
|
176
|
+
{'test1', 'test2'}
|
177
|
+
"""
|
178
|
+
matched_queues = set()
|
179
|
+
|
180
|
+
for pattern in wildcard_patterns:
|
181
|
+
# 使用fnmatch进行通配符匹配
|
182
|
+
for queue in all_queues:
|
183
|
+
if fnmatch.fnmatch(queue, pattern):
|
184
|
+
matched_queues.add(queue)
|
185
|
+
|
186
|
+
return matched_queues
|
@@ -17,7 +17,7 @@ from redis.asyncio import Redis
|
|
17
17
|
from typing import Dict, Optional, Set, List, Tuple
|
18
18
|
from collections import defaultdict
|
19
19
|
|
20
|
-
from jettask.
|
20
|
+
from jettask.db.connector import get_sync_redis_client
|
21
21
|
|
22
22
|
logger = logging.getLogger('app')
|
23
23
|
|
@@ -269,6 +269,12 @@ class ConcurrencyRateLimiter:
|
|
269
269
|
# 订阅 Pub/Sub 频道
|
270
270
|
self._pubsub = self.redis.pubsub()
|
271
271
|
await self._pubsub.subscribe(self.release_channel)
|
272
|
+
|
273
|
+
# 标记PubSub连接,防止被空闲连接清理
|
274
|
+
if hasattr(self._pubsub, 'connection') and self._pubsub.connection:
|
275
|
+
self._pubsub.connection._is_pubsub_connection = True
|
276
|
+
logger.info(f"[CONCURRENCY] Marked PubSub connection {id(self._pubsub.connection)} to prevent cleanup")
|
277
|
+
|
272
278
|
logger.debug(f"[CONCURRENCY] Subscribed to channel {self.release_channel}")
|
273
279
|
|
274
280
|
# 启动 Pub/Sub 监听协程
|
jettask/utils/stream_backlog.py
CHANGED
@@ -39,7 +39,7 @@ class StreamBacklogMonitor:
|
|
39
39
|
async def initialize(self):
|
40
40
|
"""初始化连接(使用统一的连接池管理)"""
|
41
41
|
# 初始化Redis连接
|
42
|
-
from jettask.
|
42
|
+
from jettask.db.connector import get_async_redis_client
|
43
43
|
|
44
44
|
self.redis_client = get_async_redis_client(
|
45
45
|
redis_url=self.redis_url,
|
jettask/webui/__init__.py
CHANGED
jettask/webui/api/__init__.py
CHANGED
@@ -3,26 +3,26 @@ API v1 路由模块集合
|
|
3
3
|
"""
|
4
4
|
from fastapi import APIRouter
|
5
5
|
|
6
|
-
# 导入
|
6
|
+
# 导入8个主要模块的路由
|
7
7
|
from .overview import router as overview_router # 概览
|
8
8
|
from .namespaces import router as namespaces_router # 命名空间
|
9
9
|
from .queues import router as queues_router # 队列
|
10
10
|
from .scheduled import router as scheduled_router # 定时任务
|
11
11
|
from .alerts import router as alerts_router # 告警
|
12
|
-
from .analytics import router as analytics_router # 分析
|
13
12
|
from .settings import router as settings_router # 设置
|
13
|
+
from .workers import router as workers_router # Worker 监控
|
14
14
|
|
15
15
|
# 创建 v1 总路由,添加统一的 /api/v1 前缀
|
16
16
|
api_router = APIRouter(prefix="/api/v1")
|
17
17
|
|
18
|
-
#
|
18
|
+
# 按功能模块组织路由
|
19
19
|
api_router.include_router(overview_router) # 系统概览、健康检查
|
20
20
|
api_router.include_router(namespaces_router) # 命名空间管理(独立路由)
|
21
21
|
api_router.include_router(queues_router) # 队列管理、任务处理
|
22
22
|
api_router.include_router(scheduled_router) # 定时任务管理
|
23
23
|
api_router.include_router(alerts_router) # 告警规则管理
|
24
|
-
api_router.include_router(analytics_router) # 数据分析查询
|
25
24
|
api_router.include_router(settings_router) # 系统配置
|
25
|
+
api_router.include_router(workers_router) # Worker 监控
|
26
26
|
|
27
27
|
__all__ = ['api_router']
|
28
28
|
|