jettask 0.2.7__py3-none-any.whl → 0.2.9__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 (66) hide show
  1. jettask/core/cli.py +242 -0
  2. jettask/pg_consumer/sql/add_execution_time_field.sql +29 -0
  3. jettask/pg_consumer/sql/create_new_tables.sql +137 -0
  4. jettask/pg_consumer/sql/create_tables_v3.sql +175 -0
  5. jettask/pg_consumer/sql/migrate_to_new_structure.sql +179 -0
  6. jettask/pg_consumer/sql/modify_time_fields.sql +69 -0
  7. jettask/webui/frontend/package.json +30 -0
  8. jettask/webui/frontend/src/App.css +109 -0
  9. jettask/webui/frontend/src/App.jsx +66 -0
  10. jettask/webui/frontend/src/components/NamespaceSelector.jsx +166 -0
  11. jettask/webui/frontend/src/components/QueueBacklogChart.jsx +298 -0
  12. jettask/webui/frontend/src/components/QueueBacklogTrend.jsx +638 -0
  13. jettask/webui/frontend/src/components/QueueDetailsTable.css +65 -0
  14. jettask/webui/frontend/src/components/QueueDetailsTable.jsx +487 -0
  15. jettask/webui/frontend/src/components/QueueDetailsTableV2.jsx +465 -0
  16. jettask/webui/frontend/src/components/ScheduledTaskFilter.jsx +423 -0
  17. jettask/webui/frontend/src/components/TaskFilter.jsx +425 -0
  18. jettask/webui/frontend/src/components/TimeRangeSelector.css +21 -0
  19. jettask/webui/frontend/src/components/TimeRangeSelector.jsx +160 -0
  20. jettask/webui/frontend/src/components/charts/QueueChart.jsx +111 -0
  21. jettask/webui/frontend/src/components/charts/QueueTrendChart.jsx +115 -0
  22. jettask/webui/frontend/src/components/charts/WorkerChart.jsx +40 -0
  23. jettask/webui/frontend/src/components/common/StatsCard.jsx +18 -0
  24. jettask/webui/frontend/src/components/layout/AppLayout.css +95 -0
  25. jettask/webui/frontend/src/components/layout/AppLayout.jsx +49 -0
  26. jettask/webui/frontend/src/components/layout/Header.css +106 -0
  27. jettask/webui/frontend/src/components/layout/Header.jsx +106 -0
  28. jettask/webui/frontend/src/components/layout/SideMenu.css +137 -0
  29. jettask/webui/frontend/src/components/layout/SideMenu.jsx +209 -0
  30. jettask/webui/frontend/src/components/layout/TabsNav.css +244 -0
  31. jettask/webui/frontend/src/components/layout/TabsNav.jsx +206 -0
  32. jettask/webui/frontend/src/components/layout/UserInfo.css +197 -0
  33. jettask/webui/frontend/src/components/layout/UserInfo.jsx +197 -0
  34. jettask/webui/frontend/src/contexts/LoadingContext.jsx +27 -0
  35. jettask/webui/frontend/src/contexts/NamespaceContext.jsx +72 -0
  36. jettask/webui/frontend/src/contexts/TabsContext.backup.jsx +245 -0
  37. jettask/webui/frontend/src/index.css +114 -0
  38. jettask/webui/frontend/src/main.jsx +20 -0
  39. jettask/webui/frontend/src/pages/Alerts.jsx +684 -0
  40. jettask/webui/frontend/src/pages/Dashboard/index.css +35 -0
  41. jettask/webui/frontend/src/pages/Dashboard/index.jsx +281 -0
  42. jettask/webui/frontend/src/pages/Dashboard.jsx +1330 -0
  43. jettask/webui/frontend/src/pages/QueueDetail.jsx +1117 -0
  44. jettask/webui/frontend/src/pages/QueueMonitor.jsx +527 -0
  45. jettask/webui/frontend/src/pages/Queues.jsx +12 -0
  46. jettask/webui/frontend/src/pages/ScheduledTasks.jsx +809 -0
  47. jettask/webui/frontend/src/pages/Settings.jsx +800 -0
  48. jettask/webui/frontend/src/pages/Workers.jsx +12 -0
  49. jettask/webui/frontend/src/services/api.js +114 -0
  50. jettask/webui/frontend/src/services/queueTrend.js +152 -0
  51. jettask/webui/frontend/src/utils/suppressWarnings.js +22 -0
  52. jettask/webui/frontend/src/utils/userPreferences.js +154 -0
  53. jettask/webui/frontend/vite.config.js +26 -0
  54. {jettask-0.2.7.dist-info → jettask-0.2.9.dist-info}/METADATA +1 -1
  55. {jettask-0.2.7.dist-info → jettask-0.2.9.dist-info}/RECORD +59 -14
  56. jettask/webui/static/dist/assets/index-7129cfe1.css +0 -1
  57. jettask/webui/static/dist/assets/index-8d1935cc.js +0 -774
  58. jettask/webui/static/dist/index.html +0 -15
  59. jettask/webui/static/index.html +0 -1734
  60. jettask/webui/static/queue.html +0 -981
  61. jettask/webui/static/queues.html +0 -549
  62. jettask/webui/static/workers.html +0 -734
  63. {jettask-0.2.7.dist-info → jettask-0.2.9.dist-info}/WHEEL +0 -0
  64. {jettask-0.2.7.dist-info → jettask-0.2.9.dist-info}/entry_points.txt +0 -0
  65. {jettask-0.2.7.dist-info → jettask-0.2.9.dist-info}/licenses/LICENSE +0 -0
  66. {jettask-0.2.7.dist-info → jettask-0.2.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,35 @@
1
+ .dashboard-container {
2
+ padding: 24px;
3
+ }
4
+
5
+ .stats-row {
6
+ margin-bottom: 24px;
7
+ }
8
+
9
+ .chart-controls {
10
+ margin-bottom: 16px;
11
+ }
12
+
13
+ .connection-status {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ gap: 8px;
17
+ padding: 4px 12px;
18
+ border-radius: 4px;
19
+ font-size: 12px;
20
+ }
21
+
22
+ .connection-status.connected {
23
+ background-color: #f6ffed;
24
+ color: #52c41a;
25
+ }
26
+
27
+ .connection-status.disconnected {
28
+ background-color: #fff2e8;
29
+ color: #fa8c16;
30
+ }
31
+
32
+ .connection-status.error {
33
+ background-color: #fff1f0;
34
+ color: #ff4d4f;
35
+ }
@@ -0,0 +1,281 @@
1
+ import React, { useState, useEffect, useRef, useCallback } from 'react'
2
+ import { Row, Col, Card, Statistic, Space, Button, DatePicker, message, Spin } from 'antd'
3
+ import {
4
+ RocketOutlined,
5
+ TeamOutlined,
6
+ AppstoreOutlined,
7
+ CheckCircleOutlined,
8
+ CloseCircleOutlined,
9
+ SyncOutlined,
10
+ ClockCircleOutlined
11
+ } from '@ant-design/icons'
12
+ import dayjs from 'dayjs'
13
+ import StatsCard from '../../components/common/StatsCard'
14
+ import QueueChart from '../../components/charts/QueueChart'
15
+ import WorkerChart from '../../components/charts/WorkerChart'
16
+ import { fetchGlobalStats, fetchQueues, connectWebSocket } from '../../services/api'
17
+ import './index.css'
18
+
19
+ const { RangePicker } = DatePicker
20
+
21
+ const Dashboard = () => {
22
+ // 状态管理
23
+ const [loading, setLoading] = useState(true)
24
+ const [globalStats, setGlobalStats] = useState({
25
+ total_workers: 0,
26
+ online_workers: 0,
27
+ total_queues: 0,
28
+ active_queues: 0,
29
+ total_tasks: 0,
30
+ pending_tasks: 0,
31
+ running_tasks: 0,
32
+ completed_tasks: 0,
33
+ failed_tasks: 0
34
+ })
35
+ const [queues, setQueues] = useState([])
36
+ const [workers, setWorkers] = useState([])
37
+ const [connectionStatus, setConnectionStatus] = useState('disconnected')
38
+
39
+ // 图表时间范围
40
+ const [chartTimeRange, setChartTimeRange] = useState('1h')
41
+ const [customTimeRange, setCustomTimeRange] = useState(null)
42
+
43
+ // WebSocket 引用
44
+ const wsRef = useRef(null)
45
+
46
+ // 时间范围选项
47
+ const timeRangeOptions = [
48
+ { label: '15分钟', value: '15m' },
49
+ { label: '30分钟', value: '30m' },
50
+ { label: '1小时', value: '1h' },
51
+ { label: '3小时', value: '3h' },
52
+ { label: '6小时', value: '6h' },
53
+ { label: '12小时', value: '12h' },
54
+ { label: '24小时', value: '24h' },
55
+ { label: '3天', value: '3d' },
56
+ { label: '7天', value: '7d' },
57
+ ]
58
+
59
+ // 获取数据
60
+ const fetchData = useCallback(async () => {
61
+ try {
62
+ setLoading(true)
63
+
64
+ // 获取全局统计
65
+ const stats = await fetchGlobalStats()
66
+ setGlobalStats(stats)
67
+
68
+ // 获取队列列表
69
+ const queuesData = await fetchQueues()
70
+ setQueues(queuesData.queues || [])
71
+
72
+ } catch (error) {
73
+ console.error('Failed to fetch data:', error)
74
+ message.error('获取数据失败')
75
+ } finally {
76
+ setLoading(false)
77
+ }
78
+ }, [])
79
+
80
+ // WebSocket 连接
81
+ const setupWebSocket = useCallback(() => {
82
+ const ws = connectWebSocket({
83
+ onOpen: () => {
84
+ setConnectionStatus('connected')
85
+ message.success('实时连接已建立')
86
+ },
87
+ onMessage: (data) => {
88
+ // 处理实时数据更新
89
+ if (data.globalStats) {
90
+ setGlobalStats(data.globalStats)
91
+ }
92
+ if (data.workers) {
93
+ const allWorkers = []
94
+ Object.entries(data.workers).forEach(([queueName, queueWorkers]) => {
95
+ queueWorkers.forEach(worker => {
96
+ allWorkers.push({ ...worker, queue: queueName })
97
+ })
98
+ })
99
+ setWorkers(allWorkers)
100
+ }
101
+ },
102
+ onClose: () => {
103
+ setConnectionStatus('disconnected')
104
+ message.warning('实时连接已断开')
105
+ },
106
+ onError: () => {
107
+ setConnectionStatus('error')
108
+ }
109
+ })
110
+
111
+ wsRef.current = ws
112
+ return ws
113
+ }, [])
114
+
115
+ // 组件挂载时初始化
116
+ useEffect(() => {
117
+ fetchData()
118
+ const ws = setupWebSocket()
119
+
120
+ // 设置定时刷新
121
+ const refreshInterval = setInterval(fetchData, 30000) // 30秒刷新一次
122
+
123
+ return () => {
124
+ clearInterval(refreshInterval)
125
+ if (ws) {
126
+ ws.close()
127
+ }
128
+ }
129
+ }, [fetchData, setupWebSocket])
130
+
131
+ // 处理时间范围变化
132
+ const handleTimeRangeChange = (value) => {
133
+ setChartTimeRange(value)
134
+ setCustomTimeRange(null)
135
+ }
136
+
137
+ const handleCustomTimeRangeChange = (dates) => {
138
+ if (dates) {
139
+ setCustomTimeRange(dates)
140
+ setChartTimeRange('custom')
141
+ }
142
+ }
143
+
144
+ // 渲染统计卡片
145
+ const renderStatsCards = () => {
146
+ const statsData = [
147
+ {
148
+ title: 'Workers',
149
+ value: globalStats.online_workers,
150
+ total: globalStats.total_workers,
151
+ icon: <TeamOutlined />,
152
+ color: '#52c41a',
153
+ suffix: `/ ${globalStats.total_workers}`,
154
+ trend: globalStats.online_workers > 0 ? 'up' : 'down'
155
+ },
156
+ {
157
+ title: '活跃队列',
158
+ value: globalStats.active_queues,
159
+ total: globalStats.total_queues,
160
+ icon: <AppstoreOutlined />,
161
+ color: '#1890ff',
162
+ suffix: `/ ${globalStats.total_queues}`,
163
+ },
164
+ {
165
+ title: '运行中任务',
166
+ value: globalStats.running_tasks,
167
+ icon: <SyncOutlined spin />,
168
+ color: '#faad14',
169
+ },
170
+ {
171
+ title: '待处理任务',
172
+ value: globalStats.pending_tasks,
173
+ icon: <ClockCircleOutlined />,
174
+ color: '#13c2c2',
175
+ },
176
+ {
177
+ title: '已完成',
178
+ value: globalStats.completed_tasks,
179
+ icon: <CheckCircleOutlined />,
180
+ color: '#52c41a',
181
+ precision: 0,
182
+ },
183
+ {
184
+ title: '失败任务',
185
+ value: globalStats.failed_tasks,
186
+ icon: <CloseCircleOutlined />,
187
+ color: '#ff4d4f',
188
+ precision: 0,
189
+ },
190
+ ]
191
+
192
+ return statsData.map((stat, index) => (
193
+ <Col xs={24} sm={12} md={8} lg={4} key={index}>
194
+ <StatsCard {...stat} />
195
+ </Col>
196
+ ))
197
+ }
198
+
199
+ return (
200
+ <div className="dashboard-container">
201
+ <Spin spinning={loading} size="large">
202
+ {/* 统计概览 */}
203
+ <Row gutter={[16, 16]} className="stats-row">
204
+ {renderStatsCards()}
205
+ </Row>
206
+
207
+ {/* 图表区域 */}
208
+ <Row gutter={[16, 16]} className="charts-row">
209
+ <Col xs={24} lg={16}>
210
+ <Card
211
+ className="chart-card"
212
+ title="队列处理趋势"
213
+ extra={
214
+ <Space>
215
+ <div className="time-range-selector">
216
+ {timeRangeOptions.map(option => (
217
+ <Button
218
+ key={option.value}
219
+ type={chartTimeRange === option.value ? 'primary' : 'text'}
220
+ size="small"
221
+ onClick={() => handleTimeRangeChange(option.value)}
222
+ >
223
+ {option.label}
224
+ </Button>
225
+ ))}
226
+ </div>
227
+ <RangePicker
228
+ showTime
229
+ size="small"
230
+ value={customTimeRange}
231
+ onChange={handleCustomTimeRangeChange}
232
+ placeholder={['开始时间', '结束时间']}
233
+ />
234
+ </Space>
235
+ }
236
+ >
237
+ <QueueChart
238
+ queues={queues}
239
+ timeRange={chartTimeRange}
240
+ customTimeRange={customTimeRange}
241
+ mode="trend" // 使用趋势图模式
242
+ loading={loading}
243
+ />
244
+ </Card>
245
+ </Col>
246
+
247
+ <Col xs={24} lg={8}>
248
+ <Card
249
+ className="chart-card"
250
+ title="Worker 分布"
251
+ >
252
+ <WorkerChart workers={workers} />
253
+ </Card>
254
+ </Col>
255
+ </Row>
256
+
257
+ {/* 队列状态表格 */}
258
+ <Row gutter={[16, 16]} className="table-row">
259
+ <Col span={24}>
260
+ <Card
261
+ className="table-card"
262
+ title="队列状态"
263
+ extra={
264
+ <Button
265
+ type="link"
266
+ onClick={() => window.location.href = '/queues'}
267
+ >
268
+ 查看全部
269
+ </Button>
270
+ }
271
+ >
272
+ {/* 这里可以添加队列表格组件 */}
273
+ </Card>
274
+ </Col>
275
+ </Row>
276
+ </Spin>
277
+ </div>
278
+ )
279
+ }
280
+
281
+ export default Dashboard