quapp-common 0.0.11.dev5__tar.gz → 0.0.11.dev7__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.11.dev5/quapp_common.egg-info → quapp_common-0.0.11.dev7}/PKG-INFO +35 -19
- quapp_common-0.0.11.dev7/README.md +72 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/pyproject.toml +3 -2
- quapp_common-0.0.11.dev7/quapp_common/async_tasks/async_invocation_task.py +80 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/export_circuit_task.py +21 -15
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/invocation.py +10 -9
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/job_fetcher.py +4 -4
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/job_fetching.py +2 -2
- quapp_common-0.0.11.dev7/quapp_common/component/backend/job_manager.py +302 -0
- quapp_common-0.0.11.dev7/quapp_common/component/callback/update_job_metadata.py +77 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/device/device_selection.py +1 -1
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/invocation_request.py +2 -2
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/job_fetching_request.py +2 -2
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/request.py +4 -2
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/job_response.py +2 -2
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/device/custom_device.py +1 -1
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/device/device.py +1 -1
- quapp_common-0.0.11.dev7/quapp_common/model/invocation.py +54 -0
- quapp_common-0.0.11.dev7/quapp_common/util/http_utils.py +141 -0
- quapp_common-0.0.11.dev7/quapp_common/util/response_utils.py +200 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7/quapp_common.egg-info}/PKG-INFO +35 -19
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/SOURCES.txt +3 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/requires.txt +1 -0
- quapp_common-0.0.11.dev5/README.md +0 -57
- quapp_common-0.0.11.dev5/quapp_common/component/callback/update_job_metadata.py +0 -41
- quapp_common-0.0.11.dev5/quapp_common/util/http_utils.py +0 -93
- quapp_common-0.0.11.dev5/quapp_common/util/response_utils.py +0 -97
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/LICENSE +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/async_task.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/async_tasks/post_processing_task.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/callback/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/device/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/config/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/config/logging_config.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/config/thread_config.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/backend/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/backend/backend_information.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/callback/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/callback/callback_url.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/device/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/device/circuit_running_option.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/promise/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/promise/post_processing_promise.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/promise/promise.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/request/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/authentication.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/data/response/custom_header.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/base_enum.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/http_header.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/invocation_step.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/media_type.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/processing_unit.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/provider_tag.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/sdk.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/status/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/status/job_status.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/status/status_code.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/enum/token_type.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/device_factory.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/handler_factory.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/factory/provider_factory.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/handler/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/handler/handler.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/device/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/provider/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/model/provider/provider.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/util/__init__.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/util/file_utils.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/util/json_parser_utils.py +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/dependency_links.txt +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common.egg-info/top_level.txt +0 -0
- {quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quapp-common
|
|
3
|
-
Version: 0.0.11.
|
|
3
|
+
Version: 0.0.11.dev7
|
|
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)
|
|
@@ -24,6 +24,7 @@ Requires-Dist: requests
|
|
|
24
24
|
Requires-Dist: numpy
|
|
25
25
|
Requires-Dist: matplotlib
|
|
26
26
|
Requires-Dist: pylatexenc
|
|
27
|
+
Requires-Dist: starlette
|
|
27
28
|
Provides-Extra: dev
|
|
28
29
|
Requires-Dist: black; extra == "dev"
|
|
29
30
|
Requires-Dist: bumpver; extra == "dev"
|
|
@@ -42,12 +43,11 @@ Quapp common library supporting Quapp Platform for Quantum Computing.
|
|
|
42
43
|
Quantum Computing by providing common utilities, configurations, and
|
|
43
44
|
abstractions for working with
|
|
44
45
|
quantum providers and devices.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
improving maintainability and clarity.
|
|
46
|
+
Recent improvements add first-class asynchronous job processing with a
|
|
47
|
+
cross-process JobManager,
|
|
48
|
+
background task execution, and standardized result models for immediate client
|
|
49
|
+
responses while work
|
|
50
|
+
continues in the background.
|
|
51
51
|
|
|
52
52
|
## Features
|
|
53
53
|
|
|
@@ -61,6 +61,17 @@ improving maintainability and clarity.
|
|
|
61
61
|
- Enhanced error handling and job metadata update mechanisms.
|
|
62
62
|
- Simplified and cleaner HTTP request/response logging and URL parsing
|
|
63
63
|
utilities.
|
|
64
|
+
- Asynchronous job processing:
|
|
65
|
+
- AsyncInvocationTask to run handlers in a background thread pool and return
|
|
66
|
+
immediate responses.
|
|
67
|
+
- JobManager for cross-process job registry with atomic add/update/get and
|
|
68
|
+
pub-sub updates.
|
|
69
|
+
- Standard Event/Result (Success, Error) models for consistent async
|
|
70
|
+
responses.
|
|
71
|
+
- Scheduler integration via callback URL; local updates are patched to the
|
|
72
|
+
scheduler.
|
|
73
|
+
- Safety: updates to jobs already DONE/FAILED are ignored to prevent
|
|
74
|
+
post-completion mutations.
|
|
64
75
|
|
|
65
76
|
## Installation
|
|
66
77
|
|
|
@@ -70,22 +81,27 @@ Install via pip:
|
|
|
70
81
|
pip install quapp-common
|
|
71
82
|
```
|
|
72
83
|
|
|
84
|
+
Notes:
|
|
85
|
+
|
|
86
|
+
- From version 0.0.11.dev7, `starlette` is a direct dependency to support
|
|
87
|
+
background execution helpers.
|
|
88
|
+
|
|
73
89
|
## Recently Changes Highlights
|
|
74
90
|
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
81
|
-
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
91
|
+
- Version bump to 0.0.11.dev7 and dependency update (add `starlette`).
|
|
92
|
+
- Introduce asynchronous job processing primitives:
|
|
93
|
+
- AsyncInvocationTask for background execution with immediate client
|
|
94
|
+
response.
|
|
95
|
+
- Event and standardized Result models (Success, Error).
|
|
96
|
+
- Introduce JobManager for cross-process job management and update publication.
|
|
97
|
+
- Integrate JobManager into Request to register jobs and carry scheduler
|
|
98
|
+
callback URL.
|
|
99
|
+
- Modularize update_job_metadata with clearer helpers; patch scheduler on local
|
|
100
|
+
state changes.
|
|
101
|
+
- Fix: ignore updates for jobs that are already DONE or FAILED.
|
|
102
|
+
- Improve logging and error handling (use full tracebacks, cleaner logs).
|
|
86
103
|
|
|
87
104
|
---
|
|
88
105
|
|
|
89
106
|
For detailed usage and API references, please refer to the in-code documentation
|
|
90
107
|
or contact the maintainers.
|
|
91
|
-
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# quapp-common
|
|
2
|
+
|
|
3
|
+
Quapp common library supporting Quapp Platform for Quantum Computing.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`quapp-common` is a Python library designed to support the Quapp Platform for
|
|
8
|
+
Quantum Computing by providing common utilities, configurations, and
|
|
9
|
+
abstractions for working with
|
|
10
|
+
quantum providers and devices.
|
|
11
|
+
Recent improvements add first-class asynchronous job processing with a
|
|
12
|
+
cross-process JobManager,
|
|
13
|
+
background task execution, and standardized result models for immediate client
|
|
14
|
+
responses while work
|
|
15
|
+
continues in the background.
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- Provider and device factory for quantum computing platforms.
|
|
20
|
+
- Logging and configuration utilities with improved and detailed log messages.
|
|
21
|
+
- Support for AWS Braket, OQC Cloud, Qiskit, PennyLane, DWave Ocean, and Quapp
|
|
22
|
+
quantum simulators.
|
|
23
|
+
- Refactored classes and utilities to remove tenant-specific request, response,
|
|
24
|
+
and promise classes.
|
|
25
|
+
- Standardized naming by renaming `ProjectHeader` to `CustomHeader`.
|
|
26
|
+
- Enhanced error handling and job metadata update mechanisms.
|
|
27
|
+
- Simplified and cleaner HTTP request/response logging and URL parsing
|
|
28
|
+
utilities.
|
|
29
|
+
- Asynchronous job processing:
|
|
30
|
+
- AsyncInvocationTask to run handlers in a background thread pool and return
|
|
31
|
+
immediate responses.
|
|
32
|
+
- JobManager for cross-process job registry with atomic add/update/get and
|
|
33
|
+
pub-sub updates.
|
|
34
|
+
- Standard Event/Result (Success, Error) models for consistent async
|
|
35
|
+
responses.
|
|
36
|
+
- Scheduler integration via callback URL; local updates are patched to the
|
|
37
|
+
scheduler.
|
|
38
|
+
- Safety: updates to jobs already DONE/FAILED are ignored to prevent
|
|
39
|
+
post-completion mutations.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
Install via pip:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install quapp-common
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Notes:
|
|
50
|
+
|
|
51
|
+
- From version 0.0.11.dev7, `starlette` is a direct dependency to support
|
|
52
|
+
background execution helpers.
|
|
53
|
+
|
|
54
|
+
## Recently Changes Highlights
|
|
55
|
+
|
|
56
|
+
- Version bump to 0.0.11.dev7 and dependency update (add `starlette`).
|
|
57
|
+
- Introduce asynchronous job processing primitives:
|
|
58
|
+
- AsyncInvocationTask for background execution with immediate client
|
|
59
|
+
response.
|
|
60
|
+
- Event and standardized Result models (Success, Error).
|
|
61
|
+
- Introduce JobManager for cross-process job management and update publication.
|
|
62
|
+
- Integrate JobManager into Request to register jobs and carry scheduler
|
|
63
|
+
callback URL.
|
|
64
|
+
- Modularize update_job_metadata with clearer helpers; patch scheduler on local
|
|
65
|
+
state changes.
|
|
66
|
+
- Fix: ignore updates for jobs that are already DONE or FAILED.
|
|
67
|
+
- Improve logging and error handling (use full tracebacks, cleaner logs).
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
For detailed usage and API references, please refer to the in-code documentation
|
|
72
|
+
or contact the maintainers.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "quapp-common"
|
|
7
|
-
version = "0.0.11.
|
|
7
|
+
version = "0.0.11.dev7"
|
|
8
8
|
description = "Quapp common library supporting Quapp Platform for Quantum Computing"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "CITYNOW Co. Ltd. ", email = "corp@citynow.vn" }]
|
|
@@ -20,7 +20,8 @@ dependencies = [
|
|
|
20
20
|
"requests",
|
|
21
21
|
"numpy",
|
|
22
22
|
"matplotlib",
|
|
23
|
-
"pylatexenc"
|
|
23
|
+
"pylatexenc",
|
|
24
|
+
"starlette"
|
|
24
25
|
]
|
|
25
26
|
requires-python = ">=3.7"
|
|
26
27
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# async_invocation_task.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd. All rights reserved.
|
|
4
|
+
import asyncio
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from starlette.concurrency import run_in_threadpool
|
|
8
|
+
from starlette.responses import JSONResponse
|
|
9
|
+
|
|
10
|
+
from ..async_tasks.async_task import AsyncTask
|
|
11
|
+
from ..component.backend.job_manager import JobManager
|
|
12
|
+
from ..config.logging_config import logger
|
|
13
|
+
from ..factory.handler_factory import HandlerFactory
|
|
14
|
+
from ..model.invocation import Event, Error, Success
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AsyncInvocationTask(AsyncTask):
|
|
18
|
+
"""
|
|
19
|
+
Handles asynchronous invocation tasks, designed to process events with
|
|
20
|
+
specific handlers and generate immediate responses.
|
|
21
|
+
|
|
22
|
+
The class is aimed at enabling tasks to be processed asynchronously, involving
|
|
23
|
+
a handler factory and functions for event processing and post-processing. It
|
|
24
|
+
executes operations in a background thread pool to ensure quick response to
|
|
25
|
+
clients, allowing them to poll for job status updates. Its primary purpose is
|
|
26
|
+
to facilitate efficient asynchronous processing of jobs without blocking the
|
|
27
|
+
main application flow.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
handler_factory: Factory instance that produces job handlers.
|
|
31
|
+
event: Event to be processed by the created handler.
|
|
32
|
+
processing_fn: Function to be executed during the job processing stage.
|
|
33
|
+
post_processing_fn: Function to be executed post-job processing.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, handler_factory: HandlerFactory, event: Event,
|
|
37
|
+
processing_fn, post_processing_fn):
|
|
38
|
+
super().__init__()
|
|
39
|
+
self.handler_factory = handler_factory
|
|
40
|
+
self.event = event
|
|
41
|
+
self.processing_fn = processing_fn
|
|
42
|
+
self.post_processing_fn = post_processing_fn
|
|
43
|
+
|
|
44
|
+
def do(self) -> JSONResponse:
|
|
45
|
+
"""
|
|
46
|
+
Handles executing a job asynchronously and provides an immediate response with the job's ID and
|
|
47
|
+
status. Logging is configured dynamically based on the provided job ID.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
JSONResponse: A response object with the status and job ID if the job submission succeeds,
|
|
51
|
+
or an error message if there is an issue.
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
Exception: If any error occurs during job processing, it is logged, and an appropriate error
|
|
55
|
+
response is returned.
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
job_id = self.event.json().get('jobId')
|
|
59
|
+
if job_id is None:
|
|
60
|
+
raise Exception("Job ID is missing from event")
|
|
61
|
+
logger.add(sink=sys.stderr,
|
|
62
|
+
format="[ConsoleJobLog][" + job_id + "] " + "{level} : {time} : {message}: {process}",
|
|
63
|
+
level='DEBUG')
|
|
64
|
+
|
|
65
|
+
# Define the blocking work
|
|
66
|
+
def _run_handle():
|
|
67
|
+
return self.handler_factory.create_handler(self.event,
|
|
68
|
+
self.processing_fn,
|
|
69
|
+
self.post_processing_fn).handle()
|
|
70
|
+
|
|
71
|
+
# Run in the background threadpool so this request can return immediately
|
|
72
|
+
asyncio.create_task(run_in_threadpool(_run_handle))
|
|
73
|
+
|
|
74
|
+
# Respond immediately so clients can poll GET /jobs/{job_id}
|
|
75
|
+
return JSONResponse(status_code=200, content=Success(
|
|
76
|
+
JobManager.get_job(job_id)).serialize())
|
|
77
|
+
except Exception as exception:
|
|
78
|
+
logger.exception(f"An error occurred: {exception}")
|
|
79
|
+
return JSONResponse(status_code=400,
|
|
80
|
+
content=Error(exception).serialize())
|
|
@@ -11,6 +11,7 @@ from .async_task import AsyncTask
|
|
|
11
11
|
from ..config.logging_config import job_logger
|
|
12
12
|
from ..data.async_task.circuit_export.backend_holder import BackendDataHolder
|
|
13
13
|
from ..data.async_task.circuit_export.circuit_holder import CircuitDataHolder
|
|
14
|
+
from ..data.response.custom_header import CustomHeader
|
|
14
15
|
from ..enum.media_type import MediaType
|
|
15
16
|
from ..util.file_utils import FileUtils
|
|
16
17
|
from ..util.http_utils import create_bearer_header, get_job_id_from_url
|
|
@@ -20,8 +21,11 @@ class CircuitExportTask(AsyncTask):
|
|
|
20
21
|
MAX_CIRCUIT_IMAGE_SIZE = 5 * (1024 ** 2)
|
|
21
22
|
|
|
22
23
|
def __init__(self, circuit_data_holder: CircuitDataHolder,
|
|
23
|
-
backend_data_holder: BackendDataHolder
|
|
24
|
+
backend_data_holder: BackendDataHolder,
|
|
25
|
+
project_header: CustomHeader, workspace_header: CustomHeader):
|
|
24
26
|
super().__init__()
|
|
27
|
+
self.project_header = project_header
|
|
28
|
+
self.workspace_header = workspace_header
|
|
25
29
|
self.circuit_data_holder = circuit_data_holder
|
|
26
30
|
self.backend_data_holder = backend_data_holder
|
|
27
31
|
self.logger = job_logger(
|
|
@@ -43,8 +47,8 @@ class CircuitExportTask(AsyncTask):
|
|
|
43
47
|
self.logger.debug('Converting circuit to SVG')
|
|
44
48
|
figure_buffer = self.__convert()
|
|
45
49
|
except Exception as e:
|
|
46
|
-
self.logger.
|
|
47
|
-
|
|
50
|
+
self.logger.exception(f"Error converting circuit to SVG: {e}",
|
|
51
|
+
exc_info=True)
|
|
48
52
|
return
|
|
49
53
|
|
|
50
54
|
try:
|
|
@@ -54,7 +58,7 @@ class CircuitExportTask(AsyncTask):
|
|
|
54
58
|
self.logger.debug(f"Content type: {content_type}")
|
|
55
59
|
self.logger.debug(f"Buffer size: {len(io_buffer_value)} bytes")
|
|
56
60
|
except Exception as e:
|
|
57
|
-
self.logger.
|
|
61
|
+
self.logger.exception(
|
|
58
62
|
f"Error determining if circuit SVG should be zipped: {e}",
|
|
59
63
|
exc_info=True)
|
|
60
64
|
return
|
|
@@ -64,11 +68,12 @@ class CircuitExportTask(AsyncTask):
|
|
|
64
68
|
self.__send(io_buffer_value=io_buffer_value,
|
|
65
69
|
content_type=content_type)
|
|
66
70
|
self.logger.debug("Circuit sent to backend successfully.")
|
|
71
|
+
return
|
|
67
72
|
except Exception as e:
|
|
68
|
-
self.logger.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
self.logger.exception(
|
|
74
|
+
f"Error sending exported circuit to backend: {e}",
|
|
75
|
+
exc_info=True)
|
|
76
|
+
return
|
|
72
77
|
|
|
73
78
|
def __convert(self):
|
|
74
79
|
"""
|
|
@@ -81,8 +86,8 @@ class CircuitExportTask(AsyncTask):
|
|
|
81
86
|
try:
|
|
82
87
|
circuit_figure = transpiled_circuit.draw(output='mpl', fold=-1)
|
|
83
88
|
except Exception as exception:
|
|
84
|
-
self.logger.
|
|
85
|
-
|
|
89
|
+
self.logger.exception(f"Error drawing circuit: {exception}",
|
|
90
|
+
exc_info=True)
|
|
86
91
|
raise exception
|
|
87
92
|
|
|
88
93
|
self.logger.debug("Converting circuit figure to SVG file...")
|
|
@@ -93,7 +98,7 @@ class CircuitExportTask(AsyncTask):
|
|
|
93
98
|
self.logger.debug(
|
|
94
99
|
f"SVG export complete. Size: {figure_buffer.getbuffer().nbytes} bytes")
|
|
95
100
|
except Exception as exception:
|
|
96
|
-
self.logger.
|
|
101
|
+
self.logger.exception(
|
|
97
102
|
f"Error saving circuit figure to SVG: {exception}",
|
|
98
103
|
exc_info=True)
|
|
99
104
|
raise exception
|
|
@@ -135,16 +140,17 @@ class CircuitExportTask(AsyncTask):
|
|
|
135
140
|
|
|
136
141
|
try:
|
|
137
142
|
response = requests.post(url=url, headers=create_bearer_header(
|
|
138
|
-
self.backend_data_holder.user_token
|
|
143
|
+
self.backend_data_holder.user_token, self.project_header,
|
|
144
|
+
self.workspace_header), files=payload)
|
|
139
145
|
except Exception as exception:
|
|
140
|
-
self.logger.
|
|
141
|
-
|
|
146
|
+
self.logger.exception(f"HTTP request failed: {exception}",
|
|
147
|
+
exc_info=True)
|
|
142
148
|
raise
|
|
143
149
|
|
|
144
150
|
if response.ok:
|
|
145
151
|
self.logger.info("Request sent to QuaO backend successfully.")
|
|
146
152
|
else:
|
|
147
|
-
self.logger.
|
|
153
|
+
self.logger.exception(
|
|
148
154
|
f"Sending request to QuaO backend failed with status {response.status_code}! Response: {response.content}")
|
|
149
155
|
|
|
150
156
|
self.logger.debug("HTTP request complete.")
|
{quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/invocation.py
RENAMED
|
@@ -77,9 +77,9 @@ class Invocation(ABC):
|
|
|
77
77
|
circuit = self.__prepare_circuit(circuit_preparation_fn)
|
|
78
78
|
|
|
79
79
|
if circuit is None:
|
|
80
|
-
self.logger.
|
|
80
|
+
self.logger.exception(
|
|
81
81
|
"Circuit preparation failed, returning None from pre-execute")
|
|
82
|
-
|
|
82
|
+
raise ValueError("Circuit preparation failed")
|
|
83
83
|
|
|
84
84
|
try:
|
|
85
85
|
self.logger.debug("Preparing backend data")
|
|
@@ -88,12 +88,13 @@ class Invocation(ABC):
|
|
|
88
88
|
f"Backend data prepared: device {self.backend_information.device_name}, provider {self.backend_information.provider_tag.value}")
|
|
89
89
|
|
|
90
90
|
except Exception as exception:
|
|
91
|
-
self.logger.
|
|
92
|
-
|
|
91
|
+
self.logger.exception(
|
|
92
|
+
f"Error when prepare backend data: {exception}",
|
|
93
|
+
exc_info=True)
|
|
93
94
|
|
|
94
95
|
job_response = build_error_job_response(exception,
|
|
95
96
|
message='Error when prepare backend data')
|
|
96
|
-
|
|
97
|
+
job_response.authentication = self.authentication
|
|
97
98
|
update_job_metadata(job_response, self.callback_dict.get(
|
|
98
99
|
InvocationStep.PREPARATION).on_error)
|
|
99
100
|
|
|
@@ -113,7 +114,7 @@ class Invocation(ABC):
|
|
|
113
114
|
|
|
114
115
|
try:
|
|
115
116
|
if self.backend_information is None:
|
|
116
|
-
self.logger.
|
|
117
|
+
self.logger.exception(
|
|
117
118
|
"Backend information is None before execution")
|
|
118
119
|
raise ValueError("Backend is not found")
|
|
119
120
|
|
|
@@ -129,7 +130,7 @@ class Invocation(ABC):
|
|
|
129
130
|
device = self._create_device(provider)
|
|
130
131
|
|
|
131
132
|
except Exception as exception:
|
|
132
|
-
self.logger.
|
|
133
|
+
self.logger.exception(
|
|
133
134
|
f"Exception when create provider or device: {exception}",
|
|
134
135
|
exc_info=True)
|
|
135
136
|
|
|
@@ -182,8 +183,8 @@ class Invocation(ABC):
|
|
|
182
183
|
return circuit
|
|
183
184
|
|
|
184
185
|
except Exception as exception:
|
|
185
|
-
self.logger.
|
|
186
|
-
|
|
186
|
+
self.logger.exception(f'Error when prepare circuit: {exception}',
|
|
187
|
+
exc_info=True)
|
|
187
188
|
|
|
188
189
|
job_response = build_error_job_response(exception, job_response,
|
|
189
190
|
message='Error when prepare circuit')
|
{quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/job_fetcher.py
RENAMED
|
@@ -116,7 +116,7 @@ class JobFetcher(ABC):
|
|
|
116
116
|
update_job_metadata(job_response, self.callback_urls[
|
|
117
117
|
InvocationStep.EXECUTION].on_done)
|
|
118
118
|
elif job_status == JobStatus.ERROR.value:
|
|
119
|
-
self.logger.
|
|
119
|
+
self.logger.exception("Job resulted in error, handling failure")
|
|
120
120
|
|
|
121
121
|
self._handle_failed_job(original_job_result, job_response)
|
|
122
122
|
update_job_metadata(job_response, self.callback_urls[
|
|
@@ -127,7 +127,7 @@ class JobFetcher(ABC):
|
|
|
127
127
|
job_response.status_code = StatusCode.POLLING
|
|
128
128
|
|
|
129
129
|
except Exception as exception:
|
|
130
|
-
self.logger.
|
|
130
|
+
self.logger.exception(
|
|
131
131
|
f"Exception during job fetch for provider_job_id {self.provider_job_id}: {exception}",
|
|
132
132
|
exc_info=True)
|
|
133
133
|
|
|
@@ -151,7 +151,7 @@ class JobFetcher(ABC):
|
|
|
151
151
|
def _handle_failed_job(self, original_job_result,
|
|
152
152
|
job_response: JobResponse):
|
|
153
153
|
"""Handles the job result when the job has encountered an error."""
|
|
154
|
-
self.logger.
|
|
154
|
+
self.logger.exception("Parsing job result from failed job")
|
|
155
155
|
job_response.job_result = parse(original_job_result)
|
|
156
156
|
|
|
157
157
|
def _process_job_result(self, original_job_result,
|
|
@@ -205,7 +205,7 @@ class JobFetcher(ABC):
|
|
|
205
205
|
return job_response
|
|
206
206
|
|
|
207
207
|
except Exception as exception:
|
|
208
|
-
self.logger.
|
|
208
|
+
self.logger.exception(f"Exception during analysis: {exception}",
|
|
209
209
|
exc_info=True)
|
|
210
210
|
from ...util.response_utils import build_error_job_response
|
|
211
211
|
job_response = build_error_job_response(exception, job_response,
|
{quapp_common-0.0.11.dev5 → quapp_common-0.0.11.dev7}/quapp_common/component/backend/job_fetching.py
RENAMED
|
@@ -75,7 +75,7 @@ class JobFetching(ABC):
|
|
|
75
75
|
InvocationStep.EXECUTION).on_done)
|
|
76
76
|
|
|
77
77
|
elif JobStatus.ERROR.value.__eq__(job_response.job_status):
|
|
78
|
-
self.logger.
|
|
78
|
+
self.logger.exception("Job resulted in error, handling failure")
|
|
79
79
|
|
|
80
80
|
job_response.job_result = parse(original_job_result)
|
|
81
81
|
|
|
@@ -152,7 +152,7 @@ class JobFetching(ABC):
|
|
|
152
152
|
return job_response
|
|
153
153
|
|
|
154
154
|
except Exception as exception:
|
|
155
|
-
self.logger.
|
|
155
|
+
self.logger.exception(
|
|
156
156
|
"Exception when analyst job result with provider_job_id {0}: {1}".format(
|
|
157
157
|
self.provider_job_id, str(exception)))
|
|
158
158
|
|