uniqc.backend_adapter.task.store module

SQLite-backed task storage for UnifiedQuantum.

This module is the single source of truth for task persistence. Both uniqc.backend_adapter.task_manager and uniqc.backend_adapter.task.persistence delegate to TaskStore; there is no JSON/JSONL fallback path.

Storage layout:

~/.uniqc/cache/
    tasks.sqlite          # single database file

Schema versioning (best practices)

The database uses SQLite’s built-in metadata slots in the file header rather than a custom bookkeeping table:

  • PRAGMA application_id holds APPLICATION_ID (the 4 bytes "UNIC"). On open we refuse to touch a file whose application_id is set to something else; a zero value means a fresh DB we can stamp.

  • PRAGMA user_version holds the integer schema version. It is bumped by each migration and used to decide what else to run.

MIGRATIONS is an ordered list of (target_version, migrate_fn) tuples. To evolve the schema:

  1. Append a new tuple (N, _apply_vN) where N = CURRENT_SCHEMA_VERSION + 1.

  2. Bump CURRENT_SCHEMA_VERSION to N.

  3. Implement _apply_vN(conn) (DDL or DML on the given connection).

On open, TaskStore iterates the list and runs each outstanding migration in its own transaction; user_version is stamped as part of the same transaction so a crashed migration rolls back the version bump too.

class uniqc.backend_adapter.task.store.TaskInfo(task_id, backend, status=TaskStatus.PENDING, result=None, shots=1000, submit_time=<factory>, update_time=<factory>, metadata=<factory>, error_message=None, archived_at=None)[source]

Bases: object

Information about a submitted task.

Variables:
  • task_id (str) – Unique identifier for the task.

  • backend (str) – The backend where the task was submitted.

  • status (str) – Current status of the task.

  • result (dict | None) – Task result (if completed).

  • shots (int) – Number of shots requested.

  • submit_time (str) – ISO format timestamp of submission.

  • update_time (str) – ISO format timestamp of last status update.

  • metadata (dict) – Additional metadata about the task.

  • error_message (str | None) – When status == FAILED (or for any non-success terminal state) this carries a human-readable explanation — e.g. the dummy adapter’s stderr or the cloud platform’s error string. None while the task is still running or on success.

  • archived_at (str | None) – Timestamp when the task was archived; None if still in the live tasks table.

Parameters:
  • task_id (str)

  • backend (str)

  • status (str)

  • result (dict | None)

  • shots (int)

  • submit_time (str)

  • update_time (str)

  • metadata (dict)

  • error_message (str | None)

  • archived_at (str | None)

archived_at: str | None = None
backend: str
error_message: str | None = None
classmethod from_dict(data)[source]

Create from dictionary.

Parameters:

data (dict[str, Any])

Return type:

TaskInfo

metadata: dict
result: dict | None = None
shots: int = 1000
status: str = 'pending'
submit_time: str
task_id: str
to_dict()[source]

Convert to dictionary.

Return type:

dict[str, Any]

update_time: str
class uniqc.backend_adapter.task.store.TaskShard(uniqc_task_id, shard_index, platform_task_id, backend, circuit_count=1, sub_index_offset=0, status=TaskStatus.PENDING, result=None, error_message=None, submit_time=<factory>, update_time=<factory>)[source]

Bases: object

One platform-side job belonging to a uniqc-managed task.

A uniqc task is composed of one or more shards, each backed by a single platform-issued task id (platform_task_id). For single-circuit submissions there is exactly one shard whose circuit_count == 1; for batched submissions a shard may carry multiple circuits when the underlying platform supports native batch submission. When the user batch exceeds an adapter’s max_native_batch_size uniqc transparently slices it into multiple shards.

Variables:
  • uniqc_task_id (str) – Parent uniqc task id (uqt_…).

  • shard_index (int) – 0-based index of this shard within the parent.

  • platform_task_id (str) – Task id assigned by the cloud platform.

  • backend (str) – Backend label used at submit time (e.g. "originq:WK_C180").

  • circuit_count (int) – Number of user circuits packed into this shard. 1 for non-batched / single-circuit shards.

  • sub_index_offset (int) – Offset of this shard’s first circuit in the user’s original submit_batch list. Together with circuit_count this is the authoritative source for re-assembling per-circuit results in submission order.

  • status (str) – Status of this shard (independent of sibling shards).

  • result (Any) – Per-shard adapter result (dict for single-circuit shards; list[dict] for native-batch shards). May be None while the shard is still running.

  • error_message (str | None) – Human-readable error if status == FAILED.

  • submit_time (str) – ISO timestamp when this shard was successfully submitted to the platform.

  • update_time (str) – ISO timestamp of last status update.

Parameters:
  • uniqc_task_id (str)

  • shard_index (int)

  • platform_task_id (str)

  • backend (str)

  • circuit_count (int)

  • sub_index_offset (int)

  • status (str)

  • result (Any)

  • error_message (str | None)

  • submit_time (str)

  • update_time (str)

backend: str
circuit_count: int = 1
error_message: str | None = None
platform_task_id: str
result: Any = None
shard_index: int
status: str = 'pending'
sub_index_offset: int = 0
submit_time: str
to_dict()[source]
Return type:

dict[str, Any]

uniqc_task_id: str
update_time: str
class uniqc.backend_adapter.task.store.TaskStatus(*values)[source]

Bases: str, Enum

Enumeration of task statuses.

CANCELLED = 'cancelled'
FAILED = 'failed'
PENDING = 'pending'
RUNNING = 'running'
SUCCESS = 'success'
class uniqc.backend_adapter.task.store.TaskStore(cache_dir=None)[source]

Bases: object

SQLite-backed storage for task records.

TaskStore is safe to construct multiple times against the same cache directory; all operations use short-lived connections guarded by a per-instance lock.

Parameters:

cache_dir (Path | str | None) – Directory that holds tasks.sqlite. Defaults to ~/.uniqc/cache/. The directory is created if missing.

static aggregate_status(shards)[source]

Compute parent task status from shards.

Rules (denormalised onto tasks.status): - no shards yet → pending - any shard non-terminal → running - all shards SUCCESS → success - all terminal AND any FAILED → failed - all CANCELLED (or CANCELLED + SUCCESS only) → cancelled

When the aggregate is failed or cancelled callers may still inspect the individual shards via get_shards() to discover which ones succeeded.

Parameters:

shards (list[TaskShard])

Return type:

str

cache_dir: Path
clear_all()[source]

Delete the on-disk SQLite file (and its WAL/SHM siblings).

Matches the pre-SQLite clear_cache semantics: the cache file disappears. A subsequent operation re-initialises the schema.

Return type:

None

clear_completed(terminal_statuses=('success', 'failed', 'cancelled'))[source]

Delete tasks whose status is in terminal_statuses.

Parameters:

terminal_statuses (tuple[str, ...])

Return type:

int

count(*, status=None, backend=None)[source]
Parameters:
  • status (str | None)

  • backend (str | None)

Return type:

int

db_path: Path
delete(task_id)[source]

Remove a single task. Returns True if it existed.

Parameters:

task_id (str)

Return type:

bool

delete_shards(uniqc_task_id)[source]

Delete all shards for uniqc_task_id. Returns rows deleted.

Parameters:

uniqc_task_id (str)

Return type:

int

find_uniqc_id_by_platform_id(platform_task_id, *, backend=None)[source]

Return the parent uniqc_task_id for a platform id, or None.

Parameters:
  • platform_task_id (str)

  • backend (str | None)

Return type:

str | None

get(task_id)[source]

Return a task by id, or None if missing.

Parameters:

task_id (str)

Return type:

TaskInfo | None

get_shard_by_platform_id(platform_task_id, *, backend=None)[source]

Look up a shard by its platform-issued task id.

When backend is given, requires a backend match. Returns the first shard found (the index makes lookup O(log n)). If multiple shards share the same platform id across different backends and backend is not specified, the caller should disambiguate.

Parameters:
  • platform_task_id (str)

  • backend (str | None)

Return type:

TaskShard | None

get_shards(uniqc_task_id)[source]

Return shards for uniqc_task_id ordered by shard_index.

Parameters:

uniqc_task_id (str)

Return type:

list[TaskShard]

list(*, status=None, backend=None, limit=None, offset=None)[source]

List tasks, newest first (by submit_time).

Parameters:
  • status (str | None)

  • backend (str | None)

  • limit (int | None)

  • offset (int | None)

Return type:

list[TaskInfo]

save(task_info)[source]

Insert or update a task record (by task_id).

Also stamps task_info.update_time with the current timestamp so callers see the same value that was persisted.

Parameters:

task_info (TaskInfo)

Return type:

None

save_shard(shard)[source]

Insert or update a shard row (keyed by uniqc_task_id + shard_index).

Updates shard.update_time to now and persists it.

Parameters:

shard (TaskShard)

Return type:

None

uniqc.backend_adapter.task.store.generate_uniqc_task_id()[source]

Return a fresh uqt_<32-hex> task id (36 chars total).

Return type:

str

uniqc.backend_adapter.task.store.is_uniqc_task_id(task_id)[source]

Return True if task_id looks like a uniqc-managed id.

Parameters:

task_id (str)

Return type:

bool