Behaviour: Querying
←Behaviour - Registration · Index↑ · Behaviour - Nodes→
The Query API provides a read-only interface to the Nodes and their sub-resources which are currently held in the registry. Browsing of the Query API may be performed via the RESTful API, or by using the websocket protocol (RFC 6455) which is suggested for most applications.
API Resources
Where the behaviour associated with an API attribute is not sufficiently clear from its name and schema constraints, this is documented below.
Subscriptions
secure
Indicates whether the WebSocket connection is provided via an encrypted connection or not (ws:// vs. wss://). Unless otherwise indicated the value of this attribute SHOULD be ‘false’ if the API is being presented via HTTP, and ‘true’ for HTTPS. Query API clients MAY choose to specify the opposite value in requests for subscriptions, however they will receive a 400 response code unless the Query API explicitly supports a mismatch between encrypted HTTP and WebSocket connections.
Creating a Websocket subscription
In order to connect to a websocket, a client must first request a subscription of a particular type and with particular query parameters by performing a POST as defined in the Query API subscriptions documentation. Use of GET requests to find existing suitable websocket connections is strongly discouraged.
There is no mandated URL base path for servers to use when creating websocket connections. Instead clients should observe the value of ‘ws_href’ which is returned by their subscription request in order to identify what to connect to.
Websockets created for specific clients will be cleaned up automatically if they disconnect.
Connection upgrade procedures permitting an existing HTTP query to transition to a websocket are not currently supported, but may be in the future.
Query API Behaviour
Long-lived connections to the Query API are supported via Websockets which can be set up via the /subscriptions resource. Query APIs may additionally support the HTTP ‘Upgrade’ header sent by clients to upgrade an HTTP GET request to a Websocket. In cases where this is performed, a corresponding entry in /subscriptions must also be created with matching query parameters.
Upon receiving a request for a new subscription, the Query API should identify whether it already has any websockets open which provide for the requested query. If a websocket exists, the ‘subscription’ object representing it may be returned to the user. If a relevant websocket does not exist a new one should be created.
In normal operation, once a websocket has no more clients subscribed to it the Query API may automatically remove it and its corresponding HTTP-advertised subscription object. The Query API MUST NOT acknowledge HTTP DELETE requests for websockets running in this ‘non-persistent’ mode, instead issuing an HTTP 403 response.
If a ‘persistent’ websocket has been requested by the client, this must not be cleaned up automatically by the Query API, even if all consuming clients have disconnected. The user may request closing of this socket by issuing an HTTP DELETE. If an HTTP DELETE is issued prior to all websocket connections being closed, they should be forcibly closed by the server.
Websocket Protocol
Using data Grains, the websocket protocol provides a client with the current state of the contents of the registry at the time of subscription. It subsequently notifies clients of any changes.
Note that the Source ID used in the following examples references the Query API instance. The Flow ID then corresponds to the subscription ID created via the /subscriptions HTTP resource.
The timestamps used in these messages relate to the NMOS Content Model. In this use case the three timestamps are permitted to be identical.
- creation_timestamp: The creation time of the Grain metadata which wraps the payload being exchanged.
- origin_timestamp: The capture or creation time of the payload being exchanged.
- sync_timestamp: Matches the origin_timestamp at the point of capture. This timestamp relates this payload to others which may take different processing paths. This may persist through processing devices which modify the payload’s content.
The ‘rate’ and ‘duration’ attributes may be ignored by clients as the event messages being exchanged do not adhere to a defined rate or duration.
Each Grain may contain one or more objects in its ‘data’ array. Each object identifies a change to a single Source, Flow or other resource as identified by the ‘topic’.
A schema for the Grain metadata described below is available here.
Resource(s) Added Event
Event data containing only a “post” attribute signifies creation of a resource.
{
"grain_type": "event",
"source_id": <id_of_query_api_instance>,
"flow_id": "e223e6f3-de75-4855-bd19-b83774e31689",
"origin_timestamp": <ts_secs>:<ts_nsecs>,
"sync_timestamp": <ts_secs>:<ts_nsecs>,
"creation_timestamp": <ts_secs>:<ts_nsecs>,
"rate": {
"numerator": 0,
"denominator": 1
},
"duration": {
"numerator": 0,
"denominator": 1
},
"grain": {
"type": "urn:x-nmos:format:data.event",
"topic": "/flows/",
"data": [
{
"path": "b58aae65-1913-4f7b-aae2-2377446dd639",
"post": {
"id": "b58aae65-1913-4f7b-aae2-2377446dd639",
"label": "my_flow_name",
"description": "my flow description",
"source_id": "0e1b33f-6cfb-423e-b777-23efe0f539f4",
"format": "urn:x-nmos:format:video"
}
},
...
]
}
}
Resource(s) Removed Event
Event data containing only a “pre” attribute signifies deletion of a resource.
{
"grain_type": "event",
"source_id": <id_of_query_service_instance>,
"flow_id": "e223e6f3-de75-4855-bd19-b83774e31689",
"origin_timestamp": <ts_secs>:<ts_nsecs>,
"sync_timestamp": <ts_secs>:<ts_nsecs>,
"creation_timestamp": <ts_secs>:<ts_nsecs>,
"rate": {
"numerator": 0,
"denominator": 1
},
"duration": {
"numerator": 0,
"denominator": 1
},
"grain": {
"type": "urn:x-nmos:format:data.event",
"topic": "/flows/",
"data": [
{
"path": "b58aae65-1913-4f7b-aae2-2377446dd639",
"pre": {
"id": "b58aae65-1913-4f7b-aae2-2377446dd639",
"label": "my_flow_name",
"description": "my flow description",
"source_id": "0e1b33f-6cfb-423e-b777-23efe0f539f4",
"format": "urn:x-nmos:format:video"
}
},
...
]
}
}
Resource(s) Modified Event
Event data containing both “pre” and “post” attributes signifies modification of a resource. All attributes of the resource must be specified (i.e. not just those that have changed).
{
"grain_type": "event",
"source_id": <id_of_query_service_instance>,
"flow_id": "e223e6f3-de75-4855-bd19-b83774e31689",
"origin_timestamp": <ts_secs>:<ts_nsecs>,
"sync_timestamp": <ts_secs>:<ts_nsecs>,
"creation_timestamp": <ts_secs>:<ts_nsecs>,
"rate": {
"numerator": 0,
"denominator": 1
},
"duration": {
"numerator": 0,
"denominator": 1
},
"grain": {
"type": "urn:x-nmos:format:data.event",
"topic": "/flows/",
"data": [
{
"path": "b58aae65-1913-4f7b-aae2-2377446dd639",
"pre": {
"id": "b58aae65-1913-4f7b-aae2-2377446dd639",
"label": "my_flow_name",
"description": "my flow description",
"source_id": "0e1b33f-6cfb-423e-b777-23efe0f539f4",
"format": "urn:x-nmos:format:video"
},
"post": {
"id": "b58aae65-1913-4f7b-aae2-2377446dd639",
"label": "my_new_flow_name",
"description": "my new flow description",
"source_id": "0e1b33f-6cfb-423e-b777-23efe0f539f4",
"format": "urn:x-nmos:format:video"
}
},
...
]
}
}
Resource(s) Unchanged (Sync) Event
Event data containing both “pre” and “post” where the contents of “pre” and “post” are identical. This is used in initial synchronisation messages to ensure the client has received all data for a given topic.
{
"grain_type": "event",
"source_id": <id_of_query_service_instance>,
"flow_id": "e223e6f3-de75-4855-bd19-b83774e31689",
"origin_timestamp": <ts_secs>:<ts_nsecs>,
"sync_timestamp": <ts_secs>:<ts_nsecs>,
"creation_timestamp": <ts_secs>:<ts_nsecs>,
"rate": {
"numerator": 0,
"denominator": 1
},
"duration": {
"numerator": 0,
"denominator": 1
},
"grain": {
"type": "urn:x-nmos:format:data.event",
"topic": "/flows/",
"data": [
{
"path": "b58aae65-1913-4f7b-aae2-2377446dd639",
"pre": {
"id": "b58aae65-1913-4f7b-aae2-2377446dd639",
"label": "my_flow_name",
"description": "my flow description",
"source_id": "0e1b33f-6cfb-423e-b777-23efe0f539f4",
"format": "urn:x-nmos:format:video"
},
"post": {
"id": "b58aae65-1913-4f7b-aae2-2377446dd639",
"label": "my_flow_name",
"description": "my flow description",
"source_id": "0e1b33f-6cfb-423e-b777-23efe0f539f4",
"format": "urn:x-nmos:format:video"
}
},
{
"path": "e759c3f0-8eed-4344-932a-5eb1c40a2d41",
"pre": {
"id": "e759c3f0-8eed-4344-932a-5eb1c40a2d41",
"label": "another_flow_name",
"description": "another flow description",
"source_id": "d7f43929-30c7-4847-a0f8-0242b82002d8",
"format": "urn:x-nmos:format:audio"
},
"post": {
"id": "e759c3f0-8eed-4344-932a-5eb1c40a2d41",
"label": "another_flow_name",
"description": "another flow description",
"source_id": "d7f43929-30c7-4847-a0f8-0242b82002d8",
"format": "urn:x-nmos:format:audio"
}
},
...
]
}
}
Handling Query Parameters
Websocket subscriptions support query parameters in the same way as the corresponding REST API endpoints. Care should be taken to ensure that clients are informed when resources begin to or no longer match a given query parameter. For example:
- If a Flow (or other resource) has a ‘tag’ removed causing it to no longer match the query parameters for a websocket subscription, the client must be issued a ‘Resource Removed Event’ as if this resource had been deleted from the registry.
- If a Flow (or other resource) has a ‘tag’ added causing it to match a query parameter where it didn’t match them previously, the client must be issued a ‘Resource Added Event’ as if this resource had been freshly created in the registry.
Referential Integrity
API clients should be aware of the following potential issues when interacting with the deprecated ‘senders’ and ‘receivers’ arrays present within Device resources. Use of these arrays is discouraged.
- Devices MAY be registered with UUIDs of the Senders and Receivers attached to the Device, in the (deprecated) “senders” and “receivers” array properties, even if those Senders/Receivers have not yet been registered themselves.
- Senders and Receivers attached to Devices MAY be omitted from the Device’s (deprecated) “senders” and “receivers” array properties. Consumers of the Node/Query APIs SHOULD instead discover attached Senders/Receivers by filtering Senders and Receivers on “device_id”.