Skip to content

QJob into JobV1 - #27

Open
JooNiv wants to merge 3 commits into
It4innovations:mainfrom
JooNiv:QJob-into-JobV1
Open

QJob into JobV1#27
JooNiv wants to merge 3 commits into
It4innovations:mainfrom
JooNiv:QJob-into-JobV1

Conversation

@JooNiv

@JooNiv JooNiv commented Aug 21, 2026

Copy link
Copy Markdown

QJob is now a Qiskit JobV1

closes #28

Why

QBackendIQM subclasses IQMBackend, so consumers treat the return value of run() as a
qiskit.providers.JobV1. QJob was a plain class with job_id as an int attribute and
status() returning a string. That made job.job_id() raise TypeError and made every
JobStatus based poll loop never terminate, silently. It broke e.gfiqci-ems and would break
any other Qiskit facing consumer or package trying to integrate with Qiskit or IQM software stack.

What changed

QJob derives from JobV1. status() returns a JobStatus, and submit() and cancel()
were added, so done(), cancelled(), in_final_state() and wait_for_final_state() all
work. HEAppE_QISKIT_STATUS_MAPPING holds JobStatus members now. WAITING still maps to
RUNNING rather than QUEUED, which is left as a separate change.

job_id stays an int through a callable int subclass, so job.job_id is still e.g. int 1234 for
QClient calls and HEAppE result paths while job.job_id() returns e.g. str '1234' for Qiskit.
That keeps every existing reader of job.job_id working.

Cancelling a job used to report JobStatus.ERROR, with two causes. QClient.get_job_status
folded JobState.Canceled into FAILED, so it now returns a distinct CANCELED, and the
four poll loops stop on QClient.TERMINAL_JOB_STATES instead of a local list. That is not
enough on its own, because HEAppE reaps a cancelled job as JobState.Failed and never as
Canceled. So cancel() records that HEAppE accepted the request, and _to_qiskit_status()
reports CANCELLED rather than ERROR when it did. A job cancelled out of band still
reports ERROR, which is documented on the method.

backend_service.py compared job.status() against IQMJobStatus, but IQMJob.status()
returns a Qiskit JobStatus, so that operand was always false and remote failure detection
rested on not result.success alone. It now compares against JobStatus.ERROR.

Cancel on timeout in result() and wait_for_final_state() called
self._backend.cancel_job(...), which raised AttributeError after the first result()
because update_from_remotejob() replaces self._backend. Both call self.cancel() now.

Verified on VLQ

  • returned job now bahaves like a JobV1
  • job.job_id gives 1234 and job.job_id() gives '1234'
  • status() returns the same value before and after the first result(), and done() and
    in_final_state() are true once results are in
  • after cancel(), HEAppE reports JobState.Failed and job.status() gives
    JobStatus.CANCELLED
  • fiqci-ems works as expected on VLQ (used as an integration test)

@jsw0011 jsw0011 added this to the v0.5.1 Patch milestone Aug 31, 2026
@jsw0011 jsw0011 added 4.1 Ready to deploy on DEVEL bug Something isn't working labels Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

QJob does not implment JobV1

2 participants