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.
Files changed (262) hide show
  1. quantum/__init__.py +1 -0
  2. quantum/cli/__init__.py +2 -0
  3. quantum/cli/commands/__init__.py +15 -0
  4. quantum/cli/commands/build.py +417 -0
  5. quantum/cli/commands/dev.py +185 -0
  6. quantum/cli/commands/docs.py +329 -0
  7. quantum/cli/commands/lint.py +523 -0
  8. quantum/cli/commands/migrate.py +527 -0
  9. quantum/cli/commands/new.py +622 -0
  10. quantum/cli/commands/serve.py +190 -0
  11. quantum/cli/commands/test.py +193 -0
  12. quantum/cli/deploy.py +810 -0
  13. quantum/cli/hot_reload.py +951 -0
  14. quantum/cli/jobs.py +356 -0
  15. quantum/cli/mq.py +582 -0
  16. quantum/cli/pkg.py +390 -0
  17. quantum/cli/runner.py +547 -0
  18. quantum/cli/server_process.py +159 -0
  19. quantum/cli/utils.py +334 -0
  20. quantum/compiler/__init__.py +30 -0
  21. quantum/compiler/base_generator.py +367 -0
  22. quantum/compiler/cli.py +295 -0
  23. quantum/compiler/expression_transformer.py +444 -0
  24. quantum/compiler/javascript/__init__.py +10 -0
  25. quantum/compiler/javascript/generator.py +659 -0
  26. quantum/compiler/optimizer.py +270 -0
  27. quantum/compiler/python/__init__.py +10 -0
  28. quantum/compiler/python/generator.py +883 -0
  29. quantum/compiler/python/runtime.py +863 -0
  30. quantum/compiler/transpiler.py +330 -0
  31. quantum/core/__init__.py +3 -0
  32. quantum/core/ast_nodes.py +2611 -0
  33. quantum/core/expression_diagnostics.py +87 -0
  34. quantum/core/expression_stdlib.py +148 -0
  35. quantum/core/expressions.py +591 -0
  36. quantum/core/features/agents/src/__init__.py +30 -0
  37. quantum/core/features/agents/src/ast_node.py +540 -0
  38. quantum/core/features/conditionals/src/__init__.py +8 -0
  39. quantum/core/features/conditionals/src/ast_node.py +68 -0
  40. quantum/core/features/data_fetching/src/__init__.py +21 -0
  41. quantum/core/features/data_fetching/src/ast_node.py +312 -0
  42. quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
  43. quantum/core/features/data_fetching/src/html_adapter.py +474 -0
  44. quantum/core/features/data_fetching/src/parser.py +225 -0
  45. quantum/core/features/data_import/src/__init__.py +0 -0
  46. quantum/core/features/data_import/src/ast_node.py +291 -0
  47. quantum/core/features/data_import/src/runtime.py +538 -0
  48. quantum/core/features/dump/src/__init__.py +12 -0
  49. quantum/core/features/dump/src/ast_node.py +106 -0
  50. quantum/core/features/dump/src/parser.py +61 -0
  51. quantum/core/features/dump/src/runtime.py +246 -0
  52. quantum/core/features/functions/src/__init__.py +8 -0
  53. quantum/core/features/functions/src/ast_node.py +149 -0
  54. quantum/core/features/game_engine_2d/src/__init__.py +19 -0
  55. quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
  56. quantum/core/features/game_engine_2d/src/parser.py +983 -0
  57. quantum/core/features/invocation/src/__init__.py +0 -0
  58. quantum/core/features/invocation/src/ast_node.py +146 -0
  59. quantum/core/features/invocation/src/runtime.py +327 -0
  60. quantum/core/features/knowledge_base/src/__init__.py +6 -0
  61. quantum/core/features/knowledge_base/src/ast_node.py +113 -0
  62. quantum/core/features/knowledge_base/src/parser.py +82 -0
  63. quantum/core/features/logging/src/__init__.py +12 -0
  64. quantum/core/features/logging/src/ast_node.py +111 -0
  65. quantum/core/features/logging/src/parser.py +50 -0
  66. quantum/core/features/logging/src/runtime.py +190 -0
  67. quantum/core/features/loops/src/__init__.py +8 -0
  68. quantum/core/features/loops/src/ast_node.py +60 -0
  69. quantum/core/features/query/src/__init__.py +0 -0
  70. quantum/core/features/query/src/database_service.py +322 -0
  71. quantum/core/features/query/src/query_validators.py +20 -0
  72. quantum/core/features/state_management/src/__init__.py +11 -0
  73. quantum/core/features/state_management/src/ast_node.py +228 -0
  74. quantum/core/features/terminal_engine/src/__init__.py +21 -0
  75. quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
  76. quantum/core/features/terminal_engine/src/parser.py +361 -0
  77. quantum/core/features/testing_engine/src/__init__.py +41 -0
  78. quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
  79. quantum/core/features/testing_engine/src/parser.py +604 -0
  80. quantum/core/features/theming/src/__init__.py +48 -0
  81. quantum/core/features/theming/src/ast_node.py +137 -0
  82. quantum/core/features/theming/src/presets.py +405 -0
  83. quantum/core/features/ui_engine/src/__init__.py +20 -0
  84. quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
  85. quantum/core/features/ui_engine/src/parser.py +1106 -0
  86. quantum/core/features/websocket/src/__init__.py +24 -0
  87. quantum/core/features/websocket/src/ast_node.py +247 -0
  88. quantum/core/html_compat.py +299 -0
  89. quantum/core/parser.py +1235 -0
  90. quantum/core/parser_registry.py +213 -0
  91. quantum/core/parsers/__init__.py +76 -0
  92. quantum/core/parsers/ai/__init__.py +12 -0
  93. quantum/core/parsers/ai/agent_parser.py +106 -0
  94. quantum/core/parsers/ai/knowledge_parser.py +86 -0
  95. quantum/core/parsers/ai/llm_parser.py +78 -0
  96. quantum/core/parsers/ai/team_parser.py +88 -0
  97. quantum/core/parsers/base.py +322 -0
  98. quantum/core/parsers/composition/__init__.py +10 -0
  99. quantum/core/parsers/composition/import_parser.py +50 -0
  100. quantum/core/parsers/composition/slot_parser.py +48 -0
  101. quantum/core/parsers/control_flow/__init__.py +11 -0
  102. quantum/core/parsers/control_flow/if_parser.py +68 -0
  103. quantum/core/parsers/control_flow/loop_parser.py +105 -0
  104. quantum/core/parsers/control_flow/set_parser.py +89 -0
  105. quantum/core/parsers/data/__init__.py +12 -0
  106. quantum/core/parsers/data/data_parser.py +217 -0
  107. quantum/core/parsers/data/invoke_parser.py +116 -0
  108. quantum/core/parsers/data/query_parser.py +188 -0
  109. quantum/core/parsers/data/transaction_parser.py +77 -0
  110. quantum/core/parsers/events/__init__.py +9 -0
  111. quantum/core/parsers/events/dispatch_event_parser.py +44 -0
  112. quantum/core/parsers/forms/__init__.py +11 -0
  113. quantum/core/parsers/forms/action_parser.py +54 -0
  114. quantum/core/parsers/forms/flash_parser.py +34 -0
  115. quantum/core/parsers/forms/redirect_parser.py +33 -0
  116. quantum/core/parsers/functions/__init__.py +11 -0
  117. quantum/core/parsers/functions/function_parser.py +137 -0
  118. quantum/core/parsers/functions/param_parser.py +66 -0
  119. quantum/core/parsers/functions/return_parser.py +31 -0
  120. quantum/core/parsers/html/__init__.py +10 -0
  121. quantum/core/parsers/html/component_call_parser.py +130 -0
  122. quantum/core/parsers/html/html_parser.py +115 -0
  123. quantum/core/parsers/jobs/__init__.py +11 -0
  124. quantum/core/parsers/jobs/job_parser.py +71 -0
  125. quantum/core/parsers/jobs/schedule_parser.py +62 -0
  126. quantum/core/parsers/jobs/thread_parser.py +57 -0
  127. quantum/core/parsers/messaging/__init__.py +17 -0
  128. quantum/core/parsers/messaging/message_ack_parser.py +30 -0
  129. quantum/core/parsers/messaging/message_nack_parser.py +30 -0
  130. quantum/core/parsers/messaging/message_parser.py +114 -0
  131. quantum/core/parsers/messaging/queue_parser.py +61 -0
  132. quantum/core/parsers/messaging/websocket_parser.py +121 -0
  133. quantum/core/parsers/persistence/__init__.py +9 -0
  134. quantum/core/parsers/persistence/persist_parser.py +64 -0
  135. quantum/core/parsers/routing/__init__.py +9 -0
  136. quantum/core/parsers/routing/route_parser.py +41 -0
  137. quantum/core/parsers/scripting/__init__.py +12 -0
  138. quantum/core/parsers/scripting/pyclass_parser.py +62 -0
  139. quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
  140. quantum/core/parsers/scripting/pyimport_parser.py +52 -0
  141. quantum/core/parsers/scripting/python_parser.py +49 -0
  142. quantum/core/parsers/services/__init__.py +12 -0
  143. quantum/core/parsers/services/dump_parser.py +52 -0
  144. quantum/core/parsers/services/file_parser.py +48 -0
  145. quantum/core/parsers/services/log_parser.py +46 -0
  146. quantum/core/parsers/services/mail_parser.py +65 -0
  147. quantum/core/tiers.py +82 -0
  148. quantum/packages/__init__.py +28 -0
  149. quantum/packages/manager.py +413 -0
  150. quantum/packages/manifest.py +351 -0
  151. quantum/packages/registry.py +399 -0
  152. quantum/packages/resolver.py +336 -0
  153. quantum/plugins/__init__.py +33 -0
  154. quantum/plugins/hooks.py +329 -0
  155. quantum/plugins/loader.py +479 -0
  156. quantum/plugins/manifest.py +336 -0
  157. quantum/plugins/registry.py +371 -0
  158. quantum/runtime/__init__.py +28 -0
  159. quantum/runtime/action_handler.py +443 -0
  160. quantum/runtime/adapters/__init__.py +88 -0
  161. quantum/runtime/adapters/memory_adapter.py +690 -0
  162. quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
  163. quantum/runtime/adapters/redis_adapter.py +582 -0
  164. quantum/runtime/adapters/sqlite_adapter.py +414 -0
  165. quantum/runtime/agent_service.py +1133 -0
  166. quantum/runtime/api_server.py +86 -0
  167. quantum/runtime/ast_cache.py +506 -0
  168. quantum/runtime/auth_service.py +267 -0
  169. quantum/runtime/component.py +990 -0
  170. quantum/runtime/component_composer.py +319 -0
  171. quantum/runtime/component_resolver.py +174 -0
  172. quantum/runtime/database_service.py +598 -0
  173. quantum/runtime/email_service.py +162 -0
  174. quantum/runtime/error_handler.py +295 -0
  175. quantum/runtime/execution_context.py +286 -0
  176. quantum/runtime/executor_registry.py +171 -0
  177. quantum/runtime/executors/__init__.py +71 -0
  178. quantum/runtime/executors/ai/__init__.py +12 -0
  179. quantum/runtime/executors/ai/agent_executor.py +217 -0
  180. quantum/runtime/executors/ai/knowledge_executor.py +114 -0
  181. quantum/runtime/executors/ai/llm_executor.py +153 -0
  182. quantum/runtime/executors/ai/team_executor.py +171 -0
  183. quantum/runtime/executors/base.py +262 -0
  184. quantum/runtime/executors/control_flow/__init__.py +11 -0
  185. quantum/runtime/executors/control_flow/if_executor.py +93 -0
  186. quantum/runtime/executors/control_flow/loop_executor.py +307 -0
  187. quantum/runtime/executors/control_flow/set_executor.py +412 -0
  188. quantum/runtime/executors/data/__init__.py +12 -0
  189. quantum/runtime/executors/data/data_executor.py +145 -0
  190. quantum/runtime/executors/data/invoke_executor.py +176 -0
  191. quantum/runtime/executors/data/query_executor.py +256 -0
  192. quantum/runtime/executors/data/transaction_executor.py +91 -0
  193. quantum/runtime/executors/jobs/__init__.py +11 -0
  194. quantum/runtime/executors/jobs/job_executor.py +190 -0
  195. quantum/runtime/executors/jobs/schedule_executor.py +132 -0
  196. quantum/runtime/executors/jobs/thread_executor.py +127 -0
  197. quantum/runtime/executors/messaging/__init__.py +17 -0
  198. quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
  199. quantum/runtime/executors/messaging/message_executor.py +174 -0
  200. quantum/runtime/executors/messaging/queue_executor.py +103 -0
  201. quantum/runtime/executors/messaging/websocket_executor.py +197 -0
  202. quantum/runtime/executors/scripting/__init__.py +11 -0
  203. quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
  204. quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
  205. quantum/runtime/executors/scripting/python_executor.py +249 -0
  206. quantum/runtime/executors/services/__init__.py +12 -0
  207. quantum/runtime/executors/services/dump_executor.py +72 -0
  208. quantum/runtime/executors/services/file_executor.py +89 -0
  209. quantum/runtime/executors/services/log_executor.py +77 -0
  210. quantum/runtime/executors/services/mail_executor.py +81 -0
  211. quantum/runtime/expression_cache.py +498 -0
  212. quantum/runtime/file_upload_service.py +326 -0
  213. quantum/runtime/function_registry.py +118 -0
  214. quantum/runtime/game_builder.py +166 -0
  215. quantum/runtime/game_code_generator.py +2371 -0
  216. quantum/runtime/game_templates.py +2006 -0
  217. quantum/runtime/godot_code_generator.py +4681 -0
  218. quantum/runtime/godot_templates.py +1449 -0
  219. quantum/runtime/job_executor.py +1599 -0
  220. quantum/runtime/knowledge_service.py +500 -0
  221. quantum/runtime/llm_cache.py +100 -0
  222. quantum/runtime/llm_providers.py +704 -0
  223. quantum/runtime/llm_service.py +287 -0
  224. quantum/runtime/logging_setup.py +140 -0
  225. quantum/runtime/message_broker.py +364 -0
  226. quantum/runtime/message_queue_service.py +571 -0
  227. quantum/runtime/param_validation.py +184 -0
  228. quantum/runtime/pypy_compat.py +315 -0
  229. quantum/runtime/python_bridge.py +698 -0
  230. quantum/runtime/query_validators.py +304 -0
  231. quantum/runtime/renderer.py +733 -0
  232. quantum/runtime/service_container.py +444 -0
  233. quantum/runtime/terminal_builder.py +76 -0
  234. quantum/runtime/terminal_code_generator.py +607 -0
  235. quantum/runtime/terminal_templates.py +243 -0
  236. quantum/runtime/testing_builder.py +77 -0
  237. quantum/runtime/testing_code_generator.py +833 -0
  238. quantum/runtime/testing_templates.py +85 -0
  239. quantum/runtime/ui_builder.py +188 -0
  240. quantum/runtime/ui_desktop_adapter.py +1730 -0
  241. quantum/runtime/ui_desktop_templates.py +307 -0
  242. quantum/runtime/ui_html_adapter.py +2691 -0
  243. quantum/runtime/ui_html_templates.py +2297 -0
  244. quantum/runtime/ui_mobile_adapter.py +1832 -0
  245. quantum/runtime/ui_mobile_templates.py +1003 -0
  246. quantum/runtime/ui_textual_adapter.py +1866 -0
  247. quantum/runtime/ui_textual_templates.py +45 -0
  248. quantum/runtime/ui_tokens.py +465 -0
  249. quantum/runtime/ui_validator.py +365 -0
  250. quantum/runtime/validators.py +256 -0
  251. quantum/runtime/web_server.py +1766 -0
  252. quantum/runtime/websocket_adapter.py +501 -0
  253. quantum/runtime/websocket_service.py +585 -0
  254. quantum/runtime/websocket_transport.py +289 -0
  255. quantum/runtime/wsgi.py +101 -0
  256. quantum/utils/__init__.py +1 -0
  257. quantum_framework-0.9.0.dist-info/METADATA +244 -0
  258. quantum_framework-0.9.0.dist-info/RECORD +262 -0
  259. quantum_framework-0.9.0.dist-info/WHEEL +5 -0
  260. quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
  261. quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
  262. 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