Repository: Qiskit/qiskit-ibm-runtime
Pull request #692 (2023-02-01 16:31:27)

add session_time param

Added session_time param to `Runtime session` and `program_run`, `session_time `param can be used to specify length of session.


ChitsimranGill: 


> Can you add a release note? I think it would helpful for users to see how `session_time` can be used
> 
> ```
> reno new session-time-param
> ```

Added a release note to` releasenotes/notes/0.9`

Patch:
diff --git a/qiskit_ibm_runtime/api/clients/runtime.py b/qiskit_ibm_runtime/api/clients/runtime.py
index bb35b8c6..b8830680 100644
--- a/qiskit_ibm_runtime/api/clients/runtime.py
+++ b/qiskit_ibm_runtime/api/clients/runtime.py
@@ -125,6 +125,7 @@ class RuntimeClient(BaseBackendClient):
         job_tags: Optional[List[str]] = None,
         max_execution_time: Optional[int] = None,
         start_session: Optional[bool] = False,
+        session_time: Optional[int] = None,
     ) -> Dict:
         """Run the specified program.
 
@@ -139,6 +140,7 @@ class RuntimeClient(BaseBackendClient):
             job_tags: Tags to be assigned to the job.
             max_execution_time: Maximum execution time in seconds.
             start_session: Set to True to explicitly start a runtime session. Defaults to False.
+            session_time: Length of session in seconds.
 
         Returns:
             JSON response.
@@ -157,6 +159,7 @@ class RuntimeClient(BaseBackendClient):
             job_tags=job_tags,
             max_execution_time=max_execution_time,
             start_session=start_session,
+            session_time=session_time,
             **hgp_dict
         )
 
diff --git a/qiskit_ibm_runtime/api/rest/runtime.py b/qiskit_ibm_runtime/api/rest/runtime.py
index f089b167..44679891 100644
--- a/qiskit_ibm_runtime/api/rest/runtime.py
+++ b/qiskit_ibm_runtime/api/rest/runtime.py
@@ -137,6 +137,7 @@ class Runtime(RestAdapterBase):
         job_tags: Optional[List[str]] = None,
         max_execution_time: Optional[int] = None,
         start_session: Optional[bool] = False,
+        session_time: Optional[int] = None,
     ) -> Dict:
         """Execute the program.
 
@@ -153,6 +154,7 @@ class Runtime(RestAdapterBase):
             job_tags: Tags to be assigned to the job.
             max_execution_time: Maximum execution time in seconds.
             start_session: Set to True to explicitly start a runtime session. Defaults to False.
+            session_time: Length of session in seconds.
 
         Returns:
             JSON response.
@@ -176,6 +178,7 @@ class Runtime(RestAdapterBase):
             payload["cost"] = max_execution_time
         if start_session:
             payload["start_session"] = start_session
+            payload["session_time"] = session_time
         if all([hub, group, project]):
             payload["hub"] = hub
             payload["group"] = group
diff --git a/qiskit_ibm_runtime/qiskit_runtime_service.py b/qiskit_ibm_runtime/qiskit_runtime_service.py
index 968553ad..7030e63e 100644
--- a/qiskit_ibm_runtime/qiskit_runtime_service.py
+++ b/qiskit_ibm_runtime/qiskit_runtime_service.py
@@ -1007,6 +1007,7 @@ class QiskitRuntimeService(Provider):
                 job_tags=qrt_options.job_tags,
                 max_execution_time=qrt_options.max_execution_time,
                 start_session=start_session,
+                session_time=qrt_options.session_time,
             )
         except RequestsApiError as ex:
             if ex.status_code == 404:
diff --git a/qiskit_ibm_runtime/runtime_options.py b/qiskit_ibm_runtime/runtime_options.py
index c3381eaa..13030939 100644
--- a/qiskit_ibm_runtime/runtime_options.py
+++ b/qiskit_ibm_runtime/runtime_options.py
@@ -34,6 +34,7 @@ class RuntimeOptions:
     instance: Optional[str] = None
     job_tags: Optional[List[str]] = None
     max_execution_time: Optional[int] = None
+    session_time: Optional[int] = None
 
     @deprecate_arguments({"backend_name": "backend"})
     def __init__(
@@ -44,6 +45,7 @@ class RuntimeOptions:
         instance: Optional[str] = None,
         job_tags: Optional[List[str]] = None,
         max_execution_time: Optional[int] = None,
+        session_time: Optional[int] = None,
     ) -> None:
         """RuntimeOptions constructor.
 
@@ -62,6 +64,7 @@ class RuntimeOptions:
                 as a filter in the :meth:`jobs()` function call.
             max_execution_time: Maximum execution time in seconds. If
                 a job exceeds this time limit, it is forcibly cancelled.
+            session_time: Length of session in seconds.
         """
         self.backend = backend
         self.image = image
@@ -69,6 +72,7 @@ class RuntimeOptions:
         self.instance = instance
         self.job_tags = job_tags
         self.max_execution_time = max_execution_time
+        self.session_time = session_time
 
     def validate(self, channel: str) -> None:
         """Validate options.
diff --git a/qiskit_ibm_runtime/runtime_session.py b/qiskit_ibm_runtime/runtime_session.py
index 91409ed7..1fe337c9 100644
--- a/qiskit_ibm_runtime/runtime_session.py
+++ b/qiskit_ibm_runtime/runtime_session.py
@@ -63,7 +63,7 @@ class RuntimeSession:
         if isinstance(options, RuntimeOptions):
             self._options = asdict(options)
         if max_time:
-            self._options["max_execution_time"] = max_time
+            self._options["session_time"] = max_time
         self._initial_inputs = inputs
         self._initial_job: Optional[RuntimeJob] = None
         self._job: Optional[RuntimeJob] = None
@@ -86,7 +86,7 @@ class RuntimeSession:
             self._session_id = self._job.job_id()
         else:
             self._start_session = False
-            self._options["max_execution_time"] = None
+            self._options["session_time"] = None
             self._job = self._run(inputs=inputs)
 
     def _run(self, inputs: Union[Dict, ParameterNamespace]) -> RuntimeJob:
diff --git a/qiskit_ibm_runtime/session.py b/qiskit_ibm_runtime/session.py
index a58a32bc..eebc1982 100644
--- a/qiskit_ibm_runtime/session.py
+++ b/qiskit_ibm_runtime/session.py
@@ -171,7 +171,7 @@ class Session:
         if not self._session_id:
             # TODO: What happens if session max time != first job max time?
             # Use session max time if this is first job.
-            options["max_execution_time"] = self._max_time
+            options["session_time"] = self._max_time
 
         job = self._service.run(
             program_id=program_id,
diff --git a/releasenotes/notes/0.9/session-time-param-b02d1513d9754b52.yaml b/releasenotes/notes/0.9/session-time-param-b02d1513d9754b52.yaml
new file mode 100644
index 00000000..db923b51
--- /dev/null
+++ b/releasenotes/notes/0.9/session-time-param-b02d1513d9754b52.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    Added a new argument called ``session_time`` to the program_run method and 
+    :class:`qiskit_ibm_runtime.RuntimeOptions`. Now values entered by the user for session ``max_time`` 
+    will be sent to the server side as ``session_time``. This allows users to specify different values 
+    for session ``max_time`` and ``max_execution_time``.
\ No newline at end of file


Test patch:
diff --git a/test/program.py b/test/program.py
index e76d7cf0..d5aea443 100644
--- a/test/program.py
+++ b/test/program.py
@@ -93,6 +93,7 @@ def run_program(
         "job_tags": job_tags,
         "max_execution_time": max_execution_time,
         "instance": instance,
+        "session_time": None,
     }
     if final_status is not None:
         service._api_client.set_final_status(final_status)
diff --git a/test/unit/mock/fake_runtime_client.py b/test/unit/mock/fake_runtime_client.py
index e1de822e..f99568ab 100644
--- a/test/unit/mock/fake_runtime_client.py
+++ b/test/unit/mock/fake_runtime_client.py
@@ -275,6 +275,7 @@ class BaseFakeRuntimeClient:
             "backend_client", BaseFakeAccountClient()
         )
         self._channel = test_options.get("channel", "ibm_quantum")
+        self.session_time = 0
 
     def set_job_classes(self, classes):
         """Set job classes to use."""
@@ -367,6 +368,7 @@ class BaseFakeRuntimeClient:
         job_tags: Optional[List[str]] = None,
         max_execution_time: Optional[int] = None,
         start_session: Optional[bool] = None,
+        session_time: Optional[int] = None,
     ) -> Dict[str, Any]:
         """Run the specified program."""
         _ = self._get_program(program_id)
@@ -404,6 +406,7 @@ class BaseFakeRuntimeClient:
             start_session=start_session,
             **self._job_kwargs,
         )
+        self.session_time = session_time
         self._jobs[job_id] = job
         return {"id": job_id, "backend": backend_name}
 
diff --git a/test/unit/test_session.py b/test/unit/test_session.py
index 7c34ba79..4b81f698 100644
--- a/test/unit/test_session.py
+++ b/test/unit/test_session.py
@@ -104,6 +104,7 @@ class TestSession(IBMTestCase):
             _, kwargs = service.run.call_args
             self.assertEqual(kwargs["program_id"], program_id)
             self.assertDictEqual(kwargs["options"], {"backend": backend, **options})
+            self.assertDictContainsSubset({"session_time": 42}, kwargs["options"])
             self.assertDictEqual(kwargs["inputs"], inputs)
             self.assertEqual(kwargs["session_id"], session_ids[idx])
             self.assertEqual(kwargs["start_session"], start_sessions[idx])