Repository: Qiskit/qiskit-ibm-runtime
Pull request #432 (2022-07-20 00:42:33)

Raise RuntimeJobMaxTimeoutError if a program fails for running too long
<!--
⚠️ The pull request title should be short detailed and understandable for all.
⚠️ Also, please add a release note file using reno if the change needs to be
  documented in the release notes.
⚠️ If your pull request fixes an open issue, please link to the issue.

✅ I have added the tests to cover my changes.
✅ I have updated the documentation accordingly.
✅ I have read the CONTRIBUTING document.
-->

### Summary

Raise RuntimeJobMaxTimeoutError if a program fails for running too long, so that programs can handle it.

Changes to handle an expired session error will be in a separate PR.

### Details and comments
Fixes #



CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/Qiskit/qiskit-ibm-runtime?pullRequest=432) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/Qiskit/qiskit-ibm-runtime?pullRequest=432) before we can accept your contribution.<br/><hr/>**Jane Kwon** seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please [add the email address used for this commit to your account](https://help.github.com/articles/why-are-my-commits-linked-to-the-wrong-user/#commits-are-not-linked-to-any-user).<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/Qiskit/qiskit-ibm-runtime?pullRequest=432) it.</sub>
coveralls: ## Pull Request Test Coverage Report for [Build 2701507600](https://coveralls.io/builds/51004675)

* **3** of **3**   **(100.0%)**  changed or added relevant lines in **1** file are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage increased (+**0.02%**) to **62.391%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/51004675/badge)](https://coveralls.io/builds/51004675) |
| :-- | --: |
| Change from base [Build 2700224375](https://coveralls.io/builds/50998798): |  0.02% |
| Covered Lines: | 2860 |
| Relevant Lines: | 4584 |

---
##### 💛  - [Coveralls](https://coveralls.io)

kwoane: @rathishcholarajan  The name of this error made sense to me because the job timed out during its execution. I am open to suggestions for other names.
rathishcholarajan: > @rathishcholarajan The name of this error made sense to me because the job timed out during its execution. I am open to suggestions for other names.

@kwoane Maybe something like ``RuntimeJobMaxTimeoutError``.

Patch:
diff --git a/qiskit_ibm_runtime/exceptions.py b/qiskit_ibm_runtime/exceptions.py
index b71ee6b6..9137b430 100644
--- a/qiskit_ibm_runtime/exceptions.py
+++ b/qiskit_ibm_runtime/exceptions.py
@@ -91,3 +91,9 @@ class RuntimeJobTimeoutError(IBMRuntimeError):
     """Error raised when waiting for job times out."""
 
     pass
+
+
+class RuntimeJobMaxTimeoutError(IBMRuntimeError):
+    """Error raised when a job times out."""
+
+    pass
diff --git a/qiskit_ibm_runtime/runtime_job.py b/qiskit_ibm_runtime/runtime_job.py
index 10a83716..f327c66f 100644
--- a/qiskit_ibm_runtime/runtime_job.py
+++ b/qiskit_ibm_runtime/runtime_job.py
@@ -30,6 +30,7 @@ from .exceptions import (
     RuntimeInvalidStateError,
     IBMRuntimeError,
     RuntimeJobTimeoutError,
+    RuntimeJobMaxTimeoutError,
 )
 from .program.result_decoder import ResultDecoder
 from .api.clients import RuntimeClient, RuntimeWebsocketClient, WebsocketClientCloseCode
@@ -174,14 +175,17 @@ class RuntimeJob:
 
         Raises:
             RuntimeJobFailureError: If the job failed.
-            RuntimeJobTimeoutError: If the job does not complete within given timeout.
+            RuntimeJobMaxTimeoutError: If the job does not complete within given timeout.
         """
         _decoder = decoder or self._result_decoder
         if self._results is None or (_decoder != self._result_decoder):
             self.wait_for_final_state(timeout=timeout)
             if self._status == JobStatus.ERROR:
+                error_message = self.error_message()
+                if self._reason == "RAN TOO LONG":
+                    raise RuntimeJobMaxTimeoutError(error_message)
                 raise RuntimeJobFailureError(
-                    f"Unable to retrieve job result. " f"{self.error_message()}"
+                    f"Unable to retrieve job result. " f"{error_message}"
                 )
             result_raw = self._api_client.job_results(job_id=self.job_id)
             self._results = _decoder.decode(result_raw) if result_raw else None
diff --git a/releasenotes/notes/exception-when-program-runs-too-long-cf80743eda83d601.yaml b/releasenotes/notes/exception-when-program-runs-too-long-cf80743eda83d601.yaml
new file mode 100644
index 00000000..20f62d65
--- /dev/null
+++ b/releasenotes/notes/exception-when-program-runs-too-long-cf80743eda83d601.yaml
@@ -0,0 +1,4 @@
+---
+upgrade:
+  - |
+    Raise ``RuntimeJobMaxTimeoutError`` when a job runs for too long so that it can be handled appropriately by programs.
\ No newline at end of file


Test patch:
diff --git a/test/integration/test_job.py b/test/integration/test_job.py
index e4979c94..bb2bd401 100644
--- a/test/integration/test_job.py
+++ b/test/integration/test_job.py
@@ -24,6 +24,7 @@ from qiskit_ibm_runtime.exceptions import (
     RuntimeJobFailureError,
     RuntimeInvalidStateError,
     RuntimeJobNotFound,
+    RuntimeJobMaxTimeoutError,
 )
 from ..ibm_test_case import IBMIntegrationJobTestCase
 from ..decorators import run_integration_test
@@ -115,7 +116,7 @@ class TestIntegrationJob(IBMIntegrationJobTestCase):
             ),
             job.error_message(),
         )
-        with self.assertRaises(RuntimeJobFailureError):
+        with self.assertRaises(RuntimeJobMaxTimeoutError):
             job.result()
 
     @run_integration_test
diff --git a/test/unit/test_jobs.py b/test/unit/test_jobs.py
index b949cc06..5a9c45e0 100644
--- a/test/unit/test_jobs.py
+++ b/test/unit/test_jobs.py
@@ -23,6 +23,7 @@ from qiskit_ibm_runtime.constants import API_TO_JOB_ERROR_MESSAGE
 from qiskit_ibm_runtime.exceptions import (
     RuntimeJobFailureError,
     RuntimeJobNotFound,
+    RuntimeJobMaxTimeoutError,
     RuntimeProgramNotFound,
     IBMInputValueError,
 )
@@ -192,7 +193,7 @@ class TestRuntimeJob(IBMTestCase):
                 ),
                 job.error_message(),
             )
-            with self.assertRaises(RuntimeJobFailureError):
+            with self.assertRaises(RuntimeJobMaxTimeoutError):
                 job.result()
 
     @run_quantum_and_cloud_fake