jettask 0.2.19__py3-none-any.whl → 0.2.23__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 +12 -3
- jettask/cli.py +314 -228
- jettask/config/__init__.py +9 -1
- jettask/config/config.py +245 -0
- jettask/config/env_loader.py +381 -0
- jettask/config/lua_scripts.py +158 -0
- jettask/config/nacos_config.py +132 -5
- jettask/core/__init__.py +1 -1
- jettask/core/app.py +1573 -666
- jettask/core/app_importer.py +33 -16
- jettask/core/container.py +532 -0
- jettask/core/task.py +1 -4
- jettask/core/unified_manager_base.py +2 -2
- jettask/executor/__init__.py +38 -0
- jettask/executor/core.py +625 -0
- jettask/executor/executor.py +338 -0
- jettask/executor/orchestrator.py +290 -0
- jettask/executor/process_entry.py +638 -0
- jettask/executor/task_executor.py +317 -0
- jettask/messaging/__init__.py +68 -0
- jettask/messaging/event_pool.py +2188 -0
- jettask/messaging/reader.py +519 -0
- jettask/messaging/registry.py +266 -0
- jettask/messaging/scanner.py +369 -0
- jettask/messaging/sender.py +312 -0
- jettask/persistence/__init__.py +118 -0
- jettask/persistence/backlog_monitor.py +567 -0
- jettask/{backend/data_access.py → persistence/base.py} +58 -57
- jettask/persistence/consumer.py +315 -0
- jettask/{core → persistence}/db_manager.py +23 -22
- jettask/persistence/maintenance.py +81 -0
- jettask/persistence/message_consumer.py +259 -0
- jettask/{backend/namespace_data_access.py → persistence/namespace.py} +66 -98
- jettask/persistence/offline_recovery.py +196 -0
- jettask/persistence/queue_discovery.py +215 -0
- jettask/persistence/task_persistence.py +218 -0
- jettask/persistence/task_updater.py +583 -0
- jettask/scheduler/__init__.py +2 -2
- jettask/scheduler/loader.py +6 -5
- jettask/scheduler/run_scheduler.py +1 -1
- jettask/scheduler/scheduler.py +7 -7
- jettask/scheduler/{unified_scheduler_manager.py → scheduler_coordinator.py} +18 -13
- jettask/task/__init__.py +16 -0
- jettask/{router.py → task/router.py} +26 -8
- jettask/task/task_center/__init__.py +9 -0
- jettask/task/task_executor.py +318 -0
- jettask/task/task_registry.py +291 -0
- jettask/test_connection_monitor.py +73 -0
- jettask/utils/__init__.py +31 -1
- jettask/{monitor/run_backlog_collector.py → utils/backlog_collector.py} +1 -1
- jettask/utils/db_connector.py +1629 -0
- jettask/{db_init.py → utils/db_init.py} +1 -1
- jettask/utils/rate_limit/__init__.py +30 -0
- jettask/utils/rate_limit/concurrency_limiter.py +665 -0
- jettask/utils/rate_limit/config.py +145 -0
- jettask/utils/rate_limit/limiter.py +41 -0
- jettask/utils/rate_limit/manager.py +269 -0
- jettask/utils/rate_limit/qps_limiter.py +154 -0
- jettask/utils/rate_limit/task_limiter.py +384 -0
- jettask/utils/serializer.py +3 -0
- jettask/{monitor/stream_backlog_monitor.py → utils/stream_backlog.py} +14 -6
- jettask/utils/time_sync.py +173 -0
- jettask/webui/__init__.py +27 -0
- jettask/{api/v1 → webui/api}/alerts.py +1 -1
- jettask/{api/v1 → webui/api}/analytics.py +2 -2
- jettask/{api/v1 → webui/api}/namespaces.py +1 -1
- jettask/{api/v1 → webui/api}/overview.py +1 -1
- jettask/{api/v1 → webui/api}/queues.py +3 -3
- jettask/{api/v1 → webui/api}/scheduled.py +1 -1
- jettask/{api/v1 → webui/api}/settings.py +1 -1
- jettask/{api.py → webui/app.py} +253 -145
- jettask/webui/namespace_manager/__init__.py +10 -0
- jettask/{multi_namespace_consumer.py → webui/namespace_manager/multi.py} +69 -22
- jettask/{unified_consumer_manager.py → webui/namespace_manager/unified.py} +1 -1
- jettask/{run.py → webui/run.py} +2 -2
- jettask/{services → webui/services}/__init__.py +1 -3
- jettask/{services → webui/services}/overview_service.py +34 -16
- jettask/{services → webui/services}/queue_service.py +1 -1
- jettask/{backend → webui/services}/queue_stats_v2.py +1 -1
- jettask/{services → webui/services}/settings_service.py +1 -1
- jettask/worker/__init__.py +53 -0
- jettask/worker/lifecycle.py +1507 -0
- jettask/worker/manager.py +583 -0
- jettask/{core/offline_worker_recovery.py → worker/recovery.py} +268 -175
- {jettask-0.2.19.dist-info → jettask-0.2.23.dist-info}/METADATA +2 -71
- jettask-0.2.23.dist-info/RECORD +145 -0
- jettask/__main__.py +0 -140
- jettask/api/__init__.py +0 -103
- jettask/backend/__init__.py +0 -1
- jettask/backend/api/__init__.py +0 -3
- jettask/backend/api/v1/__init__.py +0 -17
- jettask/backend/api/v1/monitoring.py +0 -431
- jettask/backend/api/v1/namespaces.py +0 -504
- jettask/backend/api/v1/queues.py +0 -342
- jettask/backend/api/v1/tasks.py +0 -367
- jettask/backend/core/__init__.py +0 -3
- jettask/backend/core/cache.py +0 -221
- jettask/backend/core/database.py +0 -200
- jettask/backend/core/exceptions.py +0 -102
- jettask/backend/dependencies.py +0 -261
- jettask/backend/init_meta_db.py +0 -158
- jettask/backend/main.py +0 -1426
- jettask/backend/main_unified.py +0 -78
- jettask/backend/main_v2.py +0 -394
- jettask/backend/models/__init__.py +0 -3
- jettask/backend/models/requests.py +0 -236
- jettask/backend/models/responses.py +0 -230
- jettask/backend/namespace_api_old.py +0 -267
- jettask/backend/services/__init__.py +0 -3
- jettask/backend/start.py +0 -42
- jettask/backend/unified_api_router.py +0 -1541
- jettask/cleanup_deprecated_tables.sql +0 -16
- jettask/core/consumer_manager.py +0 -1695
- jettask/core/delay_scanner.py +0 -256
- jettask/core/event_pool.py +0 -1700
- jettask/core/heartbeat_process.py +0 -222
- jettask/core/task_batch.py +0 -153
- jettask/core/worker_scanner.py +0 -271
- jettask/executors/__init__.py +0 -5
- jettask/executors/asyncio.py +0 -876
- jettask/executors/base.py +0 -30
- jettask/executors/common.py +0 -148
- jettask/executors/multi_asyncio.py +0 -309
- jettask/gradio_app.py +0 -570
- jettask/integrated_gradio_app.py +0 -1088
- jettask/main.py +0 -0
- jettask/monitoring/__init__.py +0 -3
- jettask/pg_consumer.py +0 -1896
- jettask/run_monitor.py +0 -22
- jettask/run_webui.py +0 -148
- jettask/scheduler/multi_namespace_scheduler.py +0 -294
- jettask/scheduler/unified_manager.py +0 -450
- jettask/task_center_client.py +0 -150
- jettask/utils/serializer_optimized.py +0 -33
- jettask/webui_exceptions.py +0 -67
- jettask-0.2.19.dist-info/RECORD +0 -150
- /jettask/{constants.py → config/constants.py} +0 -0
- /jettask/{backend/config.py → config/task_center.py} +0 -0
- /jettask/{pg_consumer → messaging/pg_consumer}/pg_consumer_v2.py +0 -0
- /jettask/{pg_consumer → messaging/pg_consumer}/sql/add_execution_time_field.sql +0 -0
- /jettask/{pg_consumer → messaging/pg_consumer}/sql/create_new_tables.sql +0 -0
- /jettask/{pg_consumer → messaging/pg_consumer}/sql/create_tables_v3.sql +0 -0
- /jettask/{pg_consumer → messaging/pg_consumer}/sql/migrate_to_new_structure.sql +0 -0
- /jettask/{pg_consumer → messaging/pg_consumer}/sql/modify_time_fields.sql +0 -0
- /jettask/{pg_consumer → messaging/pg_consumer}/sql_utils.py +0 -0
- /jettask/{models.py → persistence/models.py} +0 -0
- /jettask/scheduler/{manager.py → task_crud.py} +0 -0
- /jettask/{schema.sql → schemas/schema.sql} +0 -0
- /jettask/{task_center.py → task/task_center/client.py} +0 -0
- /jettask/{monitoring → utils}/file_watcher.py +0 -0
- /jettask/{services/redis_monitor_service.py → utils/redis_monitor.py} +0 -0
- /jettask/{api/v1 → webui/api}/__init__.py +0 -0
- /jettask/{webui_config.py → webui/config.py} +0 -0
- /jettask/{webui_models → webui/models}/__init__.py +0 -0
- /jettask/{webui_models → webui/models}/namespace.py +0 -0
- /jettask/{services → webui/services}/alert_service.py +0 -0
- /jettask/{services → webui/services}/analytics_service.py +0 -0
- /jettask/{services → webui/services}/scheduled_task_service.py +0 -0
- /jettask/{services → webui/services}/task_service.py +0 -0
- /jettask/{webui_sql → webui/sql}/batch_upsert_functions.sql +0 -0
- /jettask/{webui_sql → webui/sql}/verify_database.sql +0 -0
- {jettask-0.2.19.dist-info → jettask-0.2.23.dist-info}/WHEEL +0 -0
- {jettask-0.2.19.dist-info → jettask-0.2.23.dist-info}/entry_points.txt +0 -0
- {jettask-0.2.19.dist-info → jettask-0.2.23.dist-info}/licenses/LICENSE +0 -0
- {jettask-0.2.19.dist-info → jettask-0.2.23.dist-info}/top_level.txt +0 -0
jettask/core/delay_scanner.py
DELETED
@@ -1,256 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python
|
2
|
-
"""
|
3
|
-
独立的延迟队列扫描器进程
|
4
|
-
用于扫描延迟任务并投递到执行队列
|
5
|
-
"""
|
6
|
-
|
7
|
-
import asyncio
|
8
|
-
import time
|
9
|
-
import logging
|
10
|
-
import signal
|
11
|
-
import sys
|
12
|
-
from typing import Optional
|
13
|
-
import uuid
|
14
|
-
|
15
|
-
import redis.asyncio as aioredis
|
16
|
-
from redis.asyncio.lock import Lock
|
17
|
-
|
18
|
-
logger = logging.getLogger(__name__)
|
19
|
-
|
20
|
-
|
21
|
-
class DelayQueueScanner:
|
22
|
-
"""
|
23
|
-
独立的延迟队列扫描器
|
24
|
-
使用分布式锁确保只有一个扫描器实例在运行
|
25
|
-
"""
|
26
|
-
|
27
|
-
def __init__(
|
28
|
-
self,
|
29
|
-
redis_url: str = "redis://localhost:6379/0",
|
30
|
-
redis_prefix: str = "jettask",
|
31
|
-
scan_interval: float = 1.0,
|
32
|
-
batch_size: int = 100,
|
33
|
-
lock_ttl: int = 10
|
34
|
-
):
|
35
|
-
"""
|
36
|
-
初始化扫描器
|
37
|
-
|
38
|
-
Args:
|
39
|
-
redis_url: Redis连接URL
|
40
|
-
redis_prefix: Redis键前缀
|
41
|
-
scan_interval: 扫描间隔(秒)
|
42
|
-
batch_size: 每次处理的任务数
|
43
|
-
lock_ttl: 分布式锁TTL(秒)
|
44
|
-
"""
|
45
|
-
self.redis_url = redis_url
|
46
|
-
self.redis_prefix = redis_prefix
|
47
|
-
self.scan_interval = scan_interval
|
48
|
-
self.batch_size = batch_size
|
49
|
-
self.lock_ttl = lock_ttl
|
50
|
-
|
51
|
-
self.redis: Optional[aioredis.Redis] = None
|
52
|
-
self.running = False
|
53
|
-
self.scanner_id = f"scanner-{uuid.uuid4().hex[:8]}"
|
54
|
-
|
55
|
-
# 设置信号处理
|
56
|
-
signal.signal(signal.SIGINT, self._signal_handler)
|
57
|
-
signal.signal(signal.SIGTERM, self._signal_handler)
|
58
|
-
|
59
|
-
def _signal_handler(self, signum, frame):
|
60
|
-
"""信号处理器"""
|
61
|
-
logger.info(f"Received signal {signum}, stopping scanner...")
|
62
|
-
self.running = False
|
63
|
-
|
64
|
-
async def connect(self):
|
65
|
-
"""建立Redis连接"""
|
66
|
-
if not self.redis:
|
67
|
-
self.redis = await aioredis.from_url(
|
68
|
-
self.redis_url,
|
69
|
-
encoding="utf-8",
|
70
|
-
decode_responses=False
|
71
|
-
)
|
72
|
-
logger.info(f"Scanner {self.scanner_id} connected to Redis")
|
73
|
-
|
74
|
-
async def disconnect(self):
|
75
|
-
"""关闭Redis连接"""
|
76
|
-
if self.redis:
|
77
|
-
await self.redis.close()
|
78
|
-
self.redis = None
|
79
|
-
|
80
|
-
def _get_queue_key(self) -> str:
|
81
|
-
"""获取延迟队列键名"""
|
82
|
-
return f"{self.redis_prefix}:DELAYED:QUEUE"
|
83
|
-
|
84
|
-
def _get_task_key(self, task_id: str) -> str:
|
85
|
-
"""获取任务详情键名"""
|
86
|
-
return f"{self.redis_prefix}:DELAYED:TASK:{task_id}"
|
87
|
-
|
88
|
-
def _get_lock_key(self) -> str:
|
89
|
-
"""获取分布式锁键名"""
|
90
|
-
return f"{self.redis_prefix}:DELAYED:SCANNER_LOCK"
|
91
|
-
|
92
|
-
def get_lock(self) -> Lock:
|
93
|
-
"""
|
94
|
-
获取Redis分布式锁对象
|
95
|
-
|
96
|
-
Returns:
|
97
|
-
Redis Lock对象
|
98
|
-
"""
|
99
|
-
return Lock(
|
100
|
-
self.redis,
|
101
|
-
self._get_lock_key(),
|
102
|
-
timeout=self.lock_ttl, # 锁的自动过期时间
|
103
|
-
blocking=True, # 阻塞获取
|
104
|
-
blocking_timeout=0.1 # 最多等待0.1秒
|
105
|
-
)
|
106
|
-
|
107
|
-
async def scan_and_deliver(self) -> int:
|
108
|
-
"""
|
109
|
-
扫描并投递到期任务
|
110
|
-
|
111
|
-
Returns:
|
112
|
-
处理的任务数
|
113
|
-
"""
|
114
|
-
# 使用Redis原生锁
|
115
|
-
lock = self.get_lock()
|
116
|
-
|
117
|
-
# 尝试获取锁
|
118
|
-
async with lock:
|
119
|
-
now = time.time()
|
120
|
-
processed_count = 0
|
121
|
-
|
122
|
-
# 使用ZPOPMIN原子地获取并移除到期任务
|
123
|
-
for _ in range(self.batch_size):
|
124
|
-
# 获取分数最小的任务
|
125
|
-
result = await self.redis.zpopmin(self._get_queue_key(), 1)
|
126
|
-
|
127
|
-
if not result:
|
128
|
-
break
|
129
|
-
|
130
|
-
for item in result:
|
131
|
-
if len(item) == 2:
|
132
|
-
task_id_bytes, score = item
|
133
|
-
task_id = task_id_bytes.decode() if isinstance(task_id_bytes, bytes) else task_id_bytes
|
134
|
-
|
135
|
-
# 检查是否到期
|
136
|
-
if score > now:
|
137
|
-
# 还没到期,放回队列
|
138
|
-
await self.redis.zadd(self._get_queue_key(), {task_id: score})
|
139
|
-
break # 后面的任务肯定也没到期
|
140
|
-
|
141
|
-
# 处理到期任务
|
142
|
-
try:
|
143
|
-
await self.deliver_task(task_id)
|
144
|
-
processed_count += 1
|
145
|
-
except Exception as e:
|
146
|
-
logger.error(f"Failed to deliver task {task_id}: {e}")
|
147
|
-
# 失败的任务延迟10秒重试
|
148
|
-
retry_time = time.time() + 10
|
149
|
-
await self.redis.zadd(self._get_queue_key(), {task_id: retry_time})
|
150
|
-
|
151
|
-
if processed_count > 0:
|
152
|
-
logger.info(f"Scanner {self.scanner_id} delivered {processed_count} tasks")
|
153
|
-
|
154
|
-
return processed_count
|
155
|
-
|
156
|
-
async def deliver_task(self, task_id: str):
|
157
|
-
"""
|
158
|
-
投递任务到执行队列
|
159
|
-
|
160
|
-
Args:
|
161
|
-
task_id: 任务ID
|
162
|
-
"""
|
163
|
-
# 获取任务详情
|
164
|
-
task_json = await self.redis.get(self._get_task_key(task_id))
|
165
|
-
|
166
|
-
if not task_json:
|
167
|
-
logger.warning(f"Task {task_id} not found, skipping")
|
168
|
-
return
|
169
|
-
|
170
|
-
import json
|
171
|
-
task_info = json.loads(task_json)
|
172
|
-
|
173
|
-
queue_name = task_info['queue_name']
|
174
|
-
task_data = task_info['task_data']
|
175
|
-
|
176
|
-
# 写入到执行队列(Redis Stream)
|
177
|
-
stream_key = f"{self.redis_prefix}:{queue_name}"
|
178
|
-
await self.redis.xadd(stream_key, {'data': json.dumps(task_data)})
|
179
|
-
|
180
|
-
# 更新任务状态
|
181
|
-
event_id = task_data.get('event_id', task_id)
|
182
|
-
status_key = f"{self.redis_prefix}:TASK:{event_id}"
|
183
|
-
await self.redis.hset(status_key, "status", "pending")
|
184
|
-
|
185
|
-
# 删除任务详情
|
186
|
-
await self.redis.delete(self._get_task_key(task_id))
|
187
|
-
|
188
|
-
logger.info(f"Delivered task {task_id} to queue {queue_name}")
|
189
|
-
|
190
|
-
async def run(self):
|
191
|
-
"""运行扫描器"""
|
192
|
-
await self.connect()
|
193
|
-
|
194
|
-
self.running = True
|
195
|
-
logger.info(f"Delay queue scanner {self.scanner_id} started")
|
196
|
-
logger.info(f"Scan interval: {self.scan_interval}s, Batch size: {self.batch_size}")
|
197
|
-
|
198
|
-
try:
|
199
|
-
while self.running:
|
200
|
-
try:
|
201
|
-
# 扫描并投递任务
|
202
|
-
await self.scan_and_deliver()
|
203
|
-
except Exception as e:
|
204
|
-
logger.error(f"Scanner error: {e}", exc_info=True)
|
205
|
-
|
206
|
-
# 等待下一次扫描
|
207
|
-
await asyncio.sleep(self.scan_interval)
|
208
|
-
|
209
|
-
finally:
|
210
|
-
logger.info(f"Scanner {self.scanner_id} stopped")
|
211
|
-
await self.disconnect()
|
212
|
-
|
213
|
-
|
214
|
-
async def main():
|
215
|
-
"""主函数"""
|
216
|
-
import argparse
|
217
|
-
|
218
|
-
# 配置日志
|
219
|
-
logging.basicConfig(
|
220
|
-
level=logging.INFO,
|
221
|
-
format='%(asctime)s - %(levelname)s - %(message)s',
|
222
|
-
datefmt='%Y-%m-%d %H:%M:%S'
|
223
|
-
)
|
224
|
-
|
225
|
-
# 解析命令行参数
|
226
|
-
parser = argparse.ArgumentParser(description='Jettask Delay Queue Scanner')
|
227
|
-
parser.add_argument('--redis-url', default='redis://localhost:6379/0',
|
228
|
-
help='Redis connection URL')
|
229
|
-
parser.add_argument('--redis-prefix', default='jettask',
|
230
|
-
help='Redis key prefix')
|
231
|
-
parser.add_argument('--scan-interval', type=float, default=1.0,
|
232
|
-
help='Scan interval in seconds')
|
233
|
-
parser.add_argument('--batch-size', type=int, default=100,
|
234
|
-
help='Number of tasks to process per scan')
|
235
|
-
parser.add_argument('--lock-ttl', type=int, default=10,
|
236
|
-
help='Distributed lock TTL in seconds')
|
237
|
-
|
238
|
-
args = parser.parse_args()
|
239
|
-
|
240
|
-
# 创建并运行扫描器
|
241
|
-
scanner = DelayQueueScanner(
|
242
|
-
redis_url=args.redis_url,
|
243
|
-
redis_prefix=args.redis_prefix,
|
244
|
-
scan_interval=args.scan_interval,
|
245
|
-
batch_size=args.batch_size,
|
246
|
-
lock_ttl=args.lock_ttl
|
247
|
-
)
|
248
|
-
|
249
|
-
try:
|
250
|
-
await scanner.run()
|
251
|
-
except KeyboardInterrupt:
|
252
|
-
logger.info("Scanner interrupted by user")
|
253
|
-
|
254
|
-
|
255
|
-
if __name__ == '__main__':
|
256
|
-
asyncio.run(main())
|