Long Running Commands
A mixin class and decorators for implementing long running commands.
The mixin requires the Tango device class using it to also inherit from the generic
SKADevice class.
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.
- class ska_tango_base.future.LRCMixin[source]
Bases:
AbstractLRCMixinMixin class that adds support for long running commands with a task executor.
It must be used with
SKADeviceor 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)
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
LRCMixinclass to use its own task executor.- Returns:
Task executor instance.
- 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.future.AbstractLRCMixin[source]
Bases:
SignalBusMixinPartial mixin class that adds support for long running commands.
It must be used with
SKADeviceor 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. Atask_executormust be implemented for a long running command and the related attributes to behave correctly.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
CommandTrackerProtocolobject.
- 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_PROGRESSstatus. 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
COMPLETEDstatus. 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_REQimmediately 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
- class ska_tango_base.future.LRCReqType[source]
Bases:
IntEnumUsed 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.
Decorators
- @ska_tango_base.future.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.future.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
fisallowedparameter expects a device class method with a keyword argumentrequest_typethat defaults toLRCReqType.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 timerequest_type=LRCReqType.EXECUTE_REQ. The function is expected to returnFalse, if the task cannot be enqueued or executed. Alternatively,fisallowedmay raise an exception to provide a more detailed error message.If
fisallowedis 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.future.mark_long_running[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 theis_<Cmd>_allowed()method to be called later withLRCReqType.EXECUTE_REQwhen the task is about to be executed.Warning
This decorator does not arrange for the
is_<Cmd>_allowed()method to be called withLRCReqType.EXECUTE_REQ. For this use thesubmit_lrc_task()decorator orsubmit_lrc_task().
- @ska_tango_base.future.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.future.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
fisallowedparameter expects a device class method with a keyword argumentrequest_typethat defaults toLRCReqType.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 timerequest_type=LRCReqType.EXECUTE_REQ. The function is expected to returnFalse, if the task cannot be enqueued or executed. Alternatively,fisallowedmay raise an exception to provide a more detailed error message.If
fisallowedis 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_PROGRESSstatus.completed_callback – Callback passed to the command tracker that is called when the command transitions to
COMPLETEDstatus.
- Returns:
The wrapped function