Operator Actions: QA wait-for-ready
The OET supports operator actions: operator interventions made at runtime that control the behaviour of observing scripts. The first use case for this functionality is to give operators control over whether observing scripts wait for the system to be ‘QA Ready’ before proceeding with a scan. This behaviour is split into two mechanisms: a persistent global state that applies to every script run on that subarray, and a one-shot scan-level override that bypasses the wait for the current scan only.
Persistent state
The ScriptExecutionService holds a
ScriptContext instance whose
wait_for_qa_ready attribute is a simple boolean. When True (the
default), the context signals to scripts that they should wait for QA readiness
before each scan.
This flag is initialised from the OET_WAIT_FOR_QA_READY environment
variable (see src/ska_oso_oet/config.py), defaulting to true if unset.
It can be changed at runtime by an operator and persists across script
executions for the lifetime of the OET instance — that is, until the pod
restarts.
When a script is started, the current flag value is injected into the script’s
keyword arguments as kwargs["context"]["wait_for_qa_ready"], so every
script receives the up-to-date value at launch time.
Scan-level override
In addition to the persistent flag, an operator can send a one-shot override
signal. This does not change the persistent state at all — it is a fire-and-
forget event published on the operator.wait_for_qa_ready.override pypubsub
topic. Scripts that want to honour it must subscribe to that topic and use the
signal to release whatever blocking wait they hold in their scan loop.
The OET does not track whether a running script acted on an override. The semantics of “current scan” are defined entirely by the script.
Internal event flow
All operator actions are mediated by pypubsub topics defined in
topics:
Topic |
Purpose |
|---|---|
|
One-shot scan bypass. |
|
Persistent enable. |
|
Persistent disable. |
|
Request topic used by |
|
Response topic carrying the current
|
The sequence for a persistent state change is:
FastAPIWorker receives the POST and publishes to the relevant
topics.operator.wait_for_qa_ready.*topic.The
ScriptExecutionServicehandler methods (handle_wait_for_qa_ready_enable,handle_wait_for_qa_ready_disable) sees these pubsub messages and mutate the value ofScriptContext.wait_for_qa_readyto match.The next script to start receives the updated value of
wait_for_qa_readyvia itscontextargument.Already-running scripts can also subscribe to the same topics to react to state changes mid-execution.
For a state query (GET), the
ScriptExecutionServiceWorker uses a synchronous
request–response pattern over pypubsub: it publishes to
request.operator.override.state and returns the
ScriptContext received on
operator.override.state.
All operator actions are broadcast on the OET SSE stream, so external clients can observe override activity in real time without polling. This allows, for example, the OET UI to reflect the state set by the OST in another session.
REST API
Operator actions are served under the /operator-actions endpoint:
Method |
Endpoint |
Purpose |
|---|---|---|
|
|
Returns the current |
|
|
Publishes an operator action. Returns |
POST body
The POST body is {"topic": "<action>"} where <action> is one of:
Topic |
Effect |
|---|---|
|
Set the persistent flag to |
|
Set the persistent flag to |
|
One-shot signal to bypass the QA wait for the current scan. The persistent flag is unchanged. |
Authentication
GET requires the ACTIVITY_READ scope; POST requires
ACTIVITY_EXECUTE. Both require an authorised role (SW_ENGINEER, the
telescope operator role, or APP2APP).
CLI
The oet wait_for_qa_ready subcommand wraps the REST API:
# always wait for QA before scanning (persists)
oet wait_for_qa_ready enable --subarray_id=1
# never wait for QA before scanning (persists)
oet wait_for_qa_ready disable --subarray_id=1
# bypass the QA wait for the current scan only
oet wait_for_qa_ready override --subarray_id=1