quapp-common 0.0.13.dev6__tar.gz → 0.0.13.dev8__tar.gz

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 (92) hide show
  1. {quapp_common-0.0.13.dev6/quapp_common.egg-info → quapp_common-0.0.13.dev8}/PKG-INFO +1 -1
  2. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/pyproject.toml +41 -41
  3. quapp_common-0.0.13.dev8/quapp_common/component/backend/job_heartbeat.py +83 -0
  4. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/job_manager.py +6 -0
  5. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/circuit_adapter.py +286 -286
  6. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/dispatcher.py +4 -0
  7. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/language.py +1 -0
  8. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8/quapp_common.egg-info}/PKG-INFO +1 -1
  9. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/SOURCES.txt +3 -0
  10. quapp_common-0.0.13.dev8/tests/test_job_heartbeat.py +115 -0
  11. quapp_common-0.0.13.dev8/tests/test_language_dispatcher.py +20 -0
  12. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/LICENSE +0 -0
  13. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/README.md +0 -0
  14. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/__init__.py +0 -0
  15. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/__init__.py +0 -0
  16. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/async_invocation_task.py +0 -0
  17. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/async_task.py +0 -0
  18. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/export_circuit_task.py +0 -0
  19. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/post_processing_task.py +0 -0
  20. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/__init__.py +0 -0
  21. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/__init__.py +0 -0
  22. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/invocation.py +0 -0
  23. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/job_fetcher.py +0 -0
  24. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/job_fetching.py +0 -0
  25. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/bridge.py +0 -0
  26. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/callback/__init__.py +0 -0
  27. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/callback/update_job_metadata.py +0 -0
  28. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/device/__init__.py +0 -0
  29. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/device/device_selection.py +0 -0
  30. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/result_serializer.py +0 -0
  31. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/config/__init__.py +0 -0
  32. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/config/logging_config.py +0 -0
  33. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/config/thread_config.py +0 -0
  34. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/__init__.py +0 -0
  35. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/__init__.py +0 -0
  36. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
  37. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
  38. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
  39. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/backend/__init__.py +0 -0
  40. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/backend/backend_information.py +0 -0
  41. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/callback/__init__.py +0 -0
  42. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/callback/callback_url.py +0 -0
  43. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/device/__init__.py +0 -0
  44. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/device/circuit_running_option.py +0 -0
  45. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/promise/__init__.py +0 -0
  46. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/promise/post_processing_promise.py +0 -0
  47. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/promise/promise.py +0 -0
  48. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/__init__.py +0 -0
  49. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/invocation_request.py +0 -0
  50. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/job_fetching_request.py +0 -0
  51. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/request.py +0 -0
  52. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/__init__.py +0 -0
  53. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/authentication.py +0 -0
  54. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/custom_header.py +0 -0
  55. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/job_response.py +0 -0
  56. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/__init__.py +0 -0
  57. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/base_enum.py +0 -0
  58. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/http_header.py +0 -0
  59. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/invocation_step.py +0 -0
  60. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/media_type.py +0 -0
  61. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/processing_unit.py +0 -0
  62. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/provider_tag.py +0 -0
  63. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/sdk.py +0 -0
  64. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/status/__init__.py +0 -0
  65. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/status/job_status.py +0 -0
  66. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/status/status_code.py +0 -0
  67. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/token_type.py +0 -0
  68. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/__init__.py +0 -0
  69. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/device_factory.py +0 -0
  70. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/handler_factory.py +0 -0
  71. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/provider_factory.py +0 -0
  72. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/handler/__init__.py +0 -0
  73. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/handler/handler.py +0 -0
  74. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/__init__.py +0 -0
  75. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/device/__init__.py +0 -0
  76. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/device/custom_device.py +0 -0
  77. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/device/device.py +0 -0
  78. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/invocation.py +0 -0
  79. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/provider/__init__.py +0 -0
  80. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/provider/provider.py +0 -0
  81. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/__init__.py +0 -0
  82. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/file_utils.py +0 -0
  83. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/http_utils.py +0 -0
  84. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/json_parser_utils.py +0 -0
  85. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/response_utils.py +0 -0
  86. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/dependency_links.txt +0 -0
  87. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/requires.txt +0 -0
  88. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/top_level.txt +0 -0
  89. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/setup.cfg +0 -0
  90. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/tests/test_circuit_adapter.py +0 -0
  91. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/tests/test_json_parser_utils.py +0 -0
  92. {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/tests/test_result_serializer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.13.dev6
3
+ Version: 0.0.13.dev8
4
4
  Summary: Quapp common library supporting Quapp Platform for Quantum Computing
5
5
  Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
6
6
  License: The MIT License (MIT)
@@ -1,41 +1,41 @@
1
- [build-system]
2
- requires = ["setuptools>=61.0.0", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "quapp-common"
7
- version = "0.0.13.dev6"
8
- description = "Quapp common library supporting Quapp Platform for Quantum Computing"
9
- readme = "README.md"
10
- authors = [{ name = "CITYNOW Co. Ltd. ", email = "corp@citynow.vn" }]
11
- license = { file = "LICENSE" }
12
- classifiers = [
13
- "License :: OSI Approved :: MIT License",
14
- "Programming Language :: Python",
15
- "Programming Language :: Python :: 3",
16
- ]
17
- keywords = ["quapp", "quapp-common", "quantum"]
18
- dependencies = [
19
- "loguru",
20
- "requests",
21
- "numpy",
22
- "matplotlib",
23
- "pylatexenc",
24
- "starlette",
25
- "qibo",
26
- "dimod",
27
- "qulacs",
28
- "qiskit",
29
- "pytket",
30
- "pennylane"
31
- ]
32
- requires-python = ">=3.7"
33
-
34
- [project.optional-dependencies]
35
- dev = ["black", "bumpver", "isort", "pip-tools", "pytest"]
36
-
37
- [project.urls]
38
- Homepage = "https://citynow.asia/"
39
-
40
- [tool.pylint.main]
41
- source-roots = ["."]
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "quapp-common"
7
+ version = "0.0.13.dev8"
8
+ description = "Quapp common library supporting Quapp Platform for Quantum Computing"
9
+ readme = "README.md"
10
+ authors = [{ name = "CITYNOW Co. Ltd. ", email = "corp@citynow.vn" }]
11
+ license = { file = "LICENSE" }
12
+ classifiers = [
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python",
15
+ "Programming Language :: Python :: 3",
16
+ ]
17
+ keywords = ["quapp", "quapp-common", "quantum"]
18
+ dependencies = [
19
+ "loguru",
20
+ "requests",
21
+ "numpy",
22
+ "matplotlib",
23
+ "pylatexenc",
24
+ "starlette",
25
+ "qibo",
26
+ "dimod",
27
+ "qulacs",
28
+ "qiskit",
29
+ "pytket",
30
+ "pennylane"
31
+ ]
32
+ requires-python = ">=3.7"
33
+
34
+ [project.optional-dependencies]
35
+ dev = ["black", "bumpver", "isort", "pip-tools", "pytest"]
36
+
37
+ [project.urls]
38
+ Homepage = "https://citynow.asia/"
39
+
40
+ [tool.pylint.main]
41
+ source-roots = ["."]
@@ -0,0 +1,83 @@
1
+ # Quapp Platform Project
2
+ # job_heartbeat.py
3
+ # Copyright © CITYNOW Co. Ltd. All rights reserved.
4
+
5
+ import os
6
+ import threading
7
+
8
+ import requests
9
+
10
+ from ...config.logging_config import logger
11
+
12
+ DEFAULT_INTERVAL_SEC = 30.0
13
+ REQUEST_TIMEOUT_SEC = 5.0
14
+ TERMINAL_STATUSES = ('DONE', 'FAILED')
15
+
16
+ _lock = threading.Lock()
17
+ _thread = None
18
+ _stop_event = threading.Event()
19
+
20
+
21
+ def heartbeat_interval_sec() -> float:
22
+ raw = os.getenv('HEARTBEAT_INTERVAL_SEC', '')
23
+ try:
24
+ value = float(raw)
25
+ if value > 0:
26
+ return value
27
+ except ValueError:
28
+ pass
29
+ return DEFAULT_INTERVAL_SEC
30
+
31
+
32
+ def beat_once() -> int:
33
+ from .job_manager import JobManager, META, STATUS, SCHEDULER_CALLBACK_URL
34
+
35
+ sent = 0
36
+ for job_id, data in JobManager.list_jobs().items():
37
+ if data.get(STATUS) in TERMINAL_STATUSES:
38
+ continue
39
+ url = (data.get(META) or {}).get(SCHEDULER_CALLBACK_URL)
40
+ if not url:
41
+ continue
42
+ try:
43
+ response = requests.patch(
44
+ url, json={'status': 'RUNNING', 'heartbeat': True},
45
+ timeout=REQUEST_TIMEOUT_SEC)
46
+ logger.debug(
47
+ f'Heartbeat for job {job_id} returned {response.status_code}')
48
+ sent += 1
49
+ except Exception as exception:
50
+ logger.debug(f'Heartbeat for job {job_id} failed: {exception}')
51
+ return sent
52
+
53
+
54
+ def _run() -> None:
55
+ while True:
56
+ try:
57
+ beat_once()
58
+ except Exception as exception:
59
+ logger.exception(f'Heartbeat loop error: {exception}')
60
+ if _stop_event.wait(heartbeat_interval_sec()):
61
+ return
62
+
63
+
64
+ def ensure_started() -> None:
65
+ global _thread
66
+ with _lock:
67
+ if _thread is not None and _thread.is_alive():
68
+ return
69
+ _stop_event.clear()
70
+ _thread = threading.Thread(target=_run, name='job-heartbeat',
71
+ daemon=True)
72
+ _thread.start()
73
+ logger.info(
74
+ f'Job heartbeat started with interval {heartbeat_interval_sec()}s')
75
+
76
+
77
+ def stop() -> None:
78
+ global _thread
79
+ with _lock:
80
+ _stop_event.set()
81
+ if _thread is not None:
82
+ _thread.join(timeout=1.0)
83
+ _thread = None
@@ -66,6 +66,9 @@ class JobManager:
66
66
  """
67
67
  Stop any listener threads in this process and shutdown Manager.
68
68
  """
69
+ from .job_heartbeat import stop
70
+ stop()
71
+
69
72
  # stop listeners
70
73
  for key, (t, stop_ev) in list(cls._listener_threads.items()):
71
74
  stop_ev.set()
@@ -100,6 +103,9 @@ class JobManager:
100
103
  cls._jobs[job_id] = data # proxy is process-safe
101
104
  cls._publish(job_id, {"event": "added", **data})
102
105
 
106
+ from .job_heartbeat import ensure_started
107
+ ensure_started()
108
+
103
109
  @classmethod
104
110
  def update_status(cls, job_id: str, status: str,
105
111
  meta_update: Optional[Dict[str, Any]] = None) -> None: