quantum-framework 0.9.0__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.
- quantum/__init__.py +1 -0
- quantum/cli/__init__.py +2 -0
- quantum/cli/commands/__init__.py +15 -0
- quantum/cli/commands/build.py +417 -0
- quantum/cli/commands/dev.py +185 -0
- quantum/cli/commands/docs.py +329 -0
- quantum/cli/commands/lint.py +523 -0
- quantum/cli/commands/migrate.py +527 -0
- quantum/cli/commands/new.py +622 -0
- quantum/cli/commands/serve.py +190 -0
- quantum/cli/commands/test.py +193 -0
- quantum/cli/deploy.py +810 -0
- quantum/cli/hot_reload.py +951 -0
- quantum/cli/jobs.py +356 -0
- quantum/cli/mq.py +582 -0
- quantum/cli/pkg.py +390 -0
- quantum/cli/runner.py +547 -0
- quantum/cli/server_process.py +159 -0
- quantum/cli/utils.py +334 -0
- quantum/compiler/__init__.py +30 -0
- quantum/compiler/base_generator.py +367 -0
- quantum/compiler/cli.py +295 -0
- quantum/compiler/expression_transformer.py +444 -0
- quantum/compiler/javascript/__init__.py +10 -0
- quantum/compiler/javascript/generator.py +659 -0
- quantum/compiler/optimizer.py +270 -0
- quantum/compiler/python/__init__.py +10 -0
- quantum/compiler/python/generator.py +883 -0
- quantum/compiler/python/runtime.py +863 -0
- quantum/compiler/transpiler.py +330 -0
- quantum/core/__init__.py +3 -0
- quantum/core/ast_nodes.py +2611 -0
- quantum/core/expression_diagnostics.py +87 -0
- quantum/core/expression_stdlib.py +148 -0
- quantum/core/expressions.py +591 -0
- quantum/core/features/agents/src/__init__.py +30 -0
- quantum/core/features/agents/src/ast_node.py +540 -0
- quantum/core/features/conditionals/src/__init__.py +8 -0
- quantum/core/features/conditionals/src/ast_node.py +68 -0
- quantum/core/features/data_fetching/src/__init__.py +21 -0
- quantum/core/features/data_fetching/src/ast_node.py +312 -0
- quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
- quantum/core/features/data_fetching/src/html_adapter.py +474 -0
- quantum/core/features/data_fetching/src/parser.py +225 -0
- quantum/core/features/data_import/src/__init__.py +0 -0
- quantum/core/features/data_import/src/ast_node.py +291 -0
- quantum/core/features/data_import/src/runtime.py +538 -0
- quantum/core/features/dump/src/__init__.py +12 -0
- quantum/core/features/dump/src/ast_node.py +106 -0
- quantum/core/features/dump/src/parser.py +61 -0
- quantum/core/features/dump/src/runtime.py +246 -0
- quantum/core/features/functions/src/__init__.py +8 -0
- quantum/core/features/functions/src/ast_node.py +149 -0
- quantum/core/features/game_engine_2d/src/__init__.py +19 -0
- quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
- quantum/core/features/game_engine_2d/src/parser.py +983 -0
- quantum/core/features/invocation/src/__init__.py +0 -0
- quantum/core/features/invocation/src/ast_node.py +146 -0
- quantum/core/features/invocation/src/runtime.py +327 -0
- quantum/core/features/knowledge_base/src/__init__.py +6 -0
- quantum/core/features/knowledge_base/src/ast_node.py +113 -0
- quantum/core/features/knowledge_base/src/parser.py +82 -0
- quantum/core/features/logging/src/__init__.py +12 -0
- quantum/core/features/logging/src/ast_node.py +111 -0
- quantum/core/features/logging/src/parser.py +50 -0
- quantum/core/features/logging/src/runtime.py +190 -0
- quantum/core/features/loops/src/__init__.py +8 -0
- quantum/core/features/loops/src/ast_node.py +60 -0
- quantum/core/features/query/src/__init__.py +0 -0
- quantum/core/features/query/src/database_service.py +322 -0
- quantum/core/features/query/src/query_validators.py +20 -0
- quantum/core/features/state_management/src/__init__.py +11 -0
- quantum/core/features/state_management/src/ast_node.py +228 -0
- quantum/core/features/terminal_engine/src/__init__.py +21 -0
- quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
- quantum/core/features/terminal_engine/src/parser.py +361 -0
- quantum/core/features/testing_engine/src/__init__.py +41 -0
- quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
- quantum/core/features/testing_engine/src/parser.py +604 -0
- quantum/core/features/theming/src/__init__.py +48 -0
- quantum/core/features/theming/src/ast_node.py +137 -0
- quantum/core/features/theming/src/presets.py +405 -0
- quantum/core/features/ui_engine/src/__init__.py +20 -0
- quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
- quantum/core/features/ui_engine/src/parser.py +1106 -0
- quantum/core/features/websocket/src/__init__.py +24 -0
- quantum/core/features/websocket/src/ast_node.py +247 -0
- quantum/core/html_compat.py +299 -0
- quantum/core/parser.py +1235 -0
- quantum/core/parser_registry.py +213 -0
- quantum/core/parsers/__init__.py +76 -0
- quantum/core/parsers/ai/__init__.py +12 -0
- quantum/core/parsers/ai/agent_parser.py +106 -0
- quantum/core/parsers/ai/knowledge_parser.py +86 -0
- quantum/core/parsers/ai/llm_parser.py +78 -0
- quantum/core/parsers/ai/team_parser.py +88 -0
- quantum/core/parsers/base.py +322 -0
- quantum/core/parsers/composition/__init__.py +10 -0
- quantum/core/parsers/composition/import_parser.py +50 -0
- quantum/core/parsers/composition/slot_parser.py +48 -0
- quantum/core/parsers/control_flow/__init__.py +11 -0
- quantum/core/parsers/control_flow/if_parser.py +68 -0
- quantum/core/parsers/control_flow/loop_parser.py +105 -0
- quantum/core/parsers/control_flow/set_parser.py +89 -0
- quantum/core/parsers/data/__init__.py +12 -0
- quantum/core/parsers/data/data_parser.py +217 -0
- quantum/core/parsers/data/invoke_parser.py +116 -0
- quantum/core/parsers/data/query_parser.py +188 -0
- quantum/core/parsers/data/transaction_parser.py +77 -0
- quantum/core/parsers/events/__init__.py +9 -0
- quantum/core/parsers/events/dispatch_event_parser.py +44 -0
- quantum/core/parsers/forms/__init__.py +11 -0
- quantum/core/parsers/forms/action_parser.py +54 -0
- quantum/core/parsers/forms/flash_parser.py +34 -0
- quantum/core/parsers/forms/redirect_parser.py +33 -0
- quantum/core/parsers/functions/__init__.py +11 -0
- quantum/core/parsers/functions/function_parser.py +137 -0
- quantum/core/parsers/functions/param_parser.py +66 -0
- quantum/core/parsers/functions/return_parser.py +31 -0
- quantum/core/parsers/html/__init__.py +10 -0
- quantum/core/parsers/html/component_call_parser.py +130 -0
- quantum/core/parsers/html/html_parser.py +115 -0
- quantum/core/parsers/jobs/__init__.py +11 -0
- quantum/core/parsers/jobs/job_parser.py +71 -0
- quantum/core/parsers/jobs/schedule_parser.py +62 -0
- quantum/core/parsers/jobs/thread_parser.py +57 -0
- quantum/core/parsers/messaging/__init__.py +17 -0
- quantum/core/parsers/messaging/message_ack_parser.py +30 -0
- quantum/core/parsers/messaging/message_nack_parser.py +30 -0
- quantum/core/parsers/messaging/message_parser.py +114 -0
- quantum/core/parsers/messaging/queue_parser.py +61 -0
- quantum/core/parsers/messaging/websocket_parser.py +121 -0
- quantum/core/parsers/persistence/__init__.py +9 -0
- quantum/core/parsers/persistence/persist_parser.py +64 -0
- quantum/core/parsers/routing/__init__.py +9 -0
- quantum/core/parsers/routing/route_parser.py +41 -0
- quantum/core/parsers/scripting/__init__.py +12 -0
- quantum/core/parsers/scripting/pyclass_parser.py +62 -0
- quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
- quantum/core/parsers/scripting/pyimport_parser.py +52 -0
- quantum/core/parsers/scripting/python_parser.py +49 -0
- quantum/core/parsers/services/__init__.py +12 -0
- quantum/core/parsers/services/dump_parser.py +52 -0
- quantum/core/parsers/services/file_parser.py +48 -0
- quantum/core/parsers/services/log_parser.py +46 -0
- quantum/core/parsers/services/mail_parser.py +65 -0
- quantum/core/tiers.py +82 -0
- quantum/packages/__init__.py +28 -0
- quantum/packages/manager.py +413 -0
- quantum/packages/manifest.py +351 -0
- quantum/packages/registry.py +399 -0
- quantum/packages/resolver.py +336 -0
- quantum/plugins/__init__.py +33 -0
- quantum/plugins/hooks.py +329 -0
- quantum/plugins/loader.py +479 -0
- quantum/plugins/manifest.py +336 -0
- quantum/plugins/registry.py +371 -0
- quantum/runtime/__init__.py +28 -0
- quantum/runtime/action_handler.py +443 -0
- quantum/runtime/adapters/__init__.py +88 -0
- quantum/runtime/adapters/memory_adapter.py +690 -0
- quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
- quantum/runtime/adapters/redis_adapter.py +582 -0
- quantum/runtime/adapters/sqlite_adapter.py +414 -0
- quantum/runtime/agent_service.py +1133 -0
- quantum/runtime/api_server.py +86 -0
- quantum/runtime/ast_cache.py +506 -0
- quantum/runtime/auth_service.py +267 -0
- quantum/runtime/component.py +990 -0
- quantum/runtime/component_composer.py +319 -0
- quantum/runtime/component_resolver.py +174 -0
- quantum/runtime/database_service.py +598 -0
- quantum/runtime/email_service.py +162 -0
- quantum/runtime/error_handler.py +295 -0
- quantum/runtime/execution_context.py +286 -0
- quantum/runtime/executor_registry.py +171 -0
- quantum/runtime/executors/__init__.py +71 -0
- quantum/runtime/executors/ai/__init__.py +12 -0
- quantum/runtime/executors/ai/agent_executor.py +217 -0
- quantum/runtime/executors/ai/knowledge_executor.py +114 -0
- quantum/runtime/executors/ai/llm_executor.py +153 -0
- quantum/runtime/executors/ai/team_executor.py +171 -0
- quantum/runtime/executors/base.py +262 -0
- quantum/runtime/executors/control_flow/__init__.py +11 -0
- quantum/runtime/executors/control_flow/if_executor.py +93 -0
- quantum/runtime/executors/control_flow/loop_executor.py +307 -0
- quantum/runtime/executors/control_flow/set_executor.py +412 -0
- quantum/runtime/executors/data/__init__.py +12 -0
- quantum/runtime/executors/data/data_executor.py +145 -0
- quantum/runtime/executors/data/invoke_executor.py +176 -0
- quantum/runtime/executors/data/query_executor.py +256 -0
- quantum/runtime/executors/data/transaction_executor.py +91 -0
- quantum/runtime/executors/jobs/__init__.py +11 -0
- quantum/runtime/executors/jobs/job_executor.py +190 -0
- quantum/runtime/executors/jobs/schedule_executor.py +132 -0
- quantum/runtime/executors/jobs/thread_executor.py +127 -0
- quantum/runtime/executors/messaging/__init__.py +17 -0
- quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
- quantum/runtime/executors/messaging/message_executor.py +174 -0
- quantum/runtime/executors/messaging/queue_executor.py +103 -0
- quantum/runtime/executors/messaging/websocket_executor.py +197 -0
- quantum/runtime/executors/scripting/__init__.py +11 -0
- quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
- quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
- quantum/runtime/executors/scripting/python_executor.py +249 -0
- quantum/runtime/executors/services/__init__.py +12 -0
- quantum/runtime/executors/services/dump_executor.py +72 -0
- quantum/runtime/executors/services/file_executor.py +89 -0
- quantum/runtime/executors/services/log_executor.py +77 -0
- quantum/runtime/executors/services/mail_executor.py +81 -0
- quantum/runtime/expression_cache.py +498 -0
- quantum/runtime/file_upload_service.py +326 -0
- quantum/runtime/function_registry.py +118 -0
- quantum/runtime/game_builder.py +166 -0
- quantum/runtime/game_code_generator.py +2371 -0
- quantum/runtime/game_templates.py +2006 -0
- quantum/runtime/godot_code_generator.py +4681 -0
- quantum/runtime/godot_templates.py +1449 -0
- quantum/runtime/job_executor.py +1599 -0
- quantum/runtime/knowledge_service.py +500 -0
- quantum/runtime/llm_cache.py +100 -0
- quantum/runtime/llm_providers.py +704 -0
- quantum/runtime/llm_service.py +287 -0
- quantum/runtime/logging_setup.py +140 -0
- quantum/runtime/message_broker.py +364 -0
- quantum/runtime/message_queue_service.py +571 -0
- quantum/runtime/param_validation.py +184 -0
- quantum/runtime/pypy_compat.py +315 -0
- quantum/runtime/python_bridge.py +698 -0
- quantum/runtime/query_validators.py +304 -0
- quantum/runtime/renderer.py +733 -0
- quantum/runtime/service_container.py +444 -0
- quantum/runtime/terminal_builder.py +76 -0
- quantum/runtime/terminal_code_generator.py +607 -0
- quantum/runtime/terminal_templates.py +243 -0
- quantum/runtime/testing_builder.py +77 -0
- quantum/runtime/testing_code_generator.py +833 -0
- quantum/runtime/testing_templates.py +85 -0
- quantum/runtime/ui_builder.py +188 -0
- quantum/runtime/ui_desktop_adapter.py +1730 -0
- quantum/runtime/ui_desktop_templates.py +307 -0
- quantum/runtime/ui_html_adapter.py +2691 -0
- quantum/runtime/ui_html_templates.py +2297 -0
- quantum/runtime/ui_mobile_adapter.py +1832 -0
- quantum/runtime/ui_mobile_templates.py +1003 -0
- quantum/runtime/ui_textual_adapter.py +1866 -0
- quantum/runtime/ui_textual_templates.py +45 -0
- quantum/runtime/ui_tokens.py +465 -0
- quantum/runtime/ui_validator.py +365 -0
- quantum/runtime/validators.py +256 -0
- quantum/runtime/web_server.py +1766 -0
- quantum/runtime/websocket_adapter.py +501 -0
- quantum/runtime/websocket_service.py +585 -0
- quantum/runtime/websocket_transport.py +289 -0
- quantum/runtime/wsgi.py +101 -0
- quantum/utils/__init__.py +1 -0
- quantum_framework-0.9.0.dist-info/METADATA +244 -0
- quantum_framework-0.9.0.dist-info/RECORD +262 -0
- quantum_framework-0.9.0.dist-info/WHEEL +5 -0
- quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
- quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
- quantum_framework-0.9.0.dist-info/top_level.txt +1 -0
quantum/cli/jobs.py
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Quantum CLI - Job Management Commands
|
|
5
|
+
|
|
6
|
+
Commands for managing scheduled jobs, threads, and job queues.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import sys
|
|
11
|
+
import json
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
# Add parent to path for imports
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def create_jobs_parser(subparsers):
|
|
20
|
+
"""Add jobs subcommand to CLI parser"""
|
|
21
|
+
jobs_parser = subparsers.add_parser(
|
|
22
|
+
'jobs',
|
|
23
|
+
help='Manage scheduled jobs and job queues',
|
|
24
|
+
description='Commands for managing scheduled jobs, threads, and job queues'
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
jobs_sub = jobs_parser.add_subparsers(dest='jobs_action', help='Job action')
|
|
28
|
+
|
|
29
|
+
# List jobs
|
|
30
|
+
list_parser = jobs_sub.add_parser('list', help='List all scheduled jobs')
|
|
31
|
+
list_parser.add_argument('--status', choices=['all', 'active', 'paused', 'pending', 'running', 'failed'],
|
|
32
|
+
default='all', help='Filter by status')
|
|
33
|
+
list_parser.add_argument('--queue', help='Filter by queue name')
|
|
34
|
+
list_parser.add_argument('--format', choices=['table', 'json'], default='table', help='Output format')
|
|
35
|
+
|
|
36
|
+
# Job status
|
|
37
|
+
status_parser = jobs_sub.add_parser('status', help='Get detailed job status')
|
|
38
|
+
status_parser.add_argument('name', help='Job name')
|
|
39
|
+
status_parser.add_argument('--format', choices=['table', 'json'], default='table', help='Output format')
|
|
40
|
+
|
|
41
|
+
# Run job manually
|
|
42
|
+
run_parser = jobs_sub.add_parser('run', help='Run a job manually')
|
|
43
|
+
run_parser.add_argument('name', help='Job name')
|
|
44
|
+
run_parser.add_argument('--sync', action='store_true', help='Wait for job to complete')
|
|
45
|
+
run_parser.add_argument('--params', help='JSON parameters for the job')
|
|
46
|
+
|
|
47
|
+
# Pause job
|
|
48
|
+
pause_parser = jobs_sub.add_parser('pause', help='Pause a scheduled job')
|
|
49
|
+
pause_parser.add_argument('name', help='Job name')
|
|
50
|
+
|
|
51
|
+
# Resume job
|
|
52
|
+
resume_parser = jobs_sub.add_parser('resume', help='Resume a paused job')
|
|
53
|
+
resume_parser.add_argument('name', help='Job name')
|
|
54
|
+
|
|
55
|
+
# Cancel job
|
|
56
|
+
cancel_parser = jobs_sub.add_parser('cancel', help='Cancel a running or pending job')
|
|
57
|
+
cancel_parser.add_argument('name', help='Job name or job ID')
|
|
58
|
+
|
|
59
|
+
# Job history
|
|
60
|
+
history_parser = jobs_sub.add_parser('history', help='View job execution history')
|
|
61
|
+
history_parser.add_argument('name', nargs='?', help='Job name (optional, shows all if not specified)')
|
|
62
|
+
history_parser.add_argument('--limit', type=int, default=10, help='Number of entries to show')
|
|
63
|
+
history_parser.add_argument('--status', choices=['all', 'success', 'failed'], default='all')
|
|
64
|
+
history_parser.add_argument('--format', choices=['table', 'json'], default='table', help='Output format')
|
|
65
|
+
|
|
66
|
+
# Worker
|
|
67
|
+
worker_parser = jobs_sub.add_parser('worker', help='Start a job worker process')
|
|
68
|
+
worker_sub = worker_parser.add_subparsers(dest='worker_action', help='Worker action')
|
|
69
|
+
|
|
70
|
+
start_worker = worker_sub.add_parser('start', help='Start worker')
|
|
71
|
+
start_worker.add_argument('--queue', default='default', help='Queue(s) to process (comma-separated)')
|
|
72
|
+
start_worker.add_argument('--concurrency', type=int, default=4, help='Number of concurrent workers')
|
|
73
|
+
start_worker.add_argument('--poll-interval', type=float, default=1.0, help='Poll interval in seconds')
|
|
74
|
+
|
|
75
|
+
stop_worker = worker_sub.add_parser('stop', help='Stop worker')
|
|
76
|
+
stop_worker.add_argument('--graceful', action='store_true', help='Wait for running jobs to complete')
|
|
77
|
+
|
|
78
|
+
# Queues management
|
|
79
|
+
queues_parser = jobs_sub.add_parser('queues', help='Manage job queues')
|
|
80
|
+
queues_sub = queues_parser.add_subparsers(dest='queues_action', help='Queue action')
|
|
81
|
+
|
|
82
|
+
list_queues = queues_sub.add_parser('list', help='List all queues')
|
|
83
|
+
list_queues.add_argument('--format', choices=['table', 'json'], default='table')
|
|
84
|
+
|
|
85
|
+
purge_queue = queues_sub.add_parser('purge', help='Purge all jobs from a queue')
|
|
86
|
+
purge_queue.add_argument('name', help='Queue name')
|
|
87
|
+
purge_queue.add_argument('--status', choices=['all', 'pending', 'failed'], default='all')
|
|
88
|
+
|
|
89
|
+
stats_queue = queues_sub.add_parser('stats', help='Show queue statistics')
|
|
90
|
+
stats_queue.add_argument('name', nargs='?', help='Queue name (optional)')
|
|
91
|
+
|
|
92
|
+
return jobs_parser
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def handle_jobs(args) -> int:
|
|
96
|
+
"""Handle jobs command"""
|
|
97
|
+
from quantum.runtime.job_executor import JobExecutor
|
|
98
|
+
|
|
99
|
+
if not args.jobs_action:
|
|
100
|
+
print("Usage: quantum jobs <action>")
|
|
101
|
+
print("Actions: list, status, run, pause, resume, cancel, history, worker, queues")
|
|
102
|
+
return 1
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
executor = JobExecutor()
|
|
106
|
+
|
|
107
|
+
if args.jobs_action == 'list':
|
|
108
|
+
return _handle_jobs_list(executor, args)
|
|
109
|
+
elif args.jobs_action == 'status':
|
|
110
|
+
return _handle_jobs_status(executor, args)
|
|
111
|
+
elif args.jobs_action == 'run':
|
|
112
|
+
return _handle_jobs_run(executor, args)
|
|
113
|
+
elif args.jobs_action == 'pause':
|
|
114
|
+
return _handle_jobs_pause(executor, args)
|
|
115
|
+
elif args.jobs_action == 'resume':
|
|
116
|
+
return _handle_jobs_resume(executor, args)
|
|
117
|
+
elif args.jobs_action == 'cancel':
|
|
118
|
+
return _handle_jobs_cancel(executor, args)
|
|
119
|
+
elif args.jobs_action == 'history':
|
|
120
|
+
return _handle_jobs_history(executor, args)
|
|
121
|
+
elif args.jobs_action == 'worker':
|
|
122
|
+
return _handle_jobs_worker(executor, args)
|
|
123
|
+
elif args.jobs_action == 'queues':
|
|
124
|
+
return _handle_jobs_queues(executor, args)
|
|
125
|
+
else:
|
|
126
|
+
print(f"Unknown action: {args.jobs_action}")
|
|
127
|
+
return 1
|
|
128
|
+
|
|
129
|
+
except Exception as e:
|
|
130
|
+
print(f"[ERROR] {e}")
|
|
131
|
+
return 1
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _handle_jobs_list(executor, args) -> int:
|
|
135
|
+
"""List all jobs"""
|
|
136
|
+
jobs = executor.list_jobs(
|
|
137
|
+
status=args.status if args.status != 'all' else None,
|
|
138
|
+
queue=args.queue
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if args.format == 'json':
|
|
142
|
+
print(json.dumps(jobs, indent=2, default=str))
|
|
143
|
+
else:
|
|
144
|
+
if not jobs:
|
|
145
|
+
print("No jobs found.")
|
|
146
|
+
return 0
|
|
147
|
+
|
|
148
|
+
# Table format
|
|
149
|
+
print(f"{'Name':<25} {'Queue':<15} {'Status':<10} {'Next Run':<20} {'Last Run':<20}")
|
|
150
|
+
print("-" * 95)
|
|
151
|
+
for job in jobs:
|
|
152
|
+
next_run = job.get('next_run', '-')
|
|
153
|
+
last_run = job.get('last_run', '-')
|
|
154
|
+
if isinstance(next_run, datetime):
|
|
155
|
+
next_run = next_run.strftime('%Y-%m-%d %H:%M:%S')
|
|
156
|
+
if isinstance(last_run, datetime):
|
|
157
|
+
last_run = last_run.strftime('%Y-%m-%d %H:%M:%S')
|
|
158
|
+
print(f"{job['name']:<25} {job.get('queue', 'default'):<15} {job['status']:<10} {next_run:<20} {last_run:<20}")
|
|
159
|
+
|
|
160
|
+
return 0
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _handle_jobs_status(executor, args) -> int:
|
|
164
|
+
"""Get job status"""
|
|
165
|
+
job = executor.get_job_status(args.name)
|
|
166
|
+
|
|
167
|
+
if not job:
|
|
168
|
+
print(f"Job not found: {args.name}")
|
|
169
|
+
return 1
|
|
170
|
+
|
|
171
|
+
if args.format == 'json':
|
|
172
|
+
print(json.dumps(job, indent=2, default=str))
|
|
173
|
+
else:
|
|
174
|
+
print(f"Job: {job['name']}")
|
|
175
|
+
print(f"Status: {job['status']}")
|
|
176
|
+
print(f"Queue: {job.get('queue', 'default')}")
|
|
177
|
+
if job.get('interval'):
|
|
178
|
+
print(f"Interval: {job['interval']}")
|
|
179
|
+
if job.get('cron'):
|
|
180
|
+
print(f"Cron: {job['cron']}")
|
|
181
|
+
print(f"Last Run: {job.get('last_run', 'Never')}")
|
|
182
|
+
print(f"Next Run: {job.get('next_run', '-')}")
|
|
183
|
+
print(f"Run Count: {job.get('run_count', 0)}")
|
|
184
|
+
print(f"Error Count: {job.get('error_count', 0)}")
|
|
185
|
+
if job.get('last_error'):
|
|
186
|
+
print(f"Last Error: {job['last_error']}")
|
|
187
|
+
|
|
188
|
+
return 0
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _handle_jobs_run(executor, args) -> int:
|
|
192
|
+
"""Run job manually"""
|
|
193
|
+
params = {}
|
|
194
|
+
if args.params:
|
|
195
|
+
try:
|
|
196
|
+
params = json.loads(args.params)
|
|
197
|
+
except json.JSONDecodeError as e:
|
|
198
|
+
print(f"Invalid JSON parameters: {e}")
|
|
199
|
+
return 1
|
|
200
|
+
|
|
201
|
+
print(f"Running job: {args.name}...")
|
|
202
|
+
result = executor.run_job_now(args.name, params=params, wait=args.sync)
|
|
203
|
+
|
|
204
|
+
if args.sync:
|
|
205
|
+
if result.get('success'):
|
|
206
|
+
print(f"Job completed successfully.")
|
|
207
|
+
if result.get('result'):
|
|
208
|
+
print(f"Result: {result['result']}")
|
|
209
|
+
else:
|
|
210
|
+
print(f"Job failed: {result.get('error', 'Unknown error')}")
|
|
211
|
+
return 1
|
|
212
|
+
else:
|
|
213
|
+
print(f"Job queued for execution. Job ID: {result.get('job_id', 'N/A')}")
|
|
214
|
+
|
|
215
|
+
return 0
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _handle_jobs_pause(executor, args) -> int:
|
|
219
|
+
"""Pause a scheduled job"""
|
|
220
|
+
if executor.pause_job(args.name):
|
|
221
|
+
print(f"Job paused: {args.name}")
|
|
222
|
+
return 0
|
|
223
|
+
else:
|
|
224
|
+
print(f"Failed to pause job: {args.name}")
|
|
225
|
+
return 1
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def _handle_jobs_resume(executor, args) -> int:
|
|
229
|
+
"""Resume a paused job"""
|
|
230
|
+
if executor.resume_job(args.name):
|
|
231
|
+
print(f"Job resumed: {args.name}")
|
|
232
|
+
return 0
|
|
233
|
+
else:
|
|
234
|
+
print(f"Failed to resume job: {args.name}")
|
|
235
|
+
return 1
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _handle_jobs_cancel(executor, args) -> int:
|
|
239
|
+
"""Cancel a job"""
|
|
240
|
+
if executor.cancel_job(args.name):
|
|
241
|
+
print(f"Job cancelled: {args.name}")
|
|
242
|
+
return 0
|
|
243
|
+
else:
|
|
244
|
+
print(f"Failed to cancel job: {args.name}")
|
|
245
|
+
return 1
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _handle_jobs_history(executor, args) -> int:
|
|
249
|
+
"""View job history"""
|
|
250
|
+
history = executor.get_job_history(
|
|
251
|
+
name=args.name,
|
|
252
|
+
limit=args.limit,
|
|
253
|
+
status=args.status if args.status != 'all' else None
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
if args.format == 'json':
|
|
257
|
+
print(json.dumps(history, indent=2, default=str))
|
|
258
|
+
else:
|
|
259
|
+
if not history:
|
|
260
|
+
print("No history found.")
|
|
261
|
+
return 0
|
|
262
|
+
|
|
263
|
+
print(f"{'Job':<20} {'Status':<10} {'Started':<20} {'Duration':<12} {'Error':<30}")
|
|
264
|
+
print("-" * 95)
|
|
265
|
+
for entry in history:
|
|
266
|
+
started = entry.get('started_at', '-')
|
|
267
|
+
if isinstance(started, datetime):
|
|
268
|
+
started = started.strftime('%Y-%m-%d %H:%M:%S')
|
|
269
|
+
|
|
270
|
+
duration = entry.get('duration', '-')
|
|
271
|
+
if isinstance(duration, (int, float)):
|
|
272
|
+
duration = f"{duration:.2f}s"
|
|
273
|
+
|
|
274
|
+
error = entry.get('error', '')[:30] if entry.get('error') else ''
|
|
275
|
+
|
|
276
|
+
print(f"{entry['name']:<20} {entry['status']:<10} {started:<20} {str(duration):<12} {error:<30}")
|
|
277
|
+
|
|
278
|
+
return 0
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _handle_jobs_worker(executor, args) -> int:
|
|
282
|
+
"""Handle worker commands"""
|
|
283
|
+
if not args.worker_action:
|
|
284
|
+
print("Usage: quantum jobs worker <start|stop>")
|
|
285
|
+
return 1
|
|
286
|
+
|
|
287
|
+
if args.worker_action == 'start':
|
|
288
|
+
queues = [q.strip() for q in args.queue.split(',')]
|
|
289
|
+
print(f"Starting worker...")
|
|
290
|
+
print(f" Queues: {', '.join(queues)}")
|
|
291
|
+
print(f" Concurrency: {args.concurrency}")
|
|
292
|
+
print(f" Poll interval: {args.poll_interval}s")
|
|
293
|
+
print("")
|
|
294
|
+
print("Press Ctrl+C to stop the worker.")
|
|
295
|
+
print("")
|
|
296
|
+
|
|
297
|
+
try:
|
|
298
|
+
executor.start_worker(
|
|
299
|
+
queues=queues,
|
|
300
|
+
concurrency=args.concurrency,
|
|
301
|
+
poll_interval=args.poll_interval
|
|
302
|
+
)
|
|
303
|
+
except KeyboardInterrupt:
|
|
304
|
+
print("\nStopping worker...")
|
|
305
|
+
executor.stop_worker(graceful=True)
|
|
306
|
+
print("Worker stopped.")
|
|
307
|
+
|
|
308
|
+
return 0
|
|
309
|
+
|
|
310
|
+
elif args.worker_action == 'stop':
|
|
311
|
+
executor.stop_worker(graceful=args.graceful)
|
|
312
|
+
print("Worker stop signal sent.")
|
|
313
|
+
return 0
|
|
314
|
+
|
|
315
|
+
return 1
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def _handle_jobs_queues(executor, args) -> int:
|
|
319
|
+
"""Handle queue management commands"""
|
|
320
|
+
if not args.queues_action:
|
|
321
|
+
print("Usage: quantum jobs queues <list|purge|stats>")
|
|
322
|
+
return 1
|
|
323
|
+
|
|
324
|
+
if args.queues_action == 'list':
|
|
325
|
+
queues = executor.list_queues()
|
|
326
|
+
|
|
327
|
+
if args.format == 'json':
|
|
328
|
+
print(json.dumps(queues, indent=2))
|
|
329
|
+
else:
|
|
330
|
+
if not queues:
|
|
331
|
+
print("No queues found.")
|
|
332
|
+
return 0
|
|
333
|
+
|
|
334
|
+
print(f"{'Queue':<20} {'Pending':<10} {'Running':<10} {'Completed':<10} {'Failed':<10}")
|
|
335
|
+
print("-" * 65)
|
|
336
|
+
for q in queues:
|
|
337
|
+
print(f"{q['name']:<20} {q.get('pending', 0):<10} {q.get('running', 0):<10} {q.get('completed', 0):<10} {q.get('failed', 0):<10}")
|
|
338
|
+
|
|
339
|
+
return 0
|
|
340
|
+
|
|
341
|
+
elif args.queues_action == 'purge':
|
|
342
|
+
count = executor.purge_queue(args.name, status=args.status if args.status != 'all' else None)
|
|
343
|
+
print(f"Purged {count} job(s) from queue: {args.name}")
|
|
344
|
+
return 0
|
|
345
|
+
|
|
346
|
+
elif args.queues_action == 'stats':
|
|
347
|
+
stats = executor.get_queue_stats(args.name)
|
|
348
|
+
|
|
349
|
+
print("Queue Statistics")
|
|
350
|
+
print("-" * 40)
|
|
351
|
+
for key, value in stats.items():
|
|
352
|
+
print(f" {key}: {value}")
|
|
353
|
+
|
|
354
|
+
return 0
|
|
355
|
+
|
|
356
|
+
return 1
|