jettask 0.2.23__py3-none-any.whl → 0.2.24__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 (110) hide show
  1. jettask/__init__.py +2 -0
  2. jettask/cli.py +12 -8
  3. jettask/config/lua_scripts.py +37 -0
  4. jettask/config/nacos_config.py +1 -1
  5. jettask/core/app.py +313 -340
  6. jettask/core/container.py +4 -4
  7. jettask/{persistence → core}/namespace.py +93 -27
  8. jettask/core/task.py +16 -9
  9. jettask/core/unified_manager_base.py +136 -26
  10. jettask/db/__init__.py +67 -0
  11. jettask/db/base.py +137 -0
  12. jettask/{utils/db_connector.py → db/connector.py} +130 -26
  13. jettask/db/models/__init__.py +16 -0
  14. jettask/db/models/scheduled_task.py +196 -0
  15. jettask/db/models/task.py +77 -0
  16. jettask/db/models/task_run.py +85 -0
  17. jettask/executor/__init__.py +0 -15
  18. jettask/executor/core.py +76 -31
  19. jettask/executor/process_entry.py +29 -114
  20. jettask/executor/task_executor.py +4 -0
  21. jettask/messaging/event_pool.py +928 -685
  22. jettask/messaging/scanner.py +30 -0
  23. jettask/persistence/__init__.py +28 -103
  24. jettask/persistence/buffer.py +170 -0
  25. jettask/persistence/consumer.py +330 -249
  26. jettask/persistence/manager.py +304 -0
  27. jettask/persistence/persistence.py +391 -0
  28. jettask/scheduler/__init__.py +15 -3
  29. jettask/scheduler/{task_crud.py → database.py} +61 -57
  30. jettask/scheduler/loader.py +2 -2
  31. jettask/scheduler/{scheduler_coordinator.py → manager.py} +23 -6
  32. jettask/scheduler/models.py +14 -10
  33. jettask/scheduler/schedule.py +166 -0
  34. jettask/scheduler/scheduler.py +12 -11
  35. jettask/schemas/__init__.py +50 -1
  36. jettask/schemas/backlog.py +43 -6
  37. jettask/schemas/namespace.py +70 -19
  38. jettask/schemas/queue.py +19 -3
  39. jettask/schemas/responses.py +493 -0
  40. jettask/task/__init__.py +0 -2
  41. jettask/task/router.py +3 -0
  42. jettask/test_connection_monitor.py +1 -1
  43. jettask/utils/__init__.py +7 -5
  44. jettask/utils/db_init.py +8 -4
  45. jettask/utils/namespace_dep.py +167 -0
  46. jettask/utils/queue_matcher.py +186 -0
  47. jettask/utils/rate_limit/concurrency_limiter.py +7 -1
  48. jettask/utils/stream_backlog.py +1 -1
  49. jettask/webui/__init__.py +0 -1
  50. jettask/webui/api/__init__.py +4 -4
  51. jettask/webui/api/alerts.py +806 -71
  52. jettask/webui/api/example_refactored.py +400 -0
  53. jettask/webui/api/namespaces.py +390 -45
  54. jettask/webui/api/overview.py +300 -54
  55. jettask/webui/api/queues.py +971 -267
  56. jettask/webui/api/scheduled.py +1249 -56
  57. jettask/webui/api/settings.py +129 -7
  58. jettask/webui/api/workers.py +442 -0
  59. jettask/webui/app.py +46 -2329
  60. jettask/webui/middleware/__init__.py +6 -0
  61. jettask/webui/middleware/namespace_middleware.py +135 -0
  62. jettask/webui/services/__init__.py +146 -0
  63. jettask/webui/services/heartbeat_service.py +251 -0
  64. jettask/webui/services/overview_service.py +60 -51
  65. jettask/webui/services/queue_monitor_service.py +426 -0
  66. jettask/webui/services/redis_monitor_service.py +87 -0
  67. jettask/webui/services/settings_service.py +174 -111
  68. jettask/webui/services/task_monitor_service.py +222 -0
  69. jettask/webui/services/timeline_pg_service.py +452 -0
  70. jettask/webui/services/timeline_service.py +189 -0
  71. jettask/webui/services/worker_monitor_service.py +467 -0
  72. jettask/webui/utils/__init__.py +11 -0
  73. jettask/webui/utils/time_utils.py +122 -0
  74. jettask/worker/lifecycle.py +8 -2
  75. {jettask-0.2.23.dist-info → jettask-0.2.24.dist-info}/METADATA +1 -1
  76. jettask-0.2.24.dist-info/RECORD +142 -0
  77. jettask/executor/executor.py +0 -338
  78. jettask/persistence/backlog_monitor.py +0 -567
  79. jettask/persistence/base.py +0 -2334
  80. jettask/persistence/db_manager.py +0 -516
  81. jettask/persistence/maintenance.py +0 -81
  82. jettask/persistence/message_consumer.py +0 -259
  83. jettask/persistence/models.py +0 -49
  84. jettask/persistence/offline_recovery.py +0 -196
  85. jettask/persistence/queue_discovery.py +0 -215
  86. jettask/persistence/task_persistence.py +0 -218
  87. jettask/persistence/task_updater.py +0 -583
  88. jettask/scheduler/add_execution_count.sql +0 -11
  89. jettask/scheduler/add_priority_field.sql +0 -26
  90. jettask/scheduler/add_scheduler_id.sql +0 -25
  91. jettask/scheduler/add_scheduler_id_index.sql +0 -10
  92. jettask/scheduler/make_scheduler_id_required.sql +0 -28
  93. jettask/scheduler/migrate_interval_seconds.sql +0 -9
  94. jettask/scheduler/performance_optimization.sql +0 -45
  95. jettask/scheduler/run_scheduler.py +0 -186
  96. jettask/scheduler/schema.sql +0 -84
  97. jettask/task/task_executor.py +0 -318
  98. jettask/webui/api/analytics.py +0 -323
  99. jettask/webui/config.py +0 -90
  100. jettask/webui/models/__init__.py +0 -3
  101. jettask/webui/models/namespace.py +0 -63
  102. jettask/webui/namespace_manager/__init__.py +0 -10
  103. jettask/webui/namespace_manager/multi.py +0 -593
  104. jettask/webui/namespace_manager/unified.py +0 -193
  105. jettask/webui/run.py +0 -46
  106. jettask-0.2.23.dist-info/RECORD +0 -145
  107. {jettask-0.2.23.dist-info → jettask-0.2.24.dist-info}/WHEEL +0 -0
  108. {jettask-0.2.23.dist-info → jettask-0.2.24.dist-info}/entry_points.txt +0 -0
  109. {jettask-0.2.23.dist-info → jettask-0.2.24.dist-info}/licenses/LICENSE +0 -0
  110. {jettask-0.2.23.dist-info → jettask-0.2.24.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,87 @@
1
+ """
2
+ Redis 监控基础服务
3
+
4
+ 提供 Redis 连接管理和基础功能
5
+ """
6
+ import asyncio
7
+ import logging
8
+ from typing import Optional
9
+ import redis.asyncio as aioredis
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class RedisMonitorService:
15
+ """Redis 监控基础服务类"""
16
+
17
+ def __init__(self, redis_url: str = "redis://localhost:6379", redis_prefix: str = "jettask"):
18
+ """
19
+ 初始化 Redis 监控服务
20
+
21
+ Args:
22
+ redis_url: Redis 连接URL
23
+ redis_prefix: Redis 键前缀
24
+ """
25
+ self.redis_url = redis_url
26
+ self.redis_prefix = redis_prefix
27
+ self.redis: Optional[aioredis.Redis] = None
28
+ self.worker_state_manager = None # 延迟初始化
29
+
30
+ # 缓存配置
31
+ self._queues_cache = None
32
+ self._queues_cache_time = 0
33
+ self._queues_cache_ttl = 60 # 缓存60秒
34
+
35
+ self._workers_cache = None
36
+ self._workers_cache_time = 0
37
+ self._workers_cache_ttl = 5 # worker缓存5秒,因为更新频繁
38
+
39
+ async def connect(self):
40
+ """连接到 Redis"""
41
+ from jettask.db.connector import get_async_redis_pool
42
+
43
+ pool = get_async_redis_pool(
44
+ self.redis_url,
45
+ decode_responses=True,
46
+ max_connections=100,
47
+ socket_connect_timeout=5,
48
+ socket_timeout=10,
49
+ socket_keepalive=True,
50
+ health_check_interval=30
51
+ )
52
+ self.redis = aioredis.Redis(connection_pool=pool)
53
+
54
+ # 初始化 WorkerStateManager
55
+ from jettask.worker.lifecycle import WorkerStateManager
56
+ self.worker_state_manager = WorkerStateManager(
57
+ redis_client=self.redis,
58
+ redis_prefix=self.redis_prefix
59
+ )
60
+ logger.info(f"Redis 监控服务已连接: {self.redis_url}")
61
+
62
+ async def close(self):
63
+ """关闭 Redis 连接"""
64
+ if self.redis:
65
+ await self.redis.close()
66
+ logger.info("Redis 监控服务已关闭")
67
+
68
+ def get_prefixed_queue_name(self, queue_name: str) -> str:
69
+ """
70
+ 为队列名称添加前缀
71
+
72
+ Args:
73
+ queue_name: 原始队列名称
74
+
75
+ Returns:
76
+ 带前缀的队列名称
77
+ """
78
+ return f"{self.redis_prefix}:QUEUE:{queue_name}"
79
+
80
+ async def __aenter__(self):
81
+ """异步上下文管理器入口"""
82
+ await self.connect()
83
+ return self
84
+
85
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
86
+ """异步上下文管理器退出"""
87
+ await self.close()
@@ -9,7 +9,8 @@ from datetime import datetime
9
9
  from sqlalchemy import text
10
10
  from urllib.parse import urlparse
11
11
 
12
- from jettask.persistence.db_manager import get_db_manager
12
+ from jettask.db.connector import get_async_redis_client, get_pg_engine_and_factory
13
+ from jettask.config.task_center import task_center_config
13
14
  from jettask.schemas import (
14
15
  ConfigMode,
15
16
  NamespaceCreate,
@@ -111,8 +112,9 @@ class SettingsService:
111
112
  Returns:
112
113
  命名空间列表
113
114
  """
114
- db_manager = get_db_manager()
115
- async with db_manager.get_master_session() as session:
115
+ # 获取元数据库会话
116
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
117
+ async with session_factory() as session:
116
118
  query = """
117
119
  SELECT id, name, description, redis_config, pg_config,
118
120
  is_active, version, created_at, updated_at
@@ -137,36 +139,45 @@ class SettingsService:
137
139
  # 构建响应
138
140
  redis_config_dict = row.redis_config if row.redis_config else {}
139
141
  pg_config_dict = row.pg_config if row.pg_config else {}
140
-
141
- # 根据配置模式获取实际的URL
142
- config_mode = redis_config_dict.get('config_mode', 'direct')
143
-
144
- # 获取Redis URL
145
- if config_mode == 'nacos' and redis_config_dict.get('nacos_key'):
146
- try:
147
- redis_url = await SettingsService.get_config_from_nacos(redis_config_dict['nacos_key'])
148
- except Exception as e:
149
- logger.error(f"从Nacos获取Redis URL失败: {e} {row.name}")
150
- redis_url = redis_config_dict.get('url', '')
142
+
143
+ # 获取配置模式
144
+ redis_config_mode = redis_config_dict.get('config_mode', 'direct')
145
+ pg_config_mode = pg_config_dict.get('config_mode', 'direct')
146
+
147
+ # Redis 配置处理 - 根据模式返回不同内容
148
+ if redis_config_mode == 'nacos':
149
+ # Nacos 模式 - 只返回 nacos_key,不返回真实 URL(保密)
150
+ redis_url = None
151
+ redis_nacos_key = redis_config_dict.get('nacos_key')
152
+ logger.debug(f"命名空间 {row.name} 使用 Nacos 模式,返回 Redis key: {redis_nacos_key}")
151
153
  else:
154
+ # Direct 模式 - 返回真实完整的 URL(客户端需要使用)
152
155
  redis_url = redis_config_dict.get('url', '')
153
-
154
- # 获取PostgreSQL URL
155
- pg_url = None
156
- if config_mode == 'nacos' and pg_config_dict.get('nacos_key'):
157
- try:
158
- pg_url = await SettingsService.get_config_from_nacos(pg_config_dict['nacos_key'])
159
- except Exception as e:
160
- logger.error(f"从Nacos获取PostgreSQL URL失败: {e} {row.name}")
161
- pg_url = pg_config_dict.get('url')
156
+ redis_nacos_key = None
157
+ logger.debug(f"命名空间 {row.name} 使用 Direct 模式,返回真实 Redis URL")
158
+
159
+ # PostgreSQL 配置处理 - 根据模式返回不同内容
160
+ if pg_config_mode == 'nacos':
161
+ # Nacos 模式 - 只返回 nacos_key,不返回真实 URL(保密)
162
+ pg_url = None
163
+ pg_nacos_key = pg_config_dict.get('nacos_key')
164
+ logger.debug(f"命名空间 {row.name} 使用 Nacos 模式,返回 PG key: {pg_nacos_key}")
162
165
  else:
166
+ # Direct 模式 - 返回真实完整的 URL(客户端需要使用)
163
167
  pg_url = pg_config_dict.get('url')
164
-
168
+ pg_nacos_key = None
169
+ if pg_url:
170
+ logger.debug(f"命名空间 {row.name} 使用 Direct 模式,返回真实 PG URL")
171
+
165
172
  response = NamespaceResponse(
166
173
  name=row.name,
167
174
  description=row.description,
168
175
  redis_url=redis_url,
176
+ redis_config_mode=redis_config_mode,
177
+ redis_nacos_key=redis_nacos_key,
169
178
  pg_url=pg_url,
179
+ pg_config_mode=pg_config_mode,
180
+ pg_nacos_key=pg_nacos_key,
170
181
  connection_url=f"/api/v1/namespaces/{row.name}",
171
182
  version=row.version or 1,
172
183
  enabled=row.is_active,
@@ -188,8 +199,9 @@ class SettingsService:
188
199
  Returns:
189
200
  创建的命名空间信息
190
201
  """
191
- db_manager = get_db_manager()
192
- async with db_manager.get_master_session() as session:
202
+ # 获取元数据库会话
203
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
204
+ async with session_factory() as session:
193
205
  # 检查命名空间是否已存在
194
206
  check_query = text("SELECT COUNT(*) FROM namespaces WHERE name = :name")
195
207
  result = await session.execute(check_query, {'name': namespace.name})
@@ -264,19 +276,44 @@ class SettingsService:
264
276
 
265
277
  row = result.fetchone()
266
278
  await session.commit()
267
-
268
- # 构建响应 - 只返回最终的URL,不返回配置细节
269
- response = NamespaceResponse(
270
- name=row.name,
271
- description=row.description,
272
- redis_url=redis_config['url'], # 这里已经是最终的URL
273
- pg_url=pg_config.get('url', '') if pg_config.get('url') else None,
274
- connection_url=f"/api/v1/namespaces/{row.name}",
275
- version=row.version or 1,
276
- enabled=row.is_active,
277
- created_at=row.created_at,
278
- updated_at=row.updated_at
279
- )
279
+
280
+ # 构建响应 - 根据配置模式返回不同内容
281
+ config_mode_str = namespace.config_mode.value
282
+
283
+ if namespace.config_mode == ConfigMode.NACOS:
284
+ # Nacos 模式 - 只返回 nacos_key,不返回真实 URL(保密)
285
+ response = NamespaceResponse(
286
+ name=row.name,
287
+ description=row.description,
288
+ redis_url=None,
289
+ redis_config_mode=config_mode_str,
290
+ redis_nacos_key=redis_config.get('nacos_key'),
291
+ pg_url=None,
292
+ pg_config_mode=config_mode_str,
293
+ pg_nacos_key=pg_config.get('nacos_key'),
294
+ connection_url=f"/api/v1/namespaces/{row.name}",
295
+ version=row.version or 1,
296
+ enabled=row.is_active,
297
+ created_at=row.created_at,
298
+ updated_at=row.updated_at
299
+ )
300
+ else:
301
+ # Direct 模式 - 返回真实完整的 URL(客户端需要使用)
302
+ response = NamespaceResponse(
303
+ name=row.name,
304
+ description=row.description,
305
+ redis_url=redis_config.get('url'),
306
+ redis_config_mode=config_mode_str,
307
+ redis_nacos_key=None,
308
+ pg_url=pg_config.get('url'),
309
+ pg_config_mode=config_mode_str,
310
+ pg_nacos_key=None,
311
+ connection_url=f"/api/v1/namespaces/{row.name}",
312
+ version=row.version or 1,
313
+ enabled=row.is_active,
314
+ created_at=row.created_at,
315
+ updated_at=row.updated_at
316
+ )
280
317
 
281
318
  logger.info(f"成功创建命名空间: {namespace.name}")
282
319
  return response
@@ -292,10 +329,11 @@ class SettingsService:
292
329
  Returns:
293
330
  命名空间信息
294
331
  """
295
- db_manager = get_db_manager()
296
- async with db_manager.get_master_session() as session:
332
+ # 获取元数据库会话
333
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
334
+ async with session_factory() as session:
297
335
  query = text("""
298
- SELECT id, name, description, redis_config, pg_config,
336
+ SELECT id, name, description, redis_config, pg_config,
299
337
  is_active, version, created_at, updated_at
300
338
  FROM namespaces
301
339
  WHERE name = :name
@@ -306,40 +344,49 @@ class SettingsService:
306
344
 
307
345
  if not row:
308
346
  raise ValueError(f"命名空间 '{namespace_name}' 不存在")
309
-
347
+
310
348
  # 构建响应
311
349
  redis_config_dict = row.redis_config if row.redis_config else {}
312
350
  pg_config_dict = row.pg_config if row.pg_config else {}
313
-
314
- # 根据配置模式获取实际的URL
315
- config_mode = redis_config_dict.get('config_mode', 'direct')
316
-
317
- # 获取Redis URL
318
- if config_mode == 'nacos' and redis_config_dict.get('nacos_key'):
319
- try:
320
- redis_url = await SettingsService.get_config_from_nacos(redis_config_dict['nacos_key'])
321
- except Exception as e:
322
- logger.error(f"从Nacos获取Redis URL失败: {e}")
323
- redis_url = redis_config_dict.get('url', '')
351
+
352
+ # 获取配置模式
353
+ redis_config_mode = redis_config_dict.get('config_mode', 'direct')
354
+ pg_config_mode = pg_config_dict.get('config_mode', 'direct')
355
+
356
+ # Redis 配置处理 - 根据模式返回不同内容
357
+ if redis_config_mode == 'nacos':
358
+ # Nacos 模式 - 只返回 nacos_key,不返回真实 URL(保密)
359
+ redis_url = None
360
+ redis_nacos_key = redis_config_dict.get('nacos_key')
361
+ logger.debug(f"命名空间 {namespace_name} 使用 Nacos 模式,返回 Redis key: {redis_nacos_key}")
324
362
  else:
363
+ # Direct 模式 - 返回真实完整的 URL(客户端需要使用)
325
364
  redis_url = redis_config_dict.get('url', '')
326
-
327
- # 获取PostgreSQL URL
328
- pg_url = None
329
- if config_mode == 'nacos' and pg_config_dict.get('nacos_key'):
330
- try:
331
- pg_url = await SettingsService.get_config_from_nacos(pg_config_dict['nacos_key'])
332
- except Exception as e:
333
- logger.error(f"从Nacos获取PostgreSQL URL失败: {e}")
334
- pg_url = pg_config_dict.get('url')
365
+ redis_nacos_key = None
366
+ logger.debug(f"命名空间 {namespace_name} 使用 Direct 模式,返回真实 Redis URL")
367
+
368
+ # PostgreSQL 配置处理 - 根据模式返回不同内容
369
+ if pg_config_mode == 'nacos':
370
+ # Nacos 模式 - 只返回 nacos_key,不返回真实 URL(保密)
371
+ pg_url = None
372
+ pg_nacos_key = pg_config_dict.get('nacos_key')
373
+ logger.debug(f"命名空间 {namespace_name} 使用 Nacos 模式,返回 PG key: {pg_nacos_key}")
335
374
  else:
375
+ # Direct 模式 - 返回真实完整的 URL(客户端需要使用)
336
376
  pg_url = pg_config_dict.get('url')
337
-
377
+ pg_nacos_key = None
378
+ if pg_url:
379
+ logger.debug(f"命名空间 {namespace_name} 使用 Direct 模式,返回真实 PG URL")
380
+
338
381
  response = NamespaceResponse(
339
382
  name=row.name,
340
383
  description=row.description,
341
384
  redis_url=redis_url,
385
+ redis_config_mode=redis_config_mode,
386
+ redis_nacos_key=redis_nacos_key,
342
387
  pg_url=pg_url,
388
+ pg_config_mode=pg_config_mode,
389
+ pg_nacos_key=pg_nacos_key,
343
390
  connection_url=f"/api/v1/namespaces/{row.name}",
344
391
  version=row.version or 1,
345
392
  enabled=row.is_active,
@@ -361,8 +408,9 @@ class SettingsService:
361
408
  Returns:
362
409
  更新后的命名空间信息
363
410
  """
364
- db_manager = get_db_manager()
365
- async with db_manager.get_master_session() as session:
411
+ # 获取元数据库会话
412
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
413
+ async with session_factory() as session:
366
414
  # 检查命名空间是否存在
367
415
  check_query = text("""
368
416
  SELECT id, redis_config, pg_config FROM namespaces WHERE name = :name
@@ -510,40 +558,49 @@ class SettingsService:
510
558
  result = await session.execute(update_query, params)
511
559
  updated_row = result.fetchone()
512
560
  await session.commit()
513
-
561
+
514
562
  # 构建响应
515
- redis_config_dict = updated_row.redis_config
563
+ redis_config_dict = updated_row.redis_config if updated_row.redis_config else {}
516
564
  pg_config_dict = updated_row.pg_config if updated_row.pg_config else {}
517
-
518
- # 根据配置模式获取实际的URL
519
- config_mode = redis_config_dict.get('config_mode', 'direct')
520
-
521
- # 获取Redis URL
522
- if config_mode == 'nacos' and redis_config_dict.get('nacos_key'):
523
- try:
524
- redis_url = await SettingsService.get_config_from_nacos(redis_config_dict['nacos_key'])
525
- except Exception as e:
526
- logger.error(f"从Nacos获取Redis URL失败: {e}")
527
- redis_url = redis_config_dict.get('url', '')
565
+
566
+ # 获取配置模式
567
+ redis_config_mode = redis_config_dict.get('config_mode', 'direct')
568
+ pg_config_mode = pg_config_dict.get('config_mode', 'direct')
569
+
570
+ # Redis 配置处理 - 根据模式返回不同内容
571
+ if redis_config_mode == 'nacos':
572
+ # Nacos 模式 - 只返回 nacos_key,不返回真实 URL(保密)
573
+ redis_url = None
574
+ redis_nacos_key = redis_config_dict.get('nacos_key')
575
+ logger.debug(f"更新后命名空间 {namespace_name} 使用 Nacos 模式,返回 Redis key: {redis_nacos_key}")
528
576
  else:
577
+ # Direct 模式 - 返回真实完整的 URL(客户端需要使用)
529
578
  redis_url = redis_config_dict.get('url', '')
530
-
531
- # 获取PostgreSQL URL
532
- pg_url = None
533
- if config_mode == 'nacos' and pg_config_dict.get('nacos_key'):
534
- try:
535
- pg_url = await SettingsService.get_config_from_nacos(pg_config_dict['nacos_key'])
536
- except Exception as e:
537
- logger.error(f"从Nacos获取PostgreSQL URL失败: {e}")
538
- pg_url = pg_config_dict.get('url')
579
+ redis_nacos_key = None
580
+ logger.debug(f"更新后命名空间 {namespace_name} 使用 Direct 模式,返回真实 Redis URL")
581
+
582
+ # PostgreSQL 配置处理 - 根据模式返回不同内容
583
+ if pg_config_mode == 'nacos':
584
+ # Nacos 模式 - 只返回 nacos_key,不返回真实 URL(保密)
585
+ pg_url = None
586
+ pg_nacos_key = pg_config_dict.get('nacos_key')
587
+ logger.debug(f"更新后命名空间 {namespace_name} 使用 Nacos 模式,返回 PG key: {pg_nacos_key}")
539
588
  else:
589
+ # Direct 模式 - 返回真实完整的 URL(客户端需要使用)
540
590
  pg_url = pg_config_dict.get('url')
541
-
591
+ pg_nacos_key = None
592
+ if pg_url:
593
+ logger.debug(f"更新后命名空间 {namespace_name} 使用 Direct 模式,返回真实 PG URL")
594
+
542
595
  response = NamespaceResponse(
543
596
  name=updated_row.name,
544
597
  description=updated_row.description,
545
598
  redis_url=redis_url,
599
+ redis_config_mode=redis_config_mode,
600
+ redis_nacos_key=redis_nacos_key,
546
601
  pg_url=pg_url,
602
+ pg_config_mode=pg_config_mode,
603
+ pg_nacos_key=pg_nacos_key,
547
604
  connection_url=f"/api/v1/namespaces/{updated_row.name}",
548
605
  version=updated_row.version or 1,
549
606
  enabled=updated_row.is_active,
@@ -567,9 +624,10 @@ class SettingsService:
567
624
  """
568
625
  if namespace_name == 'default':
569
626
  raise ValueError("不能删除默认命名空间")
570
-
571
- db_manager = get_db_manager()
572
- async with db_manager.get_master_session() as session:
627
+
628
+ # 获取元数据库会话
629
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
630
+ async with session_factory() as session:
573
631
  # 检查命名空间是否存在
574
632
  check_query = text("SELECT id FROM namespaces WHERE name = :name")
575
633
  result = await session.execute(check_query, {'name': namespace_name})
@@ -596,11 +654,12 @@ class SettingsService:
596
654
  Returns:
597
655
  激活结果
598
656
  """
599
- db_manager = get_db_manager()
600
- async with db_manager.get_master_session() as session:
657
+ # 获取元数据库会话
658
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
659
+ async with session_factory() as session:
601
660
  # 检查并激活命名空间
602
661
  update_query = text("""
603
- UPDATE namespaces
662
+ UPDATE namespaces
604
663
  SET is_active = true, updated_at = CURRENT_TIMESTAMP
605
664
  WHERE name = :name
606
665
  """)
@@ -628,12 +687,13 @@ class SettingsService:
628
687
  """
629
688
  if namespace_name == 'default':
630
689
  raise ValueError("不能停用默认命名空间")
631
-
632
- db_manager = get_db_manager()
633
- async with db_manager.get_master_session() as session:
690
+
691
+ # 获取元数据库会话
692
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
693
+ async with session_factory() as session:
634
694
  # 检查并停用命名空间
635
695
  update_query = text("""
636
- UPDATE namespaces
696
+ UPDATE namespaces
637
697
  SET is_active = false, updated_at = CURRENT_TIMESTAMP
638
698
  WHERE name = :name
639
699
  """)
@@ -652,18 +712,18 @@ class SettingsService:
652
712
  async def get_namespace_statistics(namespace_name: str) -> Dict[str, Any]:
653
713
  """
654
714
  获取命名空间统计信息
655
-
715
+
656
716
  Args:
657
717
  namespace_name: 命名空间名称
658
-
718
+
659
719
  Returns:
660
- 统计信息
720
+ 统计信息(符合 NamespaceStatisticsResponse 格式)
661
721
  """
662
722
  # 这里可以根据实际需求实现统计逻辑
663
723
  # 暂时返回模拟数据
664
724
  return {
665
- "namespace": namespace_name,
666
- "statistics": {
725
+ "success": True,
726
+ "data": {
667
727
  "total_queues": 0,
668
728
  "total_tasks": 0,
669
729
  "active_workers": 0,
@@ -672,6 +732,7 @@ class SettingsService:
672
732
  "completed_tasks": 0,
673
733
  "failed_tasks": 0
674
734
  },
735
+ "namespace": namespace_name,
675
736
  "timestamp": datetime.now().isoformat()
676
737
  }
677
738
 
@@ -686,11 +747,12 @@ class SettingsService:
686
747
  Returns:
687
748
  激活结果
688
749
  """
689
- db_manager = get_db_manager()
690
- async with db_manager.get_master_session() as session:
750
+ # 获取元数据库会话
751
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
752
+ async with session_factory() as session:
691
753
  # 批量激活
692
754
  update_query = text("""
693
- UPDATE namespaces
755
+ UPDATE namespaces
694
756
  SET is_active = true, updated_at = CURRENT_TIMESTAMP
695
757
  WHERE name = ANY(:names)
696
758
  """)
@@ -726,12 +788,13 @@ class SettingsService:
726
788
  "namespaces": [],
727
789
  "skipped": ["default"]
728
790
  }
729
-
730
- db_manager = get_db_manager()
731
- async with db_manager.get_master_session() as session:
791
+
792
+ # 获取元数据库会话
793
+ _, session_factory = get_pg_engine_and_factory(task_center_config.meta_database_url)
794
+ async with session_factory() as session:
732
795
  # 批量停用
733
796
  update_query = text("""
734
- UPDATE namespaces
797
+ UPDATE namespaces
735
798
  SET is_active = false, updated_at = CURRENT_TIMESTAMP
736
799
  WHERE name = ANY(:names)
737
800
  """)