pyantz.infrastructure.distributed_queue.common package#
Submodules#
pyantz.infrastructure.distributed_queue.common.interface module#
Required function signatures for all our queues.
While the queues are function orientated, we want to ensure an exact consistent interface, so a protocol is used just to wrap the public interfaces.
Queues are expected to be stateless. The “state” should be persisted in the storage of the queue itself, but the queue instance is merely a convenience wrapper to access whatever persistent layer is used.
Classes may, however, store accessor details in their state. SQLite queues, for example, store a sqlalchemy engine to access the database file. But, after initialization this cannot be updated or changed without a new class instance.
- class QueueInterface(*args, **kwargs)[source]#
Bases:
ProtocolType checking interface to ensure consistent accesses.
- _abc_impl = <_abc._abc_data object>#
- _is_protocol = True#
- abstractmethod add_job(job_config: JobWithContext, parent_job_id: str | UUID | None)[source]#
Add the provided job to the queue.
- Parameters:
job_config (
JobWithContext) – job to enqueueparent_job_id (
str|UUID|None) – jobs added inherit their parent dependency “responsibilities”. So a job submitting new jobs should pass its own id to the function. For example if B depends on A and A adds C then B will depend on C. If, however, the user DOESN’T want that (B should run parallel to C), then they can pass “None” as the parent_job_id.
- Returns:
True if successfully added; False if unable to add
- Return type:
bool- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod change_config_in_place(job_config: JobWithContext)[source]#
Change the config of a job.
In practice, this is used to restart jobs during error recovery. A worker will update the num_attempted_runs and change the job. Then it will set its status to PENDING.
The queue will then set PENDING to READY on its next check and return the job to be re-run (the job is put back in the queue if a worker had already taken it out).
- Parameters:
job_config (
JobWithContext) – configuration to run- Return type:
None- Returns:
None.
- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod fail_deadlocked_jobs()[source]#
Mark PENDING jobs as ERROR if nothing is READY or RUNNING.
In that state nothing can ever change the status of a pending job (for example, it depends on a job id that was never added), so the pipeline would wait forever.
- Parameters:
None.
- Returns:
ids of the jobs which were failed
- Return type:
list[str]- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod fail_jobs_of_worker(worker_id: int)[source]#
Mark the RUNNING jobs of a worker which died as ERROR.
- Parameters:
worker_id (
int) – the worker (its process id) which died.- Returns:
ids of the jobs which were failed
- Return type:
list[str]- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod get_failed_jobs()[source]#
Get the status (with the error details) of every job which errored.
- Parameters:
None.
- Returns:
the failed jobs, sorted by job id.
- Return type:
list[JobStatusReport]- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod get_job()[source]#
Return a job from the queue.
- Parameters:
None.
- Returns:
- either
A job to run
Pending to indicate that nothing is ready but to keep waiting
Complete to tell the worker to kill itself
- Return type:
- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod get_job_status(job_id: str | UUID)[source]#
Get the current status of a job, and the details given with it.
- Parameters:
job_id (
str|UUID) – job to look up- Returns:
the job’s status and its details.
- Return type:
- Raises:
KeyError – if there is no such job
- abstractmethod get_jobs_report()[source]#
Get the jobs report.
Useful for debugging or determining the size of the queue.
- Parameters:
None.
- Returns:
report of the jobs and their states.
- Return type:
- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod set_job_worker(job_id: str | UUID, worker_id: int)[source]#
Record which worker is running the job.
- Parameters:
job_id (
str|UUID) – the job being run.worker_id (
int) – the worker (its process id) running it.
- Return type:
None- Returns:
None.
- Raises:
Exception – implementations may raise if the queue’s storage fails.
- abstractmethod update_job_status(job_id: str | UUID, status: JobStatus, details: str | None = None)[source]#
Update the status of the job.
- Parameters:
job_id (
str|UUID) – job to be updatedstatus (
JobStatus) – new state after this updatedetails (
str|None) – additional information about status eg., may be the error message for debugging.
- Return type:
None- Returns:
None.
- Raises:
Exception – implementations may raise if the queue’s storage fails.
pyantz.infrastructure.distributed_queue.common.return_types module#
Return types used by queue implementations.
GetJobReturn is the discriminated union returned by
get_job().
It wraps one of three payload types:
JobReturn— a job is ready to run.PendingReturn— nothing is ready now, but the queue is not empty.CompleteReturn— the queue is empty; the worker should exit.
JobsReport is a snapshot of job counts by status, used for
debugging and progress monitoring.
Example of GetJobReturn:
from pyantz.infrastructure.distributed_queue.common import ( GetJobReturn, ) report = { "total": 1, "success": 1, "error": 0, "pending": 0, "ready": 0, "running": 0, } result = GetJobReturn.model_validate( {"payload": {"type_": "complete", "jobs_report": report}} ) print(result.payload.type_, result.payload.jobs_report.all_succeeded)complete True
- class CompleteReturn(*, type_: Literal['complete'] = 'complete', jobs_report: JobsReport)[source]#
Bases:
BaseModelIndicates that the queue is empty and will not have additional jobs added.
- Parameters:
type_ (Literal['complete'])
jobs_report (JobsReport)
- _abc_impl = <_abc._abc_data object>#
- jobs_report: JobsReport#
The final state of the queue.
- type_: Literal['complete']#
Tells the returns apart at runtime; faster/easier than an isinstance check.
- class GetJobReturn(*, payload: JobReturn | CompleteReturn | PendingReturn)[source]#
Bases:
BaseModelReturn value of the get_job function.
This is used like a Rust enum return to return a “union” type.
Rather than always returning a job, get_job can return either
Job: Successfully dequeue a job
Pending: either jobs are ready and awaiting dependencies or a job is running and it may still submit something
Complete: the queue is empty and the worker should kill itself
- Parameters:
payload (JobReturn | CompleteReturn | PendingReturn)
- _abc_impl = <_abc._abc_data object>#
- payload: JobReturn | CompleteReturn | PendingReturn#
The actual return value, told apart by its
type_.
- class JobReturn(*, type_: Literal['job'] = 'job', job: JobWithContext)[source]#
Bases:
BaseModelActual job returned to be run.
- Parameters:
type_ (Literal['job'])
job (JobWithContext)
- _abc_impl = <_abc._abc_data object>#
- job: JobWithContext#
The job to run.
- type_: Literal['job']#
Tells the returns apart at runtime; faster/easier than an isinstance check.
- class JobStatus(*values)[source]#
Bases:
IntEnumPossible statuses of a job.
A job starts PENDING, becomes READY once every job it depends on succeeded, RUNNING when a worker takes it, and finally SUCCESS or ERROR. A job whose dependency fails becomes ERROR too.
- ERROR = 3#
Something went wrong; this job will never be completed. Depending on the setup, this might cause the whole pipeline to shutdown.
- PENDING = 1#
Job is waiting for dependencies.
- READY = 0#
Job can be run! Just waiting for a worker.
- RUNNING = 2#
Job is running on a worker right now.
- SUCCESS = 4#
Success! The job completed.
- class JobStatusReport(*, job_id: str | UUID, status: JobStatus, status_details: str | None = None)[source]#
Bases:
BaseModelStatus of a job.
- Parameters:
job_id (str | UUID)
status (JobStatus)
status_details (str | None)
- _abc_impl = <_abc._abc_data object>#
- job_id: str | UUID#
Identifier for the job.
- status_details: str | None#
Additional information about the status; for example, for errors this is the error message.
- class JobsReport(*, total: int, success: int, error: int, pending: int, ready: int, running: int)[source]#
Bases:
BaseModelDebug message with counts of various jobs for runtime analysis.
- Parameters:
total (Annotated[int, Ge(ge=0)])
success (Annotated[int, Ge(ge=0)])
error (Annotated[int, Ge(ge=0)])
pending (Annotated[int, Ge(ge=0)])
ready (Annotated[int, Ge(ge=0)])
running (Annotated[int, Ge(ge=0)])
- _abc_impl = <_abc._abc_data object>#
- property all_succeeded: bool#
True if no job errored and none is left unfinished.
- Parameters:
None.
- Returns:
True if every job finished successfully.
- Return type:
bool
- Raises:
None. –
Example
from pyantz.infrastructure.distributed_queue.common import JobsReport report = JobsReport( total=3, success=2, error=0, pending=0, ready=0, running=1 ) print(report.all_succeeded)
False
- error: int#
Number of jobs which updated themselves as error.
- pending: int#
Number of jobs waiting for dependencies before running.
- ready: int#
Number of jobs that could be run RIGHT NOW.
- running: int#
Number of jobs currently being run by a worker.
- success: int#
Number of jobs which updated themselves as successful.
- total: int#
Total number of unique jobs put on the queue.
- class PendingReturn(*, type_: Literal['pending'] = 'pending', jobs_report: JobsReport)[source]#
Bases:
BaseModelIndicates that the queue returned nothing but may return something later.
- Parameters:
type_ (Literal['pending'])
jobs_report (JobsReport)
- _abc_impl = <_abc._abc_data object>#
- jobs_report: JobsReport#
The state of the queue.
- type_: Literal['pending']#
Tells the returns apart at runtime; faster/easier than an isinstance check.
Module contents#
Common types across queue implementations.