Long Running Command client/server interface

This page describes the protocol built on top of Tango used by ska-tango-base to implement Long Running Commands.

Initiating Long Running Commands

To initiate an LRC, a client must invoke the corresponding Tango command. This Tango command either returns a (ResultCode, str) pair or raises an exception if argument validation fails. The return value is to be interpreted depending on the value of the ResultCode as follows:

  • ResultCode.QUEUED – The command has been queued, the second return value contains the generated command ID for the LRC.

  • ResultCode.STARTED – The command has been started immediately, the second return value contains the generated command ID for the LRC.

  • ResultCode.REJECTED – The command has been rejected (because, for example there is no room in the Input Queue). The second return value contains a reason string.

Monitoring progress of Long Running Commands

Once a client has initiated an LRC as described above the following LRC attributes are provided for monitoring the progress of their command. Associate task data of status, progress and result can be obtained corresponding to the command ID they were returned from the initiating Tango command.

LRC Attributes

Attribute

Example Value

Description

longRunningCommandsInQueue

(‘Standby’, ‘On’, ‘Off’)

Keeps track of which commands are known. Note the name is misleading as it includes LRC IN_PROGRESS and LRC that are COMPLETED/ABORTED/ REJECTED/FAILED

longRunningCommandIDsInQueue

(‘1636437568.0723004_235210334802782_On’, ‘1636437789.493874_116219429722764_Off’)

Keeps track of IDs in that have been allocated. Note the name is misleading as it includes LRC IN_PROGRESS and LRC that are COMPLETED/ABORTED/ REJECTED/FAILED

longRunningCommandStatus

(‘1636437568.0723004_235210334802782_On’, ‘IN_PROGRESS’,

‘1636437789.493874_116219429722764_Off’, ‘IN_PROGRESS’)

ID, status pair of the currently executing commands

longRunningCommandInProgress

(‘On’)

(‘Configure’, ‘Abort’)

()

Name of all commands currently executing

longRunningCommandProgress

(‘1636437568.0723004_235210334802782_On’, ‘12’,

‘1636437789.493874_116219429722764_Off’, ‘1’)

ID, progress pair of the currently executing commands

longRunningCommandResult

(‘1636438076.6105473_101143779281769_On’, (‘0’, ‘On command completed OK’))

ID, JSON encoded result of the completed command

The device has change events configured for all the LRC attributes which clients can use to track their requests. The client has the responsibility of subscribing to events to receive changes on command status and results.

In addition to the above attributes, the following commands are provided for interacting with Long Running Commands.

LRC commands

Command

Description

CheckLongRunningCommandStatus

Check the status of a long running command by ID

AbortCommands

Abort the currently executing LRC and remove all enqueued LRCs

UML illustration

Multiple clients invoke multiple Long Running Commands:

@startuml

participant Client2 as c2
participant Client1 as c1
participant SKADevice as d
entity Queue as q
participant Worker as w

== First Client Request ==

c1 -> d: Subscribe to attr to get result notification of LongRunningCommand
c1 -> d : LongRunningCommand
d -> d : Check queue capacity
d -> q : enqueue task LongRunningCommandTask
rnote over q
  Queue:
  LongRunningCommandTask
endrnote
d -> c1 : Response QUEUED LongRunningCommand, Task ID 101
== Second Client Request ==

c2 -> d: Subscribe to attr to get result notification of OtherLongRunningCommand
c2 -> d : OtherLongRunningCommand
d -> d : Check queue capacity
d -> q : enqueue task OtherLongRunningCommandTask
rnote over q
  Queue:
  LongRunningCommandTask
  OtherLongRunningCommandTask
endrnote
d -> c2 : Response QUEUED OtherLongRunningCommandTask, Task ID 102

== Processing tasks  ==

q -> w : dequeue LongRunningCommandTask
rnote over q
  Queue:
  OtherLongRunningCommandTask
endrnote
activate w

w -> d : LongRunningCommandTask result
deactivate w
d -> d : push_change_event (ID 101) on attr
d <--> c1 : on_change event with result (ID 101, some_result)
d <--> c2 : on_change event with result (ID 101, some_result)
c2 -> c2 : Not interested in 101, ignoring

q -> w : dequeue OtherLongRunningCommandTask
rnote over q
  Queue:
  <empty>
endrnote
activate w

w -> d : OtherLongRunningCommandTask result
deactivate w
d -> d : push_change_event (ID 102) on attr
d <--> c2 : on_change event with result (ID 102, some_result)
d <--> c1 : on_change event with result (ID 102, some_result)
c1 -> c1 : Not interested in 102, ignoring 

@enduml

Class diagram

@startuml

class SubmittedSlowCommand {
+ command_tracker
+ component_manager
+ method_name
+ do()
}
note bottom: Uses component_manager\nand command_tracker\nto update task state attributes\nin the Tango device


class _CommandTracker
note bottom: Keeps track of the\ncommand state and progress

class SampleDevice {
- _component_manager
- _command_tracker
- _commands__SlowCommand__
+ ...
+ ...()
}

class SampleDevice extends SKABaseDevice 

class BaseComponentManager

class TaskExecutor {
+ ...
+ submit()
+ abort()
+ ...()
}
note right: Uses `ThreadPoolExecutor` for task execution

class TaskExecutorComponentManager {
+ ...
+ submit_task()
+ abort_commands()
- _task_executor
+ ...()
}

class TaskExecutorComponentManager extends BaseComponentManager

SampleDevice::_component_manager --> TaskExecutorComponentManager
SampleDevice::_command_tracker --> _CommandTracker
SampleDevice::_commands__SlowCommand__ --> SubmittedSlowCommand
TaskExecutorComponentManager::_task_executor --> TaskExecutor


@enduml