Long Running Commands

Note

The LRC Client API has been moved to its own page, as it will be updated in a future release to be compatible with any SKA Tango command - fast or long running.

This module implements a mixin class for long running commands.

The mixin requires the class using it to also inherit from the generic SKADevice class.

class ska_tango_base.long_running_commands.mixin.LRCReqType[source]

Used to discriminate between command is allowed callers.

ENQUEUE_REQ = 1

Passed to is_<Cmd>_allowed when the task is submitted.

EXECUTE_REQ = 2

Passed to is_<Cmd>_allowed when the task is about to be executed.

class ska_tango_base.long_running_commands.mixin.LRCMixin[source]

Bases: AbstractLRCMixin

Mixin class that adds support for long running commands with a task executor.

It must be used with SKADevice or a subclass of it. It uses a shared bus with a command tracker to manage long running commands and the related user-facing Tango attributes.

lrcQueue: list[str]

Tango attribute returning a table describing queued long running commands.

Each element of the list is a JSON object with the following keys:

  • "uid" - Unique identifier for the command (str)

  • "name" - Name of the command (str)

  • "submitted_time" - Timestamp when the command was submitted (str)

lrcExecuting: list[str]

Tango attribute returning a table describing currently executing long running commands.

Each element of the list is a JSON object with the following keys:

  • "uid" - Unique identifier for the command (str)

  • "name" - Name of the command (str)

  • "submitted_time" - Timestamp when the command was submitted (str)

  • "started_time" - Timestamp when the command was started (str)

  • "progress" - Percentage completion (optional, int)

lrcFinished: list[str]

Tango attribute returning a table describing finished long running commands.

Each element of the list is a JSON object with the following keys:

  • "uid" - Unique identifier for the command (str)

  • "name" - Name of the command (str)

  • "submitted_time" - Timestamp when the command was submitted (str)

  • "started_time" - Timestamp when the command was started (str)

  • "finished_time" - Timestamp when the command finished (str)

  • "result" - JSON encoded result of command (str)

  • "status" - TaskStatus the command finished with (str)

  • "progress" - Percentage completion (optional, int)

on_new_shared_bus() None[source]

Initialise attributes which depend on signals from the bus.

create_task_executor() TaskExecutorProtocol[source]

Create and return a task executor instance.

This factory method can be overridden in a device using the LRCMixin class to use its own task executor.

Returns:

Task executor instance.

delete_device() None[source]

Delete the device.

schedule_abort_task(task_callback: TaskCallbackType) tuple[TaskStatus, str][source]

Schedule an Abort task to begin executing immediately.

Subclasses should override this to change the behaviour of the Abort command.

Parameters:

task_callback – Notified of progress of the abort command.

Returns:

A tuple containing TaskStatus.IN_PROGRESS and a message

property task_executor: TaskExecutorProtocol

Get the task executor.

Returns:

The initialised task executor.

class ska_tango_base.long_running_commands.mixin.AbstractLRCMixin[source]

Bases: SignalBusMixin

Partial mixin class that adds support for long running commands.

It must be used with SKADevice or a subclass of it. It uses a shared bus with a command tracker to manage long running commands and the related user-facing Tango attributes. A task_executor must be implemented for a long running command and the related attributes to behave correctly.

on_new_shared_bus() None[source]

Initialise attributes which depend on signals from the bus.

Raises:

AssertionError – If ‘self.task_executor.max_queued_tasks’ or ‘self.task_executor.max_executing_tasks’ is not equal to or greater than 0 or 1 respectively.

property command_tracker: CommandTrackerProtocol

Get the command tracker.

Returns:

The initialised CommandTrackerProtocol object.

property task_executor: TaskExecutorProtocol

Get the task executor.

Returns:

The initialised task executor.

lrcProtocolVersions() tuple[int, int]

Return supported protocol versions.

Returns:

A tuple containing the lower and upper bounds of supported long running command protocol versions.

is_Abort_allowed() bool[source]

Return whether the Abort() command may be called currently.

This method can be overridden by subclasses to change when this command is allowed.

Returns:

whether the command may be called in the current device state

Abort() DevVarLongStringArrayType

Abort any executing long running command(s) and empty the queue.

Abort is itself a long running command that is executed immediately.

Subclasses should override execute_Abort() to change the behaviour of this command.

Returns:

A tuple containing ResultCode.STARTED and the unique ID of the command

allocate_lrc(name: str, *, started_callback: Callable[[...], None] | str | None = None, completed_callback: Callable[[...], None] | str | None = None) tuple[str, TaskCallbackType][source]

Allocate a new command_id for a long running command.

The status and progress of the long running command should be updated using the returned task_callback object.

Parameters:
  • name – The name of the command

  • started_callback – Callback passed to the command tracker that is called when the command transitions to IN_PROGRESS status. If a str, this will be used to look up a callable on the self. If None the default name of “started_<Cmd>” will be used.

  • completed_callback – Callback passed to the command tracker that is called when the command transitions to COMPLETED status. If a str, this will be used to look up a callable on the self. If None the default name of “completed_<Cmd>” will be used.

Returns:

(command_id, task_callback)

static convert_submission_result_to_lrc_return(command_id: str, status: TaskStatus, message: str) DevVarLongStringArrayType[source]

Convert a submit result to a DevVarLongStringArray.

Example:

@command
def MyCommand(self) -> DevVarLongStringArrayType:
    command_id, task_callback = self.allocate_lrc("MyCommand")
    status, message = self.submit_lrc_task(
        "MyCommand", self.do_my_command, task_callback
    )
    return self.submit_result_to_lrc_return(
        command_id, status, message
    )
Parameters:
  • command_id – The command id of the LRC

  • status – The task status returned by submit

  • message – The message returned by submit

Returns:

[converted ResultCode], [command_id or message]

submit_lrc_task(name: str, task: TaskFunctionType, *, args: list[Any] | None = None, kwargs: dict[str, Any] | None = None, task_callback: TaskCallbackType | None = None, fisallowed: Callable[[LRCReqType], bool] | str | None = None) tuple[TaskStatus, str][source]

Submit a long running command task to the task_executor.

The f”is_{name}_allowed” method is looked up and, if found, will be called with LRCReqType.EXECUTE_REQ immediately before the task is executed.

Parameters:
  • task – task to be executed

  • args – positional arguments to be passed to the task

  • kwargs – keyword arguments to be passed to the task

  • fisallowed – override the is_cmd_allowed method used

Returns:

TaskStatus, message

execute_Abort() DevVarLongStringArrayType[source]

Execute the Abort command.

Subclasses should override this to change the behaviour of the Abort command.

Returns:

A tuple containing TaskStatus.IN_PROGRESS and a message

schedule_abort_task(task_callback: TaskCallbackType) tuple[TaskStatus, str][source]

Schedule an Abort task to begin executing immediately.

Subclasses should override this to change the behaviour of the Abort command.

Parameters:

task_callback – Notified of progress of the abort command.

Returns:

A tuple containing TaskStatus.IN_PROGRESS and a message

CheckLongRunningCommandStatus(argin: str) str

Check the status of a long running command by ID.

Parameters:

argin – the command id

Returns:

command status

execute_CheckLongRunningCommandStatus(argin: str) str[source]

Execute the CheckLongRunningCommandStatus command.

Subclasses should override this to change the behaviour of the CheckLongRunningCommandStatus command.

Parameters:

argin – the command id

Returns:

command status

Decorators for working with long running commands.

ska_tango_base.long_running_commands.decorators.long_running_command(*, fisallowed: Callable[[...], bool] | str | None = None, **cmd_kwargs: Any) Callable[[Callable[[...], Callable[[...], Any]]], Callable[[...], tuple[list[ResultCode], list[str]]]][source]
ska_tango_base.long_running_commands.decorators.long_running_command(task_factory: Callable[[...], Callable[[...], Any]], *, fisallowed: Callable[[...], bool] | str | None = None, **cmd_kwargs: Any) Callable[[...], tuple[list[ResultCode], list[str]]]

Mark a method as a long running command.

Wraps a method that returns a task with common boilerplate code for a long running command and submits the task to the task executor of the device. The wrapped task factory MUST be a method in a class that inherits from LRCMixin.

The fisallowed parameter expects a device class method with a keyword argument request_type that defaults to LRCReqType.ENQUEUE_REQ, or the name of such a method available on the device. The method will be called at submission time with the default keyword argument and will be called at execution time request_type=LRCReqType.EXECUTE_REQ. The function is expected to return False, if the task cannot be enqueued or executed. Alternatively, fisallowed may raise an exception to provide a more detailed error message.

If fisallowed is not provided, then the default method name of “is_<cmd>_allowed” will be looked up on the device. If this is not found, then it will be assumed that the task can awalys be enqueued and executed.

Parameters:
  • task_factory – An LRCMixin subclass method that returns a task.

  • fisallowed – Whether the task is allowed to execute. Called when command is added to the LRC queue (ENQUEUE_REQ) and immediately before execution (EXECUTE_REQ).

  • cmd_kwargs – Passed on to the tango.server.command call.

Returns:

A Tango command that submits the task to the long running command queue.

ska_tango_base.long_running_commands.decorators.submit_lrc_task(*, cmd_name: str | None = None, fisallowed: Callable[[...], bool] | str | None = None, started_callback: Callable[[...], None] | str | None = None, completed_callback: Callable[[...], None] | str | None = None) Callable[[Callable[[...], Callable[[...], Any]]], Callable[[...], tuple[list[ResultCode], list[str]]]][source]
ska_tango_base.long_running_commands.decorators.submit_lrc_task(task_factory: Callable[[...], Callable[[...], Any]], *, cmd_name: str | None = None, fisallowed: Callable[[...], bool] | str | None = None, started_callback: Callable[[...], None] | str | None = None, completed_callback: Callable[[...], None] | str | None = None) Callable[[...], tuple[list[ResultCode], list[str]]]

Submit a task returned by task_factory to the TaskExecutor.

Wraps a method that returns a task with common boilerplate code for a long running command and submits the task to the task executor of the device. The wrapped task factory MUST be a method in a class that inherits from LRCMixin.

The fisallowed parameter expects a device class method with a keyword argument request_type that defaults to LRCReqType.ENQUEUE_REQ, or the name of such a method available on the device. The method will be called at submission time with the default keyword argument and will be called at execution time request_type=LRCReqType.EXECUTE_REQ. The function is expected to return False, if the task cannot be enqueued or executed. Alternatively, fisallowed may raise an exception to provide a more detailed error message.

If fisallowed is not provided, then the default method name of “is_<cmd>_allowed” will be looked up on the device. If this is not found, then it will be assumed that the task can always be enqueued and executed.

Parameters:
  • task_factory – An LRCMixin subclass method that returns a task.

  • fisallowed – Whether the task is allowed to execute. Called when command is added to the LRC queue (ENQUEUE_REQ) and immediately before execution (EXECUTE_REQ).

  • started_callback – Callback passed to the command tracker that is called when the command transitions to IN_PROGRESS status.

  • completed_callback – Callback passed to the command tracker that is called when the command transitions to COMPLETED status.

Returns:

The wrapped function

ska_tango_base.long_running_commands.decorators.mark_long_running(fn: Any) Any[source]

Mark a executing_<Cmd>() method as a long running command.

This is used by the default is_<Cmd>_allowed() methods to know that they should not check the state machine when the Tango command is initially called and instead wait for the is_<Cmd>_allowed() method to be called later with LRCReqType.EXECUTE_REQ when the task is about to be executed.

Warning

This decorator does not arrange for the is_<Cmd>_allowed() method to be called with LRCReqType.EXECUTE_REQ. For this use the submit_lrc_task() decorator or submit_lrc_task().