jettask 0.2.14__py3-none-any.whl → 0.2.16__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 +14 -35
- jettask/{webui/__main__.py → __main__.py} +4 -4
- jettask/api/__init__.py +103 -0
- jettask/api/v1/__init__.py +29 -0
- jettask/api/v1/alerts.py +226 -0
- jettask/api/v1/analytics.py +323 -0
- jettask/api/v1/namespaces.py +134 -0
- jettask/api/v1/overview.py +136 -0
- jettask/api/v1/queues.py +530 -0
- jettask/api/v1/scheduled.py +420 -0
- jettask/api/v1/settings.py +44 -0
- jettask/{webui/api.py → api.py} +4 -46
- jettask/{webui/backend → backend}/main.py +21 -109
- jettask/{webui/backend → backend}/main_unified.py +1 -1
- jettask/{webui/backend → backend}/namespace_api_old.py +3 -30
- jettask/{webui/backend → backend}/namespace_data_access.py +2 -1
- jettask/{webui/backend → backend}/unified_api_router.py +14 -74
- jettask/{core/cli.py → cli.py} +106 -26
- jettask/config/nacos_config.py +386 -0
- jettask/core/app.py +8 -100
- jettask/core/db_manager.py +515 -0
- jettask/core/event_pool.py +5 -2
- jettask/core/unified_manager_base.py +47 -14
- jettask/{webui/db_init.py → db_init.py} +1 -1
- jettask/executors/asyncio.py +2 -2
- jettask/{webui/integrated_gradio_app.py → integrated_gradio_app.py} +1 -1
- jettask/{webui/multi_namespace_consumer.py → multi_namespace_consumer.py} +5 -2
- jettask/{webui/pg_consumer.py → pg_consumer.py} +137 -69
- jettask/{webui/run.py → run.py} +1 -1
- jettask/{webui/run_webui.py → run_webui.py} +4 -4
- jettask/scheduler/multi_namespace_scheduler.py +2 -2
- jettask/scheduler/unified_manager.py +5 -5
- jettask/scheduler/unified_scheduler_manager.py +1 -1
- jettask/schemas/__init__.py +166 -0
- jettask/schemas/alert.py +99 -0
- jettask/schemas/backlog.py +122 -0
- jettask/schemas/common.py +139 -0
- jettask/schemas/monitoring.py +181 -0
- jettask/schemas/namespace.py +168 -0
- jettask/schemas/queue.py +83 -0
- jettask/schemas/scheduled_task.py +128 -0
- jettask/schemas/task.py +70 -0
- jettask/services/__init__.py +24 -0
- jettask/services/alert_service.py +454 -0
- jettask/services/analytics_service.py +46 -0
- jettask/services/overview_service.py +978 -0
- jettask/services/queue_service.py +711 -0
- jettask/services/redis_monitor_service.py +151 -0
- jettask/services/scheduled_task_service.py +207 -0
- jettask/services/settings_service.py +758 -0
- jettask/services/task_service.py +157 -0
- jettask/{webui/task_center.py → task_center.py} +30 -8
- jettask/{webui/task_center_client.py → task_center_client.py} +1 -1
- jettask/{webui/config.py → webui_config.py} +6 -1
- jettask/webui_exceptions.py +67 -0
- jettask/webui_sql/verify_database.sql +72 -0
- {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/METADATA +3 -1
- jettask-0.2.16.dist-info/RECORD +150 -0
- {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/entry_points.txt +1 -1
- jettask/webui/backend/data_api.py +0 -3294
- jettask/webui/backend/namespace_api.py +0 -295
- jettask/webui/backend/queue_backlog_api.py +0 -727
- jettask/webui/backend/redis_monitor_api.py +0 -476
- jettask/webui/frontend/index.html +0 -13
- jettask/webui/frontend/package.json +0 -30
- jettask/webui/frontend/src/App.css +0 -109
- jettask/webui/frontend/src/App.jsx +0 -66
- jettask/webui/frontend/src/components/NamespaceSelector.jsx +0 -166
- jettask/webui/frontend/src/components/QueueBacklogChart.jsx +0 -298
- jettask/webui/frontend/src/components/QueueBacklogTrend.jsx +0 -638
- jettask/webui/frontend/src/components/QueueDetailsTable.css +0 -65
- jettask/webui/frontend/src/components/QueueDetailsTable.jsx +0 -487
- jettask/webui/frontend/src/components/QueueDetailsTableV2.jsx +0 -465
- jettask/webui/frontend/src/components/ScheduledTaskFilter.jsx +0 -423
- jettask/webui/frontend/src/components/TaskFilter.jsx +0 -425
- jettask/webui/frontend/src/components/TimeRangeSelector.css +0 -21
- jettask/webui/frontend/src/components/TimeRangeSelector.jsx +0 -160
- jettask/webui/frontend/src/components/charts/QueueChart.jsx +0 -111
- jettask/webui/frontend/src/components/charts/QueueTrendChart.jsx +0 -115
- jettask/webui/frontend/src/components/charts/WorkerChart.jsx +0 -40
- jettask/webui/frontend/src/components/common/StatsCard.jsx +0 -18
- jettask/webui/frontend/src/components/layout/AppLayout.css +0 -95
- jettask/webui/frontend/src/components/layout/AppLayout.jsx +0 -49
- jettask/webui/frontend/src/components/layout/Header.css +0 -106
- jettask/webui/frontend/src/components/layout/Header.jsx +0 -106
- jettask/webui/frontend/src/components/layout/SideMenu.css +0 -137
- jettask/webui/frontend/src/components/layout/SideMenu.jsx +0 -209
- jettask/webui/frontend/src/components/layout/TabsNav.css +0 -244
- jettask/webui/frontend/src/components/layout/TabsNav.jsx +0 -206
- jettask/webui/frontend/src/components/layout/UserInfo.css +0 -197
- jettask/webui/frontend/src/components/layout/UserInfo.jsx +0 -197
- jettask/webui/frontend/src/contexts/LoadingContext.jsx +0 -27
- jettask/webui/frontend/src/contexts/NamespaceContext.jsx +0 -72
- jettask/webui/frontend/src/contexts/TabsContext.backup.jsx +0 -245
- jettask/webui/frontend/src/index.css +0 -114
- jettask/webui/frontend/src/main.jsx +0 -22
- jettask/webui/frontend/src/pages/Alerts.jsx +0 -684
- jettask/webui/frontend/src/pages/Dashboard/index.css +0 -35
- jettask/webui/frontend/src/pages/Dashboard/index.jsx +0 -281
- jettask/webui/frontend/src/pages/Dashboard.jsx +0 -1330
- jettask/webui/frontend/src/pages/QueueDetail.jsx +0 -1117
- jettask/webui/frontend/src/pages/QueueMonitor.jsx +0 -527
- jettask/webui/frontend/src/pages/Queues.jsx +0 -12
- jettask/webui/frontend/src/pages/ScheduledTasks.jsx +0 -810
- jettask/webui/frontend/src/pages/Settings.jsx +0 -801
- jettask/webui/frontend/src/pages/Workers.jsx +0 -12
- jettask/webui/frontend/src/services/api.js +0 -159
- jettask/webui/frontend/src/services/queueTrend.js +0 -166
- jettask/webui/frontend/src/utils/suppressWarnings.js +0 -22
- jettask/webui/frontend/src/utils/userPreferences.js +0 -154
- jettask/webui/frontend/vite.config.js +0 -26
- jettask/webui/sql/init_database.sql +0 -640
- jettask-0.2.14.dist-info/RECORD +0 -172
- /jettask/{webui/backend → backend}/__init__.py +0 -0
- /jettask/{webui/backend → backend}/api/__init__.py +0 -0
- /jettask/{webui/backend → backend}/api/v1/__init__.py +0 -0
- /jettask/{webui/backend → backend}/api/v1/monitoring.py +0 -0
- /jettask/{webui/backend → backend}/api/v1/namespaces.py +0 -0
- /jettask/{webui/backend → backend}/api/v1/queues.py +0 -0
- /jettask/{webui/backend → backend}/api/v1/tasks.py +0 -0
- /jettask/{webui/backend → backend}/config.py +0 -0
- /jettask/{webui/backend → backend}/core/__init__.py +0 -0
- /jettask/{webui/backend → backend}/core/cache.py +0 -0
- /jettask/{webui/backend → backend}/core/database.py +0 -0
- /jettask/{webui/backend → backend}/core/exceptions.py +0 -0
- /jettask/{webui/backend → backend}/data_access.py +0 -0
- /jettask/{webui/backend → backend}/dependencies.py +0 -0
- /jettask/{webui/backend → backend}/init_meta_db.py +0 -0
- /jettask/{webui/backend → backend}/main_v2.py +0 -0
- /jettask/{webui/backend → backend}/models/__init__.py +0 -0
- /jettask/{webui/backend → backend}/models/requests.py +0 -0
- /jettask/{webui/backend → backend}/models/responses.py +0 -0
- /jettask/{webui/backend → backend}/queue_stats_v2.py +0 -0
- /jettask/{webui/backend → backend}/services/__init__.py +0 -0
- /jettask/{webui/backend → backend}/start.py +0 -0
- /jettask/{webui/cleanup_deprecated_tables.sql → cleanup_deprecated_tables.sql} +0 -0
- /jettask/{webui/gradio_app.py → gradio_app.py} +0 -0
- /jettask/{webui/__init__.py → main.py} +0 -0
- /jettask/{webui/models.py → models.py} +0 -0
- /jettask/{webui/run_monitor.py → run_monitor.py} +0 -0
- /jettask/{webui/schema.sql → schema.sql} +0 -0
- /jettask/{webui/unified_consumer_manager.py → unified_consumer_manager.py} +0 -0
- /jettask/{webui/models → webui_models}/__init__.py +0 -0
- /jettask/{webui/models → webui_models}/namespace.py +0 -0
- /jettask/{webui/sql → webui_sql}/batch_upsert_functions.sql +0 -0
- {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/WHEEL +0 -0
- {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/licenses/LICENSE +0 -0
- {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
积压监控相关的数据模型
|
|
3
|
+
"""
|
|
4
|
+
from typing import Optional, List, Dict, Any
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BacklogTrendRequest(BaseModel):
|
|
10
|
+
"""积压趋势请求模型"""
|
|
11
|
+
namespace: str = Field(..., description="命名空间")
|
|
12
|
+
queue_name: Optional[str] = Field(None, description="队列名称,为空时查询所有队列")
|
|
13
|
+
start_time: Optional[str] = Field(None, description="开始时间")
|
|
14
|
+
end_time: Optional[str] = Field(None, description="结束时间")
|
|
15
|
+
time_range: Optional[str] = Field(None, description="时间范围,如 '1h', '6h', '1d', '7d'")
|
|
16
|
+
interval: str = Field(default="5m", description="数据聚合间隔")
|
|
17
|
+
metrics: List[str] = Field(
|
|
18
|
+
default=["pending", "processing", "completed", "failed"],
|
|
19
|
+
description="要查询的指标类型"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BacklogSnapshot(BaseModel):
|
|
24
|
+
"""积压快照模型"""
|
|
25
|
+
timestamp: datetime = Field(..., description="快照时间")
|
|
26
|
+
namespace: str = Field(..., description="命名空间")
|
|
27
|
+
queue_name: str = Field(..., description="队列名称")
|
|
28
|
+
|
|
29
|
+
# 任务数量统计
|
|
30
|
+
pending_count: int = Field(default=0, description="待处理任务数")
|
|
31
|
+
processing_count: int = Field(default=0, description="处理中任务数")
|
|
32
|
+
completed_count: int = Field(default=0, description="已完成任务数")
|
|
33
|
+
failed_count: int = Field(default=0, description="失败任务数")
|
|
34
|
+
total_count: int = Field(default=0, description="总任务数")
|
|
35
|
+
|
|
36
|
+
# 性能指标
|
|
37
|
+
throughput: float = Field(default=0.0, description="吞吐量(任务/分钟)")
|
|
38
|
+
avg_processing_time: Optional[float] = Field(None, description="平均处理时间(秒)")
|
|
39
|
+
success_rate: float = Field(default=0.0, description="成功率")
|
|
40
|
+
|
|
41
|
+
# 队列状态
|
|
42
|
+
queue_size: int = Field(default=0, description="队列大小")
|
|
43
|
+
oldest_task_age: Optional[int] = Field(None, description="最老任务年龄(秒)")
|
|
44
|
+
|
|
45
|
+
class Config:
|
|
46
|
+
json_encoders = {
|
|
47
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class BacklogStatistics(BaseModel):
|
|
52
|
+
"""积压统计模型"""
|
|
53
|
+
namespace: str = Field(..., description="命名空间")
|
|
54
|
+
queue_name: Optional[str] = Field(None, description="队列名称")
|
|
55
|
+
time_period: str = Field(..., description="统计时间段")
|
|
56
|
+
|
|
57
|
+
# 汇总统计
|
|
58
|
+
total_tasks: int = Field(default=0, description="总任务数")
|
|
59
|
+
peak_pending: int = Field(default=0, description="峰值待处理任务数")
|
|
60
|
+
avg_pending: float = Field(default=0.0, description="平均待处理任务数")
|
|
61
|
+
peak_processing: int = Field(default=0, description="峰值处理中任务数")
|
|
62
|
+
avg_processing: float = Field(default=0.0, description="平均处理中任务数")
|
|
63
|
+
|
|
64
|
+
# 性能指标
|
|
65
|
+
avg_throughput: float = Field(default=0.0, description="平均吞吐量")
|
|
66
|
+
peak_throughput: float = Field(default=0.0, description="峰值吞吐量")
|
|
67
|
+
avg_processing_time: Optional[float] = Field(None, description="平均处理时间")
|
|
68
|
+
overall_success_rate: float = Field(default=0.0, description="总体成功率")
|
|
69
|
+
|
|
70
|
+
# 时间信息
|
|
71
|
+
start_time: datetime = Field(..., description="统计开始时间")
|
|
72
|
+
end_time: datetime = Field(..., description="统计结束时间")
|
|
73
|
+
|
|
74
|
+
class Config:
|
|
75
|
+
json_encoders = {
|
|
76
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class BacklogTrendResponse(BaseModel):
|
|
81
|
+
"""积压趋势响应模型"""
|
|
82
|
+
namespace: str = Field(..., description="命名空间")
|
|
83
|
+
queue_name: Optional[str] = Field(None, description="队列名称")
|
|
84
|
+
start_time: datetime = Field(..., description="开始时间")
|
|
85
|
+
end_time: datetime = Field(..., description="结束时间")
|
|
86
|
+
interval: str = Field(..., description="数据间隔")
|
|
87
|
+
|
|
88
|
+
# 时间序列数据
|
|
89
|
+
timestamps: List[datetime] = Field(default=[], description="时间戳列表")
|
|
90
|
+
pending_series: List[int] = Field(default=[], description="待处理任务数时间序列")
|
|
91
|
+
processing_series: List[int] = Field(default=[], description="处理中任务数时间序列")
|
|
92
|
+
completed_series: List[int] = Field(default=[], description="已完成任务数时间序列")
|
|
93
|
+
failed_series: List[int] = Field(default=[], description="失败任务数时间序列")
|
|
94
|
+
throughput_series: List[float] = Field(default=[], description="吞吐量时间序列")
|
|
95
|
+
|
|
96
|
+
# 统计摘要
|
|
97
|
+
statistics: Optional[BacklogStatistics] = Field(None, description="统计摘要")
|
|
98
|
+
|
|
99
|
+
class Config:
|
|
100
|
+
json_encoders = {
|
|
101
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class BacklogAlert(BaseModel):
|
|
106
|
+
"""积压告警模型"""
|
|
107
|
+
id: str = Field(..., description="告警ID")
|
|
108
|
+
namespace: str = Field(..., description="命名空间")
|
|
109
|
+
queue_name: str = Field(..., description="队列名称")
|
|
110
|
+
alert_type: str = Field(..., description="告警类型")
|
|
111
|
+
severity: str = Field(..., description="严重级别")
|
|
112
|
+
message: str = Field(..., description="告警消息")
|
|
113
|
+
current_value: float = Field(..., description="当前值")
|
|
114
|
+
threshold: float = Field(..., description="阈值")
|
|
115
|
+
status: str = Field(..., description="告警状态")
|
|
116
|
+
created_at: datetime = Field(..., description="创建时间")
|
|
117
|
+
resolved_at: Optional[datetime] = Field(None, description="解决时间")
|
|
118
|
+
|
|
119
|
+
class Config:
|
|
120
|
+
json_encoders = {
|
|
121
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
122
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""
|
|
2
|
+
通用数据模型
|
|
3
|
+
"""
|
|
4
|
+
from typing import Optional, List, Dict, Any, Union
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ErrorResponse(BaseModel):
|
|
10
|
+
"""错误响应模型"""
|
|
11
|
+
success: bool = Field(default=False, description="请求是否成功")
|
|
12
|
+
error: str = Field(..., description="错误信息")
|
|
13
|
+
error_code: Optional[str] = Field(None, description="错误代码")
|
|
14
|
+
details: Optional[Dict[str, Any]] = Field(None, description="错误详情")
|
|
15
|
+
timestamp: datetime = Field(default_factory=datetime.utcnow, description="错误时间")
|
|
16
|
+
|
|
17
|
+
class Config:
|
|
18
|
+
json_encoders = {
|
|
19
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class FilterCondition(BaseModel):
|
|
24
|
+
"""筛选条件模型"""
|
|
25
|
+
field: str = Field(..., description="字段名称")
|
|
26
|
+
operator: str = Field(
|
|
27
|
+
...,
|
|
28
|
+
description="操作符",
|
|
29
|
+
pattern="^(eq|ne|gt|gte|lt|lte|in|not_in|like|not_like|is_null|is_not_null|between)$"
|
|
30
|
+
)
|
|
31
|
+
value: Optional[Union[str, int, float, bool, List[Any]]] = Field(None, description="比较值")
|
|
32
|
+
case_sensitive: bool = Field(default=True, description="是否区分大小写(字符串比较时)")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class BaseListRequest(BaseModel):
|
|
36
|
+
"""基础列表请求模型"""
|
|
37
|
+
page: int = Field(default=1, ge=1, description="页码")
|
|
38
|
+
page_size: int = Field(default=20, ge=1, le=100, description="每页大小")
|
|
39
|
+
sort_by: Optional[str] = Field(None, description="排序字段")
|
|
40
|
+
sort_order: str = Field(default="desc", description="排序顺序", pattern="^(asc|desc)$")
|
|
41
|
+
filters: List[FilterCondition] = Field(default=[], description="筛选条件")
|
|
42
|
+
search: Optional[str] = Field(None, description="搜索关键词")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class TimeRangeRequest(BaseModel):
|
|
46
|
+
"""时间范围请求模型"""
|
|
47
|
+
start_time: Optional[datetime] = Field(None, description="开始时间")
|
|
48
|
+
end_time: Optional[datetime] = Field(None, description="结束时间")
|
|
49
|
+
time_range: Optional[str] = Field(None, description="时间范围,如 '15m', '1h', '6h', '1d', '7d', '30d'")
|
|
50
|
+
timezone: str = Field(default="UTC", description="时区")
|
|
51
|
+
|
|
52
|
+
def get_time_bounds(self) -> tuple[Optional[datetime], Optional[datetime]]:
|
|
53
|
+
"""获取时间边界"""
|
|
54
|
+
if self.start_time and self.end_time:
|
|
55
|
+
return self.start_time, self.end_time
|
|
56
|
+
elif self.time_range:
|
|
57
|
+
# TODO: 实现时间范围解析逻辑
|
|
58
|
+
return None, None
|
|
59
|
+
return None, None
|
|
60
|
+
|
|
61
|
+
class Config:
|
|
62
|
+
json_encoders = {
|
|
63
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class BatchOperationRequest(BaseModel):
|
|
68
|
+
"""批量操作请求模型"""
|
|
69
|
+
operation: str = Field(..., description="操作类型")
|
|
70
|
+
target_ids: List[str] = Field(..., min_items=1, description="目标ID列表")
|
|
71
|
+
parameters: Dict[str, Any] = Field(default={}, description="操作参数")
|
|
72
|
+
force: bool = Field(default=False, description="是否强制执行")
|
|
73
|
+
reason: Optional[str] = Field(None, description="操作原因")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class BatchOperationResponse(BaseModel):
|
|
77
|
+
"""批量操作响应模型"""
|
|
78
|
+
success: bool = Field(..., description="整体操作是否成功")
|
|
79
|
+
total_count: int = Field(..., description="总操作数")
|
|
80
|
+
success_count: int = Field(..., description="成功数")
|
|
81
|
+
failure_count: int = Field(..., description="失败数")
|
|
82
|
+
results: List[Dict[str, Any]] = Field(default=[], description="详细结果")
|
|
83
|
+
errors: List[str] = Field(default=[], description="错误信息列表")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class PaginationResponse(BaseModel):
|
|
87
|
+
"""分页响应模型"""
|
|
88
|
+
total: int = Field(..., description="总记录数")
|
|
89
|
+
page: int = Field(..., description="当前页码")
|
|
90
|
+
page_size: int = Field(..., description="每页大小")
|
|
91
|
+
total_pages: int = Field(..., description="总页数")
|
|
92
|
+
has_next: bool = Field(..., description="是否有下一页")
|
|
93
|
+
has_prev: bool = Field(..., description="是否有上一页")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class ListResponse(BaseModel):
|
|
97
|
+
"""列表响应模型"""
|
|
98
|
+
success: bool = Field(default=True, description="请求是否成功")
|
|
99
|
+
data: List[Any] = Field(default=[], description="数据列表")
|
|
100
|
+
pagination: Optional[PaginationResponse] = Field(None, description="分页信息")
|
|
101
|
+
filters_applied: List[FilterCondition] = Field(default=[], description="已应用的筛选条件")
|
|
102
|
+
sort_applied: Optional[Dict[str, str]] = Field(None, description="已应用的排序")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class HealthCheck(BaseModel):
|
|
106
|
+
"""健康检查模型"""
|
|
107
|
+
status: str = Field(..., description="服务状态", pattern="^(healthy|unhealthy|degraded)$")
|
|
108
|
+
version: str = Field(..., description="服务版本")
|
|
109
|
+
timestamp: datetime = Field(default_factory=datetime.utcnow, description="检查时间")
|
|
110
|
+
uptime: int = Field(..., description="运行时间(秒)")
|
|
111
|
+
dependencies: Dict[str, Dict[str, Any]] = Field(default={}, description="依赖服务状态")
|
|
112
|
+
|
|
113
|
+
class Config:
|
|
114
|
+
json_encoders = {
|
|
115
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class SystemConfigUpdateRequest(BaseModel):
|
|
120
|
+
"""系统配置更新请求模型"""
|
|
121
|
+
config_key: str = Field(..., description="配置键")
|
|
122
|
+
config_value: Any = Field(..., description="配置值")
|
|
123
|
+
description: Optional[str] = Field(None, description="配置描述")
|
|
124
|
+
category: Optional[str] = Field(None, description="配置分类")
|
|
125
|
+
is_sensitive: bool = Field(default=False, description="是否为敏感配置")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class ApiResponse(BaseModel):
|
|
129
|
+
"""通用API响应模型"""
|
|
130
|
+
success: bool = Field(default=True, description="请求是否成功")
|
|
131
|
+
data: Optional[Any] = Field(None, description="响应数据")
|
|
132
|
+
message: Optional[str] = Field(None, description="响应消息")
|
|
133
|
+
error: Optional[str] = Field(None, description="错误信息")
|
|
134
|
+
timestamp: datetime = Field(default_factory=datetime.utcnow, description="响应时间")
|
|
135
|
+
|
|
136
|
+
class Config:
|
|
137
|
+
json_encoders = {
|
|
138
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
139
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""
|
|
2
|
+
监控和分析相关的数据模型
|
|
3
|
+
"""
|
|
4
|
+
from typing import Optional, List, Dict, Any, Union
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MetricPoint(BaseModel):
|
|
10
|
+
"""指标数据点模型"""
|
|
11
|
+
timestamp: datetime = Field(..., description="时间戳")
|
|
12
|
+
value: Union[int, float] = Field(..., description="指标值")
|
|
13
|
+
labels: Dict[str, str] = Field(default={}, description="标签")
|
|
14
|
+
|
|
15
|
+
class Config:
|
|
16
|
+
json_encoders = {
|
|
17
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TimeSeries(BaseModel):
|
|
22
|
+
"""时间序列模型"""
|
|
23
|
+
metric_name: str = Field(..., description="指标名称")
|
|
24
|
+
labels: Dict[str, str] = Field(default={}, description="标签")
|
|
25
|
+
data_points: List[MetricPoint] = Field(default=[], description="数据点列表")
|
|
26
|
+
unit: Optional[str] = Field(None, description="指标单位")
|
|
27
|
+
description: Optional[str] = Field(None, description="指标描述")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class MonitoringMetrics(BaseModel):
|
|
31
|
+
"""监控指标模型"""
|
|
32
|
+
namespace: str = Field(..., description="命名空间")
|
|
33
|
+
timestamp: datetime = Field(..., description="采集时间")
|
|
34
|
+
|
|
35
|
+
# 系统指标
|
|
36
|
+
cpu_usage: Optional[float] = Field(None, description="CPU使用率")
|
|
37
|
+
memory_usage: Optional[float] = Field(None, description="内存使用率")
|
|
38
|
+
disk_usage: Optional[float] = Field(None, description="磁盘使用率")
|
|
39
|
+
network_io: Optional[Dict[str, float]] = Field(None, description="网络IO统计")
|
|
40
|
+
|
|
41
|
+
# Redis指标
|
|
42
|
+
redis_memory_usage: Optional[float] = Field(None, description="Redis内存使用")
|
|
43
|
+
redis_connected_clients: Optional[int] = Field(None, description="Redis连接数")
|
|
44
|
+
redis_operations_per_sec: Optional[float] = Field(None, description="Redis每秒操作数")
|
|
45
|
+
redis_keyspace_hits: Optional[int] = Field(None, description="Redis键空间命中数")
|
|
46
|
+
redis_keyspace_misses: Optional[int] = Field(None, description="Redis键空间未命中数")
|
|
47
|
+
|
|
48
|
+
# 任务队列指标
|
|
49
|
+
total_queues: int = Field(default=0, description="总队列数")
|
|
50
|
+
total_tasks: int = Field(default=0, description="总任务数")
|
|
51
|
+
pending_tasks: int = Field(default=0, description="待处理任务数")
|
|
52
|
+
processing_tasks: int = Field(default=0, description="处理中任务数")
|
|
53
|
+
completed_tasks: int = Field(default=0, description="已完成任务数")
|
|
54
|
+
failed_tasks: int = Field(default=0, description="失败任务数")
|
|
55
|
+
|
|
56
|
+
# 工作节点指标
|
|
57
|
+
active_workers: int = Field(default=0, description="活跃工作节点数")
|
|
58
|
+
idle_workers: int = Field(default=0, description="空闲工作节点数")
|
|
59
|
+
busy_workers: int = Field(default=0, description="忙碌工作节点数")
|
|
60
|
+
|
|
61
|
+
# 性能指标
|
|
62
|
+
avg_task_processing_time: Optional[float] = Field(None, description="平均任务处理时间")
|
|
63
|
+
task_throughput: Optional[float] = Field(None, description="任务吞吐量")
|
|
64
|
+
success_rate: Optional[float] = Field(None, description="任务成功率")
|
|
65
|
+
error_rate: Optional[float] = Field(None, description="错误率")
|
|
66
|
+
|
|
67
|
+
class Config:
|
|
68
|
+
json_encoders = {
|
|
69
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class AnalyticsData(BaseModel):
|
|
74
|
+
"""分析数据模型"""
|
|
75
|
+
metric_type: str = Field(..., description="指标类型")
|
|
76
|
+
aggregation_period: str = Field(..., description="聚合周期")
|
|
77
|
+
time_series: List[TimeSeries] = Field(default=[], description="时间序列数据")
|
|
78
|
+
summary: Dict[str, Any] = Field(default={}, description="汇总信息")
|
|
79
|
+
insights: List[str] = Field(default=[], description="数据洞察")
|
|
80
|
+
recommendations: List[str] = Field(default=[], description="建议")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class SystemHealth(BaseModel):
|
|
84
|
+
"""系统健康状态模型"""
|
|
85
|
+
overall_status: str = Field(..., description="整体状态", pattern="^(healthy|warning|critical|unknown)$")
|
|
86
|
+
last_check: datetime = Field(..., description="最后检查时间")
|
|
87
|
+
|
|
88
|
+
# 组件健康状态
|
|
89
|
+
redis_status: str = Field(..., description="Redis状态")
|
|
90
|
+
database_status: str = Field(..., description="数据库状态")
|
|
91
|
+
queue_system_status: str = Field(..., description="队列系统状态")
|
|
92
|
+
worker_system_status: str = Field(..., description="工作节点系统状态")
|
|
93
|
+
|
|
94
|
+
# 健康指标
|
|
95
|
+
redis_latency: Optional[float] = Field(None, description="Redis延迟(毫秒)")
|
|
96
|
+
database_latency: Optional[float] = Field(None, description="数据库延迟(毫秒)")
|
|
97
|
+
queue_backlog_health: str = Field(..., description="队列积压健康状态")
|
|
98
|
+
error_rate_health: str = Field(..., description="错误率健康状态")
|
|
99
|
+
|
|
100
|
+
# 告警信息
|
|
101
|
+
active_alerts: List[Dict[str, Any]] = Field(default=[], description="活跃告警")
|
|
102
|
+
warnings: List[str] = Field(default=[], description="警告信息")
|
|
103
|
+
|
|
104
|
+
class Config:
|
|
105
|
+
json_encoders = {
|
|
106
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class DashboardOverviewRequest(BaseModel):
|
|
111
|
+
"""仪表板概览请求模型"""
|
|
112
|
+
namespace: Optional[str] = Field(None, description="命名空间筛选")
|
|
113
|
+
time_range: str = Field(default="1h", description="时间范围")
|
|
114
|
+
refresh_interval: int = Field(default=30, description="刷新间隔(秒)")
|
|
115
|
+
include_metrics: List[str] = Field(
|
|
116
|
+
default=["tasks", "queues", "workers", "performance"],
|
|
117
|
+
description="包含的指标类型"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class DashboardOverview(BaseModel):
|
|
122
|
+
"""仪表板概览模型"""
|
|
123
|
+
timestamp: datetime = Field(..., description="数据时间戳")
|
|
124
|
+
namespace: Optional[str] = Field(None, description="命名空间")
|
|
125
|
+
|
|
126
|
+
# 核心统计
|
|
127
|
+
total_namespaces: int = Field(default=0, description="总命名空间数")
|
|
128
|
+
total_queues: int = Field(default=0, description="总队列数")
|
|
129
|
+
total_tasks: int = Field(default=0, description="总任务数")
|
|
130
|
+
active_workers: int = Field(default=0, description="活跃工作节点数")
|
|
131
|
+
|
|
132
|
+
# 任务状态分布
|
|
133
|
+
task_status_distribution: Dict[str, int] = Field(default={}, description="任务状态分布")
|
|
134
|
+
|
|
135
|
+
# 性能指标
|
|
136
|
+
current_throughput: float = Field(default=0.0, description="当前吞吐量")
|
|
137
|
+
avg_processing_time: Optional[float] = Field(None, description="平均处理时间")
|
|
138
|
+
success_rate: float = Field(default=0.0, description="成功率")
|
|
139
|
+
|
|
140
|
+
# 趋势数据
|
|
141
|
+
task_trends: List[TimeSeries] = Field(default=[], description="任务趋势")
|
|
142
|
+
performance_trends: List[TimeSeries] = Field(default=[], description="性能趋势")
|
|
143
|
+
|
|
144
|
+
# 热点数据
|
|
145
|
+
top_queues: List[Dict[str, Any]] = Field(default=[], description="热门队列")
|
|
146
|
+
recent_failures: List[Dict[str, Any]] = Field(default=[], description="最近失败任务")
|
|
147
|
+
|
|
148
|
+
# 系统状态
|
|
149
|
+
system_health: SystemHealth = Field(..., description="系统健康状态")
|
|
150
|
+
|
|
151
|
+
class Config:
|
|
152
|
+
json_encoders = {
|
|
153
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class WorkerMetrics(BaseModel):
|
|
158
|
+
"""工作节点指标模型"""
|
|
159
|
+
worker_id: str = Field(..., description="工作节点ID")
|
|
160
|
+
namespace: str = Field(..., description="命名空间")
|
|
161
|
+
status: str = Field(..., description="状态")
|
|
162
|
+
last_heartbeat: datetime = Field(..., description="最后心跳时间")
|
|
163
|
+
|
|
164
|
+
# 任务处理统计
|
|
165
|
+
tasks_processed: int = Field(default=0, description="已处理任务数")
|
|
166
|
+
tasks_succeeded: int = Field(default=0, description="成功任务数")
|
|
167
|
+
tasks_failed: int = Field(default=0, description="失败任务数")
|
|
168
|
+
current_task: Optional[str] = Field(None, description="当前处理任务")
|
|
169
|
+
|
|
170
|
+
# 性能指标
|
|
171
|
+
avg_task_time: Optional[float] = Field(None, description="平均任务处理时间")
|
|
172
|
+
cpu_usage: Optional[float] = Field(None, description="CPU使用率")
|
|
173
|
+
memory_usage: Optional[float] = Field(None, description="内存使用率")
|
|
174
|
+
|
|
175
|
+
# 队列信息
|
|
176
|
+
queues: List[str] = Field(default=[], description="监听的队列")
|
|
177
|
+
|
|
178
|
+
class Config:
|
|
179
|
+
json_encoders = {
|
|
180
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
181
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""
|
|
2
|
+
命名空间相关的数据模型
|
|
3
|
+
"""
|
|
4
|
+
from typing import Optional, Dict, Any, List
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from enum import Enum
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ConfigMode(str, Enum):
|
|
11
|
+
"""配置模式枚举"""
|
|
12
|
+
DIRECT = "direct" # 直接配置模式(自由输入)
|
|
13
|
+
NACOS = "nacos" # Nacos配置模式
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class NamespaceCreate(BaseModel):
|
|
17
|
+
"""创建命名空间请求模型"""
|
|
18
|
+
name: str = Field(..., description="命名空间名称")
|
|
19
|
+
description: Optional[str] = Field(None, description="命名空间描述")
|
|
20
|
+
|
|
21
|
+
# 配置模式
|
|
22
|
+
config_mode: ConfigMode = Field(ConfigMode.DIRECT, description="配置模式: direct(直接配置) 或 nacos(Nacos配置)")
|
|
23
|
+
|
|
24
|
+
# Redis配置 - 支持两种方式
|
|
25
|
+
# 方式1: 直接配置字符串 (格式: redis://[password@]host:port/db)
|
|
26
|
+
redis_url: Optional[str] = Field(None, description="Redis连接字符串,格式: redis://[password@]host:port/db")
|
|
27
|
+
# 方式2: Nacos配置键
|
|
28
|
+
redis_nacos_key: Optional[str] = Field(None, description="Redis连接字符串的Nacos配置键")
|
|
29
|
+
|
|
30
|
+
# PostgreSQL配置 - 支持两种方式
|
|
31
|
+
# 方式1: 直接配置字符串 (格式: postgresql://user:password@host:port/database)
|
|
32
|
+
pg_url: Optional[str] = Field(None, description="PostgreSQL连接字符串,格式: postgresql://user:password@host:port/database")
|
|
33
|
+
# 方式2: Nacos配置键
|
|
34
|
+
pg_nacos_key: Optional[str] = Field(None, description="PostgreSQL连接字符串的Nacos配置键")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class NamespaceUpdate(BaseModel):
|
|
38
|
+
"""更新命名空间请求模型"""
|
|
39
|
+
description: Optional[str] = Field(None, description="命名空间描述")
|
|
40
|
+
|
|
41
|
+
# 配置模式
|
|
42
|
+
config_mode: Optional[ConfigMode] = Field(None, description="配置模式: direct(直接配置) 或 nacos(Nacos配置)")
|
|
43
|
+
|
|
44
|
+
# Redis配置 - 支持两种方式
|
|
45
|
+
redis_url: Optional[str] = Field(None, description="Redis连接字符串,格式: redis://[password@]host:port/db")
|
|
46
|
+
redis_nacos_key: Optional[str] = Field(None, description="Redis连接字符串的Nacos配置键")
|
|
47
|
+
|
|
48
|
+
# PostgreSQL配置 - 支持两种方式
|
|
49
|
+
pg_url: Optional[str] = Field(None, description="PostgreSQL连接字符串,格式: postgresql://user:password@host:port/database")
|
|
50
|
+
pg_nacos_key: Optional[str] = Field(None, description="PostgreSQL连接字符串的Nacos配置键")
|
|
51
|
+
|
|
52
|
+
enabled: Optional[bool] = Field(None, description="是否启用")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class NamespaceResponse(BaseModel):
|
|
56
|
+
"""命名空间响应模型"""
|
|
57
|
+
name: str = Field(..., description="命名空间名称")
|
|
58
|
+
description: Optional[str] = Field(None, description="命名空间描述")
|
|
59
|
+
|
|
60
|
+
# Redis配置信息 - 只返回最终的URL
|
|
61
|
+
redis_url: str = Field(..., description="Redis连接字符串")
|
|
62
|
+
|
|
63
|
+
# PostgreSQL配置信息 - 只返回最终的URL
|
|
64
|
+
pg_url: Optional[str] = Field(None, description="PostgreSQL连接字符串")
|
|
65
|
+
|
|
66
|
+
# 连接信息
|
|
67
|
+
connection_url: str = Field(..., description="用于连接此命名空间的URL路径")
|
|
68
|
+
version: int = Field(default=1, description="配置版本号")
|
|
69
|
+
|
|
70
|
+
enabled: bool = Field(..., description="是否启用")
|
|
71
|
+
created_at: datetime = Field(..., description="创建时间")
|
|
72
|
+
updated_at: Optional[datetime] = Field(None, description="更新时间")
|
|
73
|
+
|
|
74
|
+
class Config:
|
|
75
|
+
json_encoders = {
|
|
76
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class NamespaceInfo(BaseModel):
|
|
81
|
+
"""命名空间详细信息模型"""
|
|
82
|
+
name: str = Field(..., description="命名空间名称")
|
|
83
|
+
description: Optional[str] = Field(None, description="命名空间描述")
|
|
84
|
+
redis_config: Dict[str, Any] = Field(..., description="Redis配置")
|
|
85
|
+
status: str = Field(..., description="状态")
|
|
86
|
+
enabled: bool = Field(default=True, description="是否启用")
|
|
87
|
+
created_at: datetime = Field(..., description="创建时间")
|
|
88
|
+
updated_at: Optional[datetime] = Field(None, description="更新时间")
|
|
89
|
+
last_activity: Optional[datetime] = Field(None, description="最后活动时间")
|
|
90
|
+
|
|
91
|
+
# 统计信息
|
|
92
|
+
total_queues: int = Field(default=0, description="总队列数")
|
|
93
|
+
total_tasks: int = Field(default=0, description="总任务数")
|
|
94
|
+
active_workers: int = Field(default=0, description="活跃工作节点数")
|
|
95
|
+
pending_tasks: int = Field(default=0, description="待处理任务数")
|
|
96
|
+
processing_tasks: int = Field(default=0, description="处理中任务数")
|
|
97
|
+
completed_tasks: int = Field(default=0, description="已完成任务数")
|
|
98
|
+
failed_tasks: int = Field(default=0, description="失败任务数")
|
|
99
|
+
|
|
100
|
+
class Config:
|
|
101
|
+
json_encoders = {
|
|
102
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class NamespaceCreateRequest(BaseModel):
|
|
107
|
+
"""命名空间创建请求模型(详细版)"""
|
|
108
|
+
name: str = Field(..., min_length=1, max_length=100, description="命名空间名称")
|
|
109
|
+
display_name: Optional[str] = Field(None, max_length=200, description="显示名称")
|
|
110
|
+
description: Optional[str] = Field(None, max_length=1000, description="命名空间描述")
|
|
111
|
+
|
|
112
|
+
# Redis连接配置
|
|
113
|
+
redis_host: str = Field(..., description="Redis主机地址")
|
|
114
|
+
redis_port: int = Field(..., ge=1, le=65535, description="Redis端口号")
|
|
115
|
+
redis_db: int = Field(default=0, ge=0, le=15, description="Redis数据库编号")
|
|
116
|
+
redis_password: Optional[str] = Field(None, description="Redis密码")
|
|
117
|
+
redis_ssl: bool = Field(default=False, description="是否使用SSL连接")
|
|
118
|
+
redis_ssl_cert_reqs: Optional[str] = Field(None, description="SSL证书验证")
|
|
119
|
+
redis_ssl_ca_certs: Optional[str] = Field(None, description="SSL CA证书路径")
|
|
120
|
+
redis_ssl_certfile: Optional[str] = Field(None, description="SSL客户端证书路径")
|
|
121
|
+
redis_ssl_keyfile: Optional[str] = Field(None, description="SSL私钥路径")
|
|
122
|
+
|
|
123
|
+
# 连接池配置
|
|
124
|
+
redis_max_connections: int = Field(default=50, ge=1, le=1000, description="最大连接数")
|
|
125
|
+
redis_connection_timeout: int = Field(default=30, ge=1, description="连接超时(秒)")
|
|
126
|
+
redis_socket_timeout: int = Field(default=30, ge=1, description="套接字超时(秒)")
|
|
127
|
+
|
|
128
|
+
# 业务配置
|
|
129
|
+
default_queue_prefix: str = Field(default="task", description="默认队列前缀")
|
|
130
|
+
max_queue_size: Optional[int] = Field(None, ge=1, description="队列最大大小")
|
|
131
|
+
task_ttl: int = Field(default=86400, ge=60, description="任务TTL(秒)")
|
|
132
|
+
result_ttl: int = Field(default=3600, ge=60, description="结果TTL(秒)")
|
|
133
|
+
|
|
134
|
+
# 其他设置
|
|
135
|
+
enabled: bool = Field(default=True, description="是否启用")
|
|
136
|
+
auto_create_queues: bool = Field(default=True, description="是否自动创建队列")
|
|
137
|
+
tags: List[str] = Field(default=[], description="标签列表")
|
|
138
|
+
metadata: Dict[str, Any] = Field(default={}, description="元数据")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class NamespaceUpdateRequest(BaseModel):
|
|
142
|
+
"""命名空间更新请求模型(详细版)"""
|
|
143
|
+
display_name: Optional[str] = Field(None, max_length=200, description="显示名称")
|
|
144
|
+
description: Optional[str] = Field(None, max_length=1000, description="命名空间描述")
|
|
145
|
+
|
|
146
|
+
# Redis连接配置
|
|
147
|
+
redis_host: Optional[str] = Field(None, description="Redis主机地址")
|
|
148
|
+
redis_port: Optional[int] = Field(None, ge=1, le=65535, description="Redis端口号")
|
|
149
|
+
redis_db: Optional[int] = Field(None, ge=0, le=15, description="Redis数据库编号")
|
|
150
|
+
redis_password: Optional[str] = Field(None, description="Redis密码")
|
|
151
|
+
redis_ssl: Optional[bool] = Field(None, description="是否使用SSL连接")
|
|
152
|
+
|
|
153
|
+
# 连接池配置
|
|
154
|
+
redis_max_connections: Optional[int] = Field(None, ge=1, le=1000, description="最大连接数")
|
|
155
|
+
redis_connection_timeout: Optional[int] = Field(None, ge=1, description="连接超时(秒)")
|
|
156
|
+
redis_socket_timeout: Optional[int] = Field(None, ge=1, description="套接字超时(秒)")
|
|
157
|
+
|
|
158
|
+
# 业务配置
|
|
159
|
+
default_queue_prefix: Optional[str] = Field(None, description="默认队列前缀")
|
|
160
|
+
max_queue_size: Optional[int] = Field(None, ge=1, description="队列最大大小")
|
|
161
|
+
task_ttl: Optional[int] = Field(None, ge=60, description="任务TTL(秒)")
|
|
162
|
+
result_ttl: Optional[int] = Field(None, ge=60, description="结果TTL(秒)")
|
|
163
|
+
|
|
164
|
+
# 其他设置
|
|
165
|
+
enabled: Optional[bool] = Field(None, description="是否启用")
|
|
166
|
+
auto_create_queues: Optional[bool] = Field(None, description="是否自动创建队列")
|
|
167
|
+
tags: Optional[List[str]] = Field(None, description="标签列表")
|
|
168
|
+
metadata: Optional[Dict[str, Any]] = Field(None, description="元数据")
|