jettask 0.2.5__py3-none-any.whl → 0.2.6__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 (93) hide show
  1. jettask/monitor/run_backlog_collector.py +96 -0
  2. jettask/monitor/stream_backlog_monitor.py +362 -0
  3. jettask/pg_consumer/pg_consumer_v2.py +403 -0
  4. jettask/pg_consumer/sql_utils.py +182 -0
  5. jettask/scheduler/__init__.py +17 -0
  6. jettask/scheduler/add_execution_count.sql +11 -0
  7. jettask/scheduler/add_priority_field.sql +26 -0
  8. jettask/scheduler/add_scheduler_id.sql +25 -0
  9. jettask/scheduler/add_scheduler_id_index.sql +10 -0
  10. jettask/scheduler/loader.py +249 -0
  11. jettask/scheduler/make_scheduler_id_required.sql +28 -0
  12. jettask/scheduler/manager.py +696 -0
  13. jettask/scheduler/migrate_interval_seconds.sql +9 -0
  14. jettask/scheduler/models.py +200 -0
  15. jettask/scheduler/multi_namespace_scheduler.py +294 -0
  16. jettask/scheduler/performance_optimization.sql +45 -0
  17. jettask/scheduler/run_scheduler.py +186 -0
  18. jettask/scheduler/scheduler.py +715 -0
  19. jettask/scheduler/schema.sql +84 -0
  20. jettask/scheduler/unified_manager.py +450 -0
  21. jettask/scheduler/unified_scheduler_manager.py +280 -0
  22. jettask/webui/backend/api/__init__.py +3 -0
  23. jettask/webui/backend/api/v1/__init__.py +17 -0
  24. jettask/webui/backend/api/v1/monitoring.py +431 -0
  25. jettask/webui/backend/api/v1/namespaces.py +504 -0
  26. jettask/webui/backend/api/v1/queues.py +342 -0
  27. jettask/webui/backend/api/v1/tasks.py +367 -0
  28. jettask/webui/backend/core/__init__.py +3 -0
  29. jettask/webui/backend/core/cache.py +221 -0
  30. jettask/webui/backend/core/database.py +200 -0
  31. jettask/webui/backend/core/exceptions.py +102 -0
  32. jettask/webui/backend/models/__init__.py +3 -0
  33. jettask/webui/backend/models/requests.py +236 -0
  34. jettask/webui/backend/models/responses.py +230 -0
  35. jettask/webui/backend/services/__init__.py +3 -0
  36. jettask/webui/frontend/index.html +13 -0
  37. jettask/webui/models/__init__.py +3 -0
  38. jettask/webui/models/namespace.py +63 -0
  39. jettask/webui/sql/batch_upsert_functions.sql +178 -0
  40. jettask/webui/sql/init_database.sql +640 -0
  41. {jettask-0.2.5.dist-info → jettask-0.2.6.dist-info}/METADATA +11 -9
  42. {jettask-0.2.5.dist-info → jettask-0.2.6.dist-info}/RECORD +46 -53
  43. jettask/webui/frontend/package-lock.json +0 -4833
  44. jettask/webui/frontend/package.json +0 -30
  45. jettask/webui/frontend/src/App.css +0 -109
  46. jettask/webui/frontend/src/App.jsx +0 -66
  47. jettask/webui/frontend/src/components/NamespaceSelector.jsx +0 -166
  48. jettask/webui/frontend/src/components/QueueBacklogChart.jsx +0 -298
  49. jettask/webui/frontend/src/components/QueueBacklogTrend.jsx +0 -638
  50. jettask/webui/frontend/src/components/QueueDetailsTable.css +0 -65
  51. jettask/webui/frontend/src/components/QueueDetailsTable.jsx +0 -487
  52. jettask/webui/frontend/src/components/QueueDetailsTableV2.jsx +0 -465
  53. jettask/webui/frontend/src/components/ScheduledTaskFilter.jsx +0 -423
  54. jettask/webui/frontend/src/components/TaskFilter.jsx +0 -425
  55. jettask/webui/frontend/src/components/TimeRangeSelector.css +0 -21
  56. jettask/webui/frontend/src/components/TimeRangeSelector.jsx +0 -160
  57. jettask/webui/frontend/src/components/charts/QueueChart.jsx +0 -111
  58. jettask/webui/frontend/src/components/charts/QueueTrendChart.jsx +0 -115
  59. jettask/webui/frontend/src/components/charts/WorkerChart.jsx +0 -40
  60. jettask/webui/frontend/src/components/common/StatsCard.jsx +0 -18
  61. jettask/webui/frontend/src/components/layout/AppLayout.css +0 -95
  62. jettask/webui/frontend/src/components/layout/AppLayout.jsx +0 -49
  63. jettask/webui/frontend/src/components/layout/Header.css +0 -106
  64. jettask/webui/frontend/src/components/layout/Header.jsx +0 -106
  65. jettask/webui/frontend/src/components/layout/SideMenu.css +0 -137
  66. jettask/webui/frontend/src/components/layout/SideMenu.jsx +0 -209
  67. jettask/webui/frontend/src/components/layout/TabsNav.css +0 -244
  68. jettask/webui/frontend/src/components/layout/TabsNav.jsx +0 -206
  69. jettask/webui/frontend/src/components/layout/UserInfo.css +0 -197
  70. jettask/webui/frontend/src/components/layout/UserInfo.jsx +0 -197
  71. jettask/webui/frontend/src/contexts/LoadingContext.jsx +0 -27
  72. jettask/webui/frontend/src/contexts/NamespaceContext.jsx +0 -72
  73. jettask/webui/frontend/src/contexts/TabsContext.backup.jsx +0 -245
  74. jettask/webui/frontend/src/index.css +0 -114
  75. jettask/webui/frontend/src/main.jsx +0 -20
  76. jettask/webui/frontend/src/pages/Alerts.jsx +0 -684
  77. jettask/webui/frontend/src/pages/Dashboard/index.css +0 -35
  78. jettask/webui/frontend/src/pages/Dashboard/index.jsx +0 -281
  79. jettask/webui/frontend/src/pages/Dashboard.jsx +0 -1330
  80. jettask/webui/frontend/src/pages/QueueDetail.jsx +0 -1117
  81. jettask/webui/frontend/src/pages/QueueMonitor.jsx +0 -527
  82. jettask/webui/frontend/src/pages/Queues.jsx +0 -12
  83. jettask/webui/frontend/src/pages/ScheduledTasks.jsx +0 -809
  84. jettask/webui/frontend/src/pages/Settings.jsx +0 -800
  85. jettask/webui/frontend/src/pages/Workers.jsx +0 -12
  86. jettask/webui/frontend/src/services/api.js +0 -114
  87. jettask/webui/frontend/src/services/queueTrend.js +0 -152
  88. jettask/webui/frontend/src/utils/suppressWarnings.js +0 -22
  89. jettask/webui/frontend/src/utils/userPreferences.js +0 -154
  90. {jettask-0.2.5.dist-info → jettask-0.2.6.dist-info}/WHEEL +0 -0
  91. {jettask-0.2.5.dist-info → jettask-0.2.6.dist-info}/entry_points.txt +0 -0
  92. {jettask-0.2.5.dist-info → jettask-0.2.6.dist-info}/licenses/LICENSE +0 -0
  93. {jettask-0.2.5.dist-info → jettask-0.2.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ 定时任务调度器启动脚本
4
+ """
5
+ import asyncio
6
+ import os
7
+ import sys
8
+ import signal
9
+ from pathlib import Path
10
+
11
+ # 添加项目根目录到Python路径
12
+ project_root = Path(__file__).parent.parent.parent
13
+ sys.path.insert(0, str(project_root))
14
+
15
+ from jettask import Jettask
16
+ from jettask.scheduler.scheduler import TaskScheduler
17
+ from jettask.scheduler.manager import ScheduledTaskManager
18
+ from jettask.utils.task_logger import get_task_logger
19
+
20
+ logger = get_task_logger(__name__)
21
+
22
+
23
+ class SchedulerRunner:
24
+ """调度器运行器"""
25
+
26
+ def __init__(self):
27
+ self.scheduler = None
28
+ self.app = None
29
+ self.running = False
30
+
31
+ async def setup(self):
32
+ """初始化设置"""
33
+ # 从环境变量获取配置
34
+ redis_url = os.getenv('JETTASK_REDIS_URL', 'redis://localhost:6379/0')
35
+ db_url = os.getenv('JETTASK_PG_URL', 'postgresql://jettask:123456@localhost:5432/jettask')
36
+
37
+ # 创建Jettask应用实例
38
+ self.app = Jettask(
39
+ redis_url=redis_url,
40
+ pg_url=db_url
41
+ )
42
+
43
+ # 导入任务模块(确保任务被注册)
44
+ try:
45
+ # 尝试导入用户定义的任务模块
46
+ import importlib
47
+ import importlib.util
48
+
49
+ # 先尝试加载示例模块
50
+ example_paths = [
51
+ 'examples.scheduler_auto_demo',
52
+ 'scheduler_auto_demo'
53
+ ]
54
+
55
+ for path in example_paths:
56
+ try:
57
+ example_module = importlib.import_module(path)
58
+ if hasattr(example_module, 'app'):
59
+ # 将任务模块中的任务复制到调度器的app中
60
+ for task_name, task_obj in example_module.app._tasks.items():
61
+ self.app._tasks[task_name] = task_obj
62
+ # 也注册带模块名的任务
63
+ full_name = f"scheduler_auto_demo.{task_name}"
64
+ self.app._tasks[full_name] = task_obj
65
+ logger.info(f"Registered task: {task_name} and {full_name}")
66
+ logger.info(f"Loaded example tasks from module: {path}")
67
+ break
68
+ except ImportError:
69
+ continue
70
+
71
+ # 然后加载用户指定的任务模块
72
+ task_module = os.getenv('JETTASK_TASKS_MODULE', 'tasks')
73
+ if task_module:
74
+ try:
75
+ module = importlib.import_module(task_module)
76
+ # 获取模块中的app对象的任务
77
+ if hasattr(module, 'app'):
78
+ # 将任务模块中的任务复制到调度器的app中
79
+ for task_name, task_obj in module.app._tasks.items():
80
+ self.app._tasks[task_name] = task_obj
81
+ logger.info(f"Registered task: {task_name}")
82
+
83
+ # 注册别名任务(scheduler_auto_demo.send_notification)
84
+ if hasattr(module, 'send_notification'):
85
+ self.app._tasks['scheduler_auto_demo.send_notification'] = module.send_notification
86
+ logger.info("Registered task: scheduler_auto_demo.send_notification")
87
+
88
+ logger.info(f"Loaded tasks from module: {task_module}")
89
+ except ImportError as e:
90
+ logger.warning(f"Could not import tasks module '{task_module}': {e}")
91
+ except Exception as e:
92
+ logger.warning(f"Error loading tasks: {e}")
93
+
94
+ # 创建数据库管理器
95
+ db_manager = ScheduledTaskManager(db_url)
96
+ await db_manager.connect()
97
+
98
+ # 确保数据库表存在
99
+ await db_manager.init_schema()
100
+
101
+ # 创建调度器
102
+ self.scheduler = TaskScheduler(
103
+ app=self.app,
104
+ redis_url=redis_url,
105
+ db_manager=db_manager,
106
+ redis_prefix="jettask:scheduled",
107
+ scan_interval=0.5, # 每0.5秒扫描一次
108
+ batch_size=100, # 每批处理100个任务
109
+ leader_ttl=30 # Leader锁30秒过期
110
+ )
111
+
112
+ await self.scheduler.connect()
113
+ logger.info("Scheduler setup completed")
114
+
115
+ async def run(self):
116
+ """运行调度器"""
117
+ self.running = True
118
+ logger.info("Starting scheduler...")
119
+
120
+ try:
121
+ # 运行调度器
122
+ await self.scheduler.run()
123
+ except Exception as e:
124
+ logger.error(f"Scheduler error: {e}", exc_info=True)
125
+ finally:
126
+ self.running = False
127
+ logger.info("Scheduler stopped")
128
+
129
+ async def shutdown(self):
130
+ """关闭调度器"""
131
+ logger.info("Shutting down scheduler...")
132
+
133
+ if self.scheduler:
134
+ self.scheduler.stop()
135
+ await self.scheduler.disconnect()
136
+
137
+ if self.app:
138
+ # 关闭应用连接
139
+ pass
140
+
141
+ logger.info("Scheduler shutdown completed")
142
+
143
+ def handle_signal(self, signum, frame):
144
+ """处理终止信号"""
145
+ logger.info(f"Received signal {signum}, initiating shutdown...")
146
+ self.running = False
147
+
148
+ # 创建关闭任务
149
+ if self.scheduler:
150
+ self.scheduler.stop()
151
+
152
+
153
+ async def main():
154
+ """主函数"""
155
+ runner = SchedulerRunner()
156
+
157
+ # 设置信号处理
158
+ signal.signal(signal.SIGINT, runner.handle_signal)
159
+ signal.signal(signal.SIGTERM, runner.handle_signal)
160
+
161
+ try:
162
+ # 初始化
163
+ await runner.setup()
164
+
165
+ # 运行调度器
166
+ await runner.run()
167
+
168
+ except KeyboardInterrupt:
169
+ logger.info("Received keyboard interrupt")
170
+ except Exception as e:
171
+ logger.error(f"Unexpected error: {e}", exc_info=True)
172
+ finally:
173
+ # 清理
174
+ await runner.shutdown()
175
+
176
+
177
+ if __name__ == '__main__':
178
+ # 设置日志级别
179
+ import logging
180
+ logging.basicConfig(
181
+ level=logging.INFO,
182
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
183
+ )
184
+
185
+ # 运行主函数
186
+ asyncio.run(main())