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.
- {quapp_common-0.0.13.dev6/quapp_common.egg-info → quapp_common-0.0.13.dev8}/PKG-INFO +1 -1
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/pyproject.toml +41 -41
- quapp_common-0.0.13.dev8/quapp_common/component/backend/job_heartbeat.py +83 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/job_manager.py +6 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/circuit_adapter.py +286 -286
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/dispatcher.py +4 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/language.py +1 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8/quapp_common.egg-info}/PKG-INFO +1 -1
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/SOURCES.txt +3 -0
- quapp_common-0.0.13.dev8/tests/test_job_heartbeat.py +115 -0
- quapp_common-0.0.13.dev8/tests/test_language_dispatcher.py +20 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/LICENSE +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/README.md +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/async_invocation_task.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/async_task.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/export_circuit_task.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/async_tasks/post_processing_task.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/invocation.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/job_fetcher.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/job_fetching.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/bridge.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/callback/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/callback/update_job_metadata.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/device/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/device/device_selection.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/result_serializer.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/config/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/config/logging_config.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/config/thread_config.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/backend/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/backend/backend_information.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/callback/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/callback/callback_url.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/device/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/device/circuit_running_option.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/promise/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/promise/post_processing_promise.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/promise/promise.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/invocation_request.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/job_fetching_request.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/request/request.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/authentication.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/custom_header.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/data/response/job_response.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/base_enum.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/http_header.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/invocation_step.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/media_type.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/processing_unit.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/provider_tag.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/sdk.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/status/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/status/job_status.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/status/status_code.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/enum/token_type.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/device_factory.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/handler_factory.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/factory/provider_factory.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/handler/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/handler/handler.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/device/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/device/custom_device.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/device/device.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/invocation.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/provider/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/model/provider/provider.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/__init__.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/file_utils.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/http_utils.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/json_parser_utils.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/util/response_utils.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/dependency_links.txt +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/requires.txt +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common.egg-info/top_level.txt +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/setup.cfg +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/tests/test_circuit_adapter.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/tests/test_json_parser_utils.py +0 -0
- {quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/tests/test_result_serializer.py +0 -0
|
@@ -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.
|
|
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
|
{quapp_common-0.0.13.dev6 → quapp_common-0.0.13.dev8}/quapp_common/component/backend/job_manager.py
RENAMED
|
@@ -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:
|