jettask 0.2.16__py3-none-any.whl → 0.2.18__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/config/nacos_config.py +34 -14
- jettask/core/unified_manager_base.py +25 -13
- jettask/scheduler/manager.py +6 -0
- jettask/scheduler/unified_scheduler_manager.py +19 -11
- {jettask-0.2.16.dist-info → jettask-0.2.18.dist-info}/METADATA +1 -1
- {jettask-0.2.16.dist-info → jettask-0.2.18.dist-info}/RECORD +10 -10
- {jettask-0.2.16.dist-info → jettask-0.2.18.dist-info}/WHEEL +0 -0
- {jettask-0.2.16.dist-info → jettask-0.2.18.dist-info}/entry_points.txt +0 -0
- {jettask-0.2.16.dist-info → jettask-0.2.18.dist-info}/licenses/LICENSE +0 -0
- {jettask-0.2.16.dist-info → jettask-0.2.18.dist-info}/top_level.txt +0 -0
jettask/config/nacos_config.py
CHANGED
@@ -53,23 +53,38 @@ class Config:
|
|
53
53
|
# 配置锁,保证线程安全
|
54
54
|
self._config_lock = threading.RLock()
|
55
55
|
|
56
|
+
# 标记是否已初始化
|
57
|
+
self._initialized = False
|
58
|
+
self._config = None
|
59
|
+
|
60
|
+
@property
|
61
|
+
def config(self) -> dict:
|
62
|
+
"""获取当前配置(线程安全,延迟初始化)"""
|
63
|
+
with self._config_lock:
|
64
|
+
# 延迟初始化:第一次访问时才初始化并加载配置
|
65
|
+
if not self._initialized:
|
66
|
+
self._lazy_init()
|
67
|
+
return self._config
|
68
|
+
|
69
|
+
def _lazy_init(self):
|
70
|
+
"""延迟初始化:第一次访问配置时才执行"""
|
71
|
+
if self._initialized:
|
72
|
+
return
|
73
|
+
|
74
|
+
logger.info("第一次访问配置,开始初始化...")
|
75
|
+
|
56
76
|
# 初始化配置
|
57
77
|
self._init_config()
|
58
78
|
|
79
|
+
# 加载配置
|
59
80
|
self._config = self._load_config()
|
60
81
|
|
61
|
-
|
62
82
|
# 启动定时刷新
|
63
|
-
if not self.local_dev_mode and refresh_interval > 0:
|
83
|
+
if not self.local_dev_mode and self.refresh_interval > 0:
|
64
84
|
self.start_refresh_thread()
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
"""获取当前配置(线程安全)"""
|
69
|
-
with self._config_lock:
|
70
|
-
if not hasattr(self, '_config'):
|
71
|
-
self._config = self._load_config()
|
72
|
-
return self._config
|
85
|
+
|
86
|
+
self._initialized = True
|
87
|
+
logger.info("配置初始化完成")
|
73
88
|
|
74
89
|
def _init_config(self):
|
75
90
|
"""初始化配置"""
|
@@ -265,8 +280,7 @@ class Config:
|
|
265
280
|
|
266
281
|
def get(self, key, default=None):
|
267
282
|
"""获取配置项(线程安全)"""
|
268
|
-
|
269
|
-
return self.config.get(key, default)
|
283
|
+
return self.config.get(key, default)
|
270
284
|
|
271
285
|
def refresh(self) -> bool:
|
272
286
|
"""手动刷新配置
|
@@ -274,9 +288,14 @@ class Config:
|
|
274
288
|
Returns:
|
275
289
|
True if config was refreshed, False otherwise
|
276
290
|
"""
|
291
|
+
# 如果还未初始化,不执行刷新
|
292
|
+
if not self._initialized:
|
293
|
+
logger.debug("配置尚未初始化,跳过刷新")
|
294
|
+
return False
|
295
|
+
|
277
296
|
try:
|
278
297
|
logger.info("手动触发配置刷新")
|
279
|
-
old_config = self._config.copy() if
|
298
|
+
old_config = self._config.copy() if self._config else {}
|
280
299
|
|
281
300
|
with self._config_lock:
|
282
301
|
new_config = self._load_config()
|
@@ -365,6 +384,7 @@ class Config:
|
|
365
384
|
def get_config_info(self) -> Dict[str, Any]:
|
366
385
|
"""获取配置信息"""
|
367
386
|
return {
|
387
|
+
'initialized': self._initialized,
|
368
388
|
'version': self.config_version,
|
369
389
|
'last_refresh_time': self.last_refresh_time.isoformat() if self.last_refresh_time else None,
|
370
390
|
'refresh_interval': self.refresh_interval,
|
@@ -374,7 +394,7 @@ class Config:
|
|
374
394
|
'nacos_group': self.nacos_group,
|
375
395
|
'nacos_data_id': self.nacos_data_id,
|
376
396
|
'local_dev_mode': self.local_dev_mode,
|
377
|
-
'config_items_count': len(self.
|
397
|
+
'config_items_count': len(self._config) if self._config else 0
|
378
398
|
}
|
379
399
|
|
380
400
|
def __del__(self):
|
@@ -97,6 +97,12 @@ class UnifiedManagerBase(ABC):
|
|
97
97
|
elif '/api/namespaces/' in self.task_center_url:
|
98
98
|
# 兼容旧格式
|
99
99
|
return self.task_center_url.split('/api/namespaces/')[0]
|
100
|
+
|
101
|
+
# 多命名空间模式,如果URL以 /api/v1/ 结尾,去掉 /api/v1/ 部分
|
102
|
+
if self.task_center_url.endswith('/api/v1/') or self.task_center_url.endswith('/api/v1'):
|
103
|
+
# 从 http://localhost:8001/api/v1/ 提取 http://localhost:8001
|
104
|
+
return self.task_center_url.rstrip('/').rsplit('/api/v1', 1)[0]
|
105
|
+
|
100
106
|
return self.task_center_url
|
101
107
|
|
102
108
|
def get_target_namespaces(self) -> Optional[Set[str]]:
|
@@ -139,13 +145,16 @@ class UnifiedManagerBase(ABC):
|
|
139
145
|
if response.status == 200:
|
140
146
|
data = await response.json()
|
141
147
|
# 构建redis和pg配置
|
142
|
-
|
143
|
-
|
144
|
-
|
148
|
+
# 跳过没有有效配置的命名空间
|
149
|
+
redis_url = data.get('redis_url', '')
|
150
|
+
pg_url = data.get('pg_url', '')
|
145
151
|
|
146
|
-
|
147
|
-
|
148
|
-
|
152
|
+
if not redis_url or not pg_url:
|
153
|
+
logger.warning(f"跳过命名空间 {data['name']}:缺少 Redis 或 PostgreSQL 配置")
|
154
|
+
continue
|
155
|
+
|
156
|
+
redis_config = {'url': redis_url}
|
157
|
+
pg_config = {'url': pg_url}
|
149
158
|
|
150
159
|
ns_info = {
|
151
160
|
'id': data.get('id', data['name']), # 如果没有id,使用name作为id
|
@@ -163,7 +172,7 @@ class UnifiedManagerBase(ABC):
|
|
163
172
|
else:
|
164
173
|
# 获取所有命名空间
|
165
174
|
async with aiohttp.ClientSession() as session:
|
166
|
-
url = f"{base_url}/api/v1/namespaces"
|
175
|
+
url = f"{base_url}/api/v1/namespaces/" # 添加末尾斜杠
|
167
176
|
logger.debug(f"请求所有命名空间配置: {url}")
|
168
177
|
|
169
178
|
async with session.get(url) as response:
|
@@ -171,13 +180,16 @@ class UnifiedManagerBase(ABC):
|
|
171
180
|
data_list = await response.json()
|
172
181
|
for data in data_list:
|
173
182
|
# 构建redis和pg配置
|
174
|
-
|
175
|
-
|
176
|
-
|
183
|
+
# 跳过没有有效配置的命名空间
|
184
|
+
redis_url = data.get('redis_url', '')
|
185
|
+
pg_url = data.get('pg_url', '')
|
186
|
+
|
187
|
+
if not redis_url or not pg_url:
|
188
|
+
logger.warning(f"跳过命名空间 {data['name']}:缺少 Redis 或 PostgreSQL 配置")
|
189
|
+
continue
|
177
190
|
|
178
|
-
|
179
|
-
|
180
|
-
pg_config = {'url': data['pg_url']}
|
191
|
+
redis_config = {'url': redis_url}
|
192
|
+
pg_config = {'url': pg_url}
|
181
193
|
|
182
194
|
ns_info = {
|
183
195
|
'id': data.get('id', data['name']), # 如果没有id,使用name作为id
|
jettask/scheduler/manager.py
CHANGED
@@ -26,6 +26,12 @@ class ScheduledTaskManager:
|
|
26
26
|
else:
|
27
27
|
# 从app对象获取pg_url
|
28
28
|
self.db_url = app_or_db_url.pg_url
|
29
|
+
|
30
|
+
# 将SQLAlchemy格式的URL转换为原生PostgreSQL URL
|
31
|
+
# postgresql+asyncpg:// -> postgresql://
|
32
|
+
if self.db_url and '+' in self.db_url:
|
33
|
+
self.db_url = self.db_url.split('+')[0] + self.db_url[self.db_url.index('://'):]
|
34
|
+
|
29
35
|
self.pool: Optional[asyncpg.Pool] = None
|
30
36
|
|
31
37
|
async def connect(self):
|
@@ -67,18 +67,19 @@ class UnifiedSchedulerManager(UnifiedManagerBase):
|
|
67
67
|
# 创建 Jettask 应用
|
68
68
|
app = Jettask(task_center=tc)
|
69
69
|
|
70
|
-
#
|
71
|
-
manager = ScheduledTaskManager(app
|
70
|
+
# 创建调度器管理器(不需要传递namespace参数)
|
71
|
+
manager = ScheduledTaskManager(app)
|
72
72
|
|
73
73
|
# 创建并启动调度器
|
74
74
|
self.scheduler_instance = TaskScheduler(
|
75
|
-
|
75
|
+
app=app,
|
76
|
+
db_manager=manager,
|
76
77
|
scan_interval=self.scan_interval,
|
77
78
|
batch_size=self.batch_size
|
78
79
|
)
|
79
80
|
|
80
81
|
# 运行调度器
|
81
|
-
await self.scheduler_instance.
|
82
|
+
await self.scheduler_instance.run()
|
82
83
|
|
83
84
|
except Exception as e:
|
84
85
|
logger.error(f"单命名空间调度器运行失败: {e}", exc_info=self.debug)
|
@@ -170,13 +171,20 @@ class UnifiedSchedulerManager(UnifiedManagerBase):
|
|
170
171
|
async def run_scheduler():
|
171
172
|
try:
|
172
173
|
# 构建命名空间特定的URL
|
173
|
-
if '/api/
|
174
|
-
#
|
175
|
-
url = f"{task_center_url}/
|
176
|
-
|
177
|
-
#
|
174
|
+
if task_center_url.endswith('/api/v1/') or task_center_url.endswith('/api/v1'):
|
175
|
+
# 多命名空间模式,URL是 http://localhost:8001/api/v1/
|
176
|
+
url = f"{task_center_url.rstrip('/')}/namespaces/{namespace_name}"
|
177
|
+
elif '/api/v1/namespaces/' in task_center_url:
|
178
|
+
# 单命名空间模式的URL,需要替换命名空间
|
179
|
+
base_url = task_center_url.split('/api/v1/namespaces/')[0]
|
180
|
+
url = f"{base_url}/api/v1/namespaces/{namespace_name}"
|
181
|
+
elif '/api/namespaces/' in task_center_url:
|
182
|
+
# 兼容旧格式
|
178
183
|
base_url = task_center_url.split('/api/namespaces/')[0]
|
179
184
|
url = f"{base_url}/api/namespaces/{namespace_name}"
|
185
|
+
else:
|
186
|
+
# 如果是基础URL,添加命名空间路径
|
187
|
+
url = f"{task_center_url.rstrip('/')}/api/v1/namespaces/{namespace_name}"
|
180
188
|
|
181
189
|
# 创建任务中心连接
|
182
190
|
tc = TaskCenter(url)
|
@@ -189,7 +197,7 @@ class UnifiedSchedulerManager(UnifiedManagerBase):
|
|
189
197
|
# 创建调度器管理器 - ScheduledTaskManager 只接受一个参数
|
190
198
|
manager = ScheduledTaskManager(app)
|
191
199
|
|
192
|
-
# 创建并启动调度器
|
200
|
+
# 创建并启动调度器
|
193
201
|
scheduler = TaskScheduler(
|
194
202
|
app=app,
|
195
203
|
db_manager=manager,
|
@@ -262,7 +270,7 @@ class UnifiedSchedulerManager(UnifiedManagerBase):
|
|
262
270
|
if self.scheduler_instance:
|
263
271
|
# 单命名空间模式
|
264
272
|
logger.info("停止调度器")
|
265
|
-
|
273
|
+
self.scheduler_instance.stop() # stop()不是异步方法
|
266
274
|
|
267
275
|
# 多命名空间模式
|
268
276
|
logger.info("停止所有调度器进程")
|
@@ -59,7 +59,7 @@ jettask/backend/models/requests.py,sha256=fsHiv4sU46biQ1bK1KfV-yxak0LRoFLoe-dPvH
|
|
59
59
|
jettask/backend/models/responses.py,sha256=FwGpAFNL61a2okJFD41TYLcuwu-41FHXrk6P190jxzw,8528
|
60
60
|
jettask/backend/services/__init__.py,sha256=DCf9NuJo1a65q3CXG0GtRksQpDhg3QuvmTYiWjxGjVE,57
|
61
61
|
jettask/config/__init__.py,sha256=qCRGmiXSK45LDU9pr0bUC-VoZAkTK1jAch1i9tvHCeE,158
|
62
|
-
jettask/config/nacos_config.py,sha256=
|
62
|
+
jettask/config/nacos_config.py,sha256=dgOCwflZVVoA71qj113XPTyQMCetLSS6lD6au-2skfU,14847
|
63
63
|
jettask/config/performance.py,sha256=bOdLEskfB_6cRfS10IRgmtKEsJw_CaIZsPHbXxaHwbU,5686
|
64
64
|
jettask/core/__init__.py,sha256=CvBoBCERXCo-jgnkPqAuIgT4uC7oQMnSi7okRxMi6Vc,181
|
65
65
|
jettask/core/app.py,sha256=qQPYl74uKV1ZgnuNTvPNPD0F_JVH20oZrsz9jIJusjk,70737
|
@@ -76,7 +76,7 @@ jettask/core/offline_worker_recovery.py,sha256=L1i61RN5NnPiP7neudmdb_qYMEEvIYRd3
|
|
76
76
|
jettask/core/retry.py,sha256=lX56Z0fvKjEhVbYPHYdoN-W4XUPVplHlfIOupBylEeI,10711
|
77
77
|
jettask/core/task.py,sha256=7VygTXcsBPjkfecz2oGXIVECvuuEI_p4lCjE2FzvLZc,5261
|
78
78
|
jettask/core/task_batch.py,sha256=lSI4ijf7YrMqS9m9NX3qQ3_HMkrCVZ3LGHL_zDOKc4k,4339
|
79
|
-
jettask/core/unified_manager_base.py,sha256=
|
79
|
+
jettask/core/unified_manager_base.py,sha256=Nc3hMzFJeQaMajoXH6A5u0-LCd2jcT9MxEX-VCFUjUU,12050
|
80
80
|
jettask/core/worker_scanner.py,sha256=_ZFlH7eKeg-2lIL-3JFMV_Oht9Shf7VMEw_uyCBh5Tc,11277
|
81
81
|
jettask/executors/__init__.py,sha256=1aXRvwHzlypVcHNYy60UgUELOlNmbPp8oFMS5T0tJbs,186
|
82
82
|
jettask/executors/asyncio.py,sha256=zy2mezaRtri2RYXzl7jG9_idnvX9edFiTZWutPLfx9U,43167
|
@@ -101,7 +101,7 @@ jettask/scheduler/add_scheduler_id.sql,sha256=uDPSnYVjGE75LcOMKuT2kMEbCPW1JEbDq0
|
|
101
101
|
jettask/scheduler/add_scheduler_id_index.sql,sha256=xaY4uXa5QitIEgx4tcDqh1SRZ1NIZXuq5NtQQH_4Liw,471
|
102
102
|
jettask/scheduler/loader.py,sha256=oZtz-RbXlxlHbzUOE2WVutPljtXV7SuPRU0W-4KGlVM,8727
|
103
103
|
jettask/scheduler/make_scheduler_id_required.sql,sha256=ksZ8rA7cAobrcQk3t93CrTePE2G40KQNESqA9WyPF50,854
|
104
|
-
jettask/scheduler/manager.py,sha256=
|
104
|
+
jettask/scheduler/manager.py,sha256=atbDUwlW5NmzrEx63FtKcr508qWfSja5pcE8NDIdo_U,26508
|
105
105
|
jettask/scheduler/migrate_interval_seconds.sql,sha256=40MSij1-YsOX7mQU958v7Qsse6NCId0R6NkZEjeWr-8,391
|
106
106
|
jettask/scheduler/models.py,sha256=Mv-csKjsrYp4nI2H6IldCh6avu-9ke5YTfyufhlYjKI,7376
|
107
107
|
jettask/scheduler/multi_namespace_scheduler.py,sha256=629GGTMi8Rsaw62kzkt4Y8yF59WQMjHk67yrQP3I-4A,11375
|
@@ -110,7 +110,7 @@ jettask/scheduler/run_scheduler.py,sha256=zRp_V5D7CaTsfEDSEuzISN4Pdypj3NR62zbJn8
|
|
110
110
|
jettask/scheduler/scheduler.py,sha256=PUEqVlYH_SyCYxKj0xzvig78AHzpoYhcUHAnLP9v5MU,27733
|
111
111
|
jettask/scheduler/schema.sql,sha256=iBGUrsMYv9_FQCr_0b5DC-XFUXOaLIjnwWH-yvy4LdM,4109
|
112
112
|
jettask/scheduler/unified_manager.py,sha256=rah9xUiZlTJiKu_2EuuM6shn9vAEE3KJ3tMpXlzhmGk,17580
|
113
|
-
jettask/scheduler/unified_scheduler_manager.py,sha256=
|
113
|
+
jettask/scheduler/unified_scheduler_manager.py,sha256=6sVsoaa_bXg49WbDsrZARY024UhfWISg9Oo4_ujpJDU,11734
|
114
114
|
jettask/schemas/__init__.py,sha256=YtyBjdLtZCceqmeVohlykFdgl5xtF_w9jtRmBfMRlqk,3170
|
115
115
|
jettask/schemas/alert.py,sha256=Od29QjDrnLN1Tw_F2rPFSGsqRvbBcO2hf1d8GO1_WEQ,4958
|
116
116
|
jettask/schemas/backlog.py,sha256=Qxl5I2cVI1ek1JujLl8I55IFINpXZr0Kbd1WWoyyRQg,5493
|
@@ -142,9 +142,9 @@ jettask/webui_models/__init__.py,sha256=5cv0oZksj1B3_rzCqsPmF3Gn9NRZLwzMnaJ8bOKG
|
|
142
142
|
jettask/webui_models/namespace.py,sha256=jDj-hZF_-wXzrWAWVDyZVU0JUWDax9apb4Gyykwg-rE,2006
|
143
143
|
jettask/webui_sql/batch_upsert_functions.sql,sha256=5eWOhOD8gWHhtcop_BrCpZTxPFeyBHtt_leNQZO89Cs,6615
|
144
144
|
jettask/webui_sql/verify_database.sql,sha256=HtTup3xHWbOo1BTU_u4i41E9LrPEXB8qYbChL9WeWOc,2313
|
145
|
-
jettask-0.2.
|
146
|
-
jettask-0.2.
|
147
|
-
jettask-0.2.
|
148
|
-
jettask-0.2.
|
149
|
-
jettask-0.2.
|
150
|
-
jettask-0.2.
|
145
|
+
jettask-0.2.18.dist-info/licenses/LICENSE,sha256=sKR8OPWvnqxzcHAmnaVSANpRpeM0Z52PNLCB0ZlFN6c,1062
|
146
|
+
jettask-0.2.18.dist-info/METADATA,sha256=qyPVUJgGayes-hL7OadkIa010jF8nGrbzv8Zid6VS9o,3015
|
147
|
+
jettask-0.2.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
148
|
+
jettask-0.2.18.dist-info/entry_points.txt,sha256=9-8eTLJPgzpBgeGC8WHdMYtldZxHAXFspMeqArVUdew,148
|
149
|
+
jettask-0.2.18.dist-info/top_level.txt,sha256=uymyRUF87-OsSurk5NhpeTW0jy3Wltnn91Zoa6jmAaw,8
|
150
|
+
jettask-0.2.18.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|