An update stream service returns a stream of update messages, as defined in
Section 5. An ALTO server's IRD (Information Resource Directory)
MAY define one or more update stream services, which ALTO clients use to request new update stream instances. An IRD entry defining an update stream service
MUST define the media type, HTTP method, and capabilities and uses as follows.
The media type of an ALTO update stream service is "text/event-stream", as defined by [
SSE].
An ALTO update stream service is requested using the HTTP POST method.
The capabilities are defined as an object of type UpdateStreamCapabilities:
object {
IncrementalUpdateMediaTypes incremental-change-media-types;
Boolean support-stream-control;
} UpdateStreamCapabilities;
object-map {
ResourceID -> String;
} IncrementalUpdateMediaTypes;
If this update stream can provide data update messages with incremental changes for a resource, the "incremental-change-media-types" field has an entry for that resource-id, and the value is the supported media types of the incremental change separated by commas. Normally, this will be "application/merge-patch+json", "application/json-patch+json", or "application/merge-patch+json,application/json-patch+json", because, as described in
Section 5, they are the only incremental change types defined by this document. However, future extensions may define other types of incremental changes.
When choosing the media types to encode incremental changes for a resource, the update stream server
MUST consider the limitations of the encoding. For example, when a JSON merge patch specifies that the value of a field is null, its semantics are that the field is removed from the target and hence the field is no longer defined (i.e., undefined); see the MergePatch algorithm in
Section 3.1.1 on how null value is processed. This, however, may not be the intended result for the resource, when null and undefined have different semantics for the resource. In such a case, the update stream server
MUST choose JSON patch over JSON merge patch if JSON patch is indicated as a capability of the update stream server. If the server does not support JSON patch to handle such a case, the server then need to send a full replacement.
The "support-stream-control" field specifies whether the given update stream supports stream control. If the "support-stream-control" field is "true", the update stream server will use the stream control specified in this document; otherwise, the update stream server may use other mechanisms to provide the same functionality as stream control.
The "uses" attribute
MUST be an array with the resource-ids of every resource for which this update stream can provide updates. Each resource specified in the "uses"
MUST support full replacement; the update stream server can always send full replacement, and the ALTO client
MUST accept full replacement.
This set may be any subset of the ALTO server's resources and may include resources defined in linked IRDs. However, it is
RECOMMENDED that the ALTO server selects a set that is closed under the resource dependency relationship. That is, if an update stream's "uses" set includes resource R1 and resource R1 depends on ("uses") resource R0, then the update stream's "uses" set
SHOULD include R0 as well as R1. For example, an update stream for a cost map
SHOULD also provide updates for the network map upon which that cost map depends.
An ALTO client specifies the parameters for the new update stream by sending an HTTP POST body with the media type "application/alto-updatestreamparams+json". That body contains a JSON object of type UpdateStreamReq, where:
object {
[AddUpdatesReq add;]
[SubstreamID remove<0..*>;]
} UpdateStreamReq;
object-map {
SubstreamID -> AddUpdateReq;
} AddUpdatesReq;
object {
ResourceID resource-id;
[JSONString tag;]
[Boolean incremental-changes;]
[Object input;]
} AddUpdateReq;
-
add:
-
Specifies the resources (and the parameters for the resources) for which the ALTO client wants updates. In the scope of the same update stream, the ALTO client MUST assign a substream-id that is unique in the scope of the update stream (Section 5.2) for each entry and use those substream-ids as the keys in the "add" field.
-
resource-id:
-
The resource-id of an ALTO resource and MUST be in the update stream's "uses" list (Section 6.4). If the resource-id is a GET-mode resource with a version tag (or "vtag"), as defined in Sections 6.3 and 10.3 of [RFC 7285], and the ALTO client has previously retrieved a version of that resource from the update stream server, the ALTO client MAY set the "tag" field to the tag part of the client's version of that resource. If that version is not current, the update stream server MUST send a full replacement before sending any incremental changes, as described in Section 6.7.1. If that version is still current, the update stream server MAY omit the initial full replacement.
-
incremental-changes:
-
The ALTO client specifies whether it is willing to receive incremental changes from the update stream server for this substream. If the "incremental-changes" field is "true", the update stream server MAY send incremental changes for this substream. In this case, the client MUST support all incremental methods from the set announced in the server's capabilities for this resource; see Section 6.3 for the server's announcement of potential incremental methods. If a client does not support all incremental methods from the set announced in the server's capabilities, the client can set "incremental-changes" to "false", and the update stream server then MUST NOT send incremental changes for that substream. The default value for "incremental-changes" is "true", so to suppress incremental changes, the ALTO client MUST explicitly set "incremental-changes" to "false". An alternative design of incremental-changes control is a more fine-grained control, by allowing a client to select a subset of incremental methods from the set announced in the server's capabilities. But this alternative design is not adopted in this document, because it adds complexity to the server, which is more likely to be the bottleneck. Note that the ALTO client cannot suppress full replacement. When the ALTO client sets "incremental-changes" to "false", the update stream server MUST send a full replacement instead of an incremental change to the ALTO client. The update stream server MAY wait until more changes are available and send a single full replacement with those changes. Thus, an ALTO client that declines to accept incremental changes may not get updates as quickly as an ALTO client that does.
-
input:
-
If the resource is a POST-mode service that requires input, the ALTO client MUST set the "input" field to a JSON object with the parameters that the resource expects.
-
remove:
-
It is used in update stream control requests (Section 7) and is not allowed in the update stream request. The update stream server SHOULD ignore this field if it is included in the request.
If a request has any errors, the update stream server
MUST NOT create an update stream. Also, the update stream server will send an error response to the ALTO client, as specified in
Section 6.6.
If the update stream request has any errors, the update stream server
MUST return an HTTP "400 Bad Request" to the ALTO client; the body of the response follows the generic ALTO error response format specified in
Section 8.5.2 of
RFC 7285. Hence, an example ALTO error response has the format:
HTTP/1.1 400 Bad Request
Content-Length: 131
Content-Type: application/alto-error+json
Connection: Closed
{
"meta":{
"code": "E_INVALID_FIELD_VALUE",
"field": "add/my-network-map/resource-id",
"value": "my-networkmap/#"
}
}
Note that "field" and "value" are optional fields. If the "value" field exists, the "field" field
MUST exist.
-
If an update stream request does not have an "add" field specifying one or more resources, the error code of the error message MUST be E_MISSING_FIELD and the "field" field SHOULD be "add". The update stream server MUST close the stream without sending any events.
-
If the "resource-id" field is invalid or is not associated with the update stream, the error code of the error message MUST be E_INVALID_FIELD_VALUE. The "field" field SHOULD be the full path of the "resource-id" field, and the "value" field SHOULD be the invalid resource-id. If there are more than one invalid resource-ids, the update stream server SHOULD pick one and return it. The update stream server MUST close the stream (i.e., TCP connection) without sending any events.
-
If the resource is a POST-mode service that requires input, the client MUST set the "input" field to a JSON object with the parameters that that resource expects. If the "input" field is missing or invalid, the update stream server MUST return the same error response that that resource would return for missing or invalid input (see [RFC 7285]). In this case, the update stream server MUST close the update stream without sending any events. If the input for several POST-mode resources is missing or invalid, the update stream server MUST pick one and return it.
The response to a valid request is a stream of update messages.
Section 5 defines the update messages, and [
SSE] defines how they are encoded into a stream.
An update stream server
SHOULD send updates only when the underlying values change. However, it may be difficult for an update stream server to guarantee that in all circumstances. Therefore, a client
MUST NOT assume that an update message represents an actual change.
-
The first event MUST be a control update message with the URI of the update stream control service (see Section 7) for this update stream. Note that the value of the control-uri can be "null", indicating that there is no control stream service.
-
As soon as possible, after the ALTO client initiates the connection, the update stream server checks the "tag" field for each added update request. If the "tag" field is not specified in an added update request, the update stream server MUST first send a full replacement for the request. If the "tag" field is specified, the client can accept incremental changes, and the server can compute an incremental update based on the "tag" (the server needs to ensure that for a POST resource with input, the "tag" should indicate the correct result for different inputs); the update stream server MAY omit the initial full replacement.
-
If this update stream provides updates for resource-ids R0 and R1 and if R1 depends on R0, then the update stream server MUST send the update for R0 before sending the related updates for R1. For example, suppose an update stream provides updates to a network map and its dependent cost maps. When the network map changes, the update stream server MUST send the network map update before sending the cost map updates.
-
When the ALTO client uses the stream control service to stop updates for one or more resources (Section 7), the ALTO client MUST send a stream control request. The update stream server MUST send a control update message whose "stopped" field has the substream-ids of all stopped resources.
If multiple ALTO clients create multiple update streams from the same update stream resource and with the same update request parameters (i.e., same resource and same input), the update stream server
MUST send the same updates to all of them. However, the update stream server
MAY pack data items into different patch events, as long as the net result of applying those updates is the same.
For example, suppose two different ALTO clients create two different update streams for the same cost map, and suppose the update stream server processes three separate cost point updates with a brief pause between each update. The server
MUST send all three new cost points to both clients. But the update stream server
MAY send a single patch event (with all three cost points) to one ALTO client while sending three separate patch events (with one cost point per event) to the other ALTO client.
An update stream server
MAY offer several different update stream resources that provide updates to the same underlying resource (that is, a resource-id may appear in the "uses" field of more than one update stream resource). In this case, those update stream resources
MUST return the same update.
This design allows any valid media type for full replacement. Hence, it supports ALTO resources using multipart to contain multiple JSON objects. This realizes the push benefit but not the incremental encoding benefit of SSE.
JSON patch and merge patch provide the incremental encoding benefit but can be applied to only a single JSON object. If an update stream service supports a resource providing a multipart media type, which we refer to as a multipart resource, then the update stream service needs to handle the issue that the message of a full multipart resource can include multiple JSON objects. To address the issue, when an update stream service specifies that it supports JSON patch or merge patch incremental updates for a multipart resource, the service
MUST ensure that (1) each part of a multipart message is a single JSON object, (2) each part is specified by a static Content-ID in the initial full message, (3) each data update event applies to only one part, and (4) each data update specifies substream-id.content-id as the "event" field of the event, to identify the part to be updated.
In an SSE stream, any line that starts with a colon (U+003A) character is a comment, and an ALTO client
MUST ignore that line [
SSE]. As recommended in [
SSE], an update stream server
SHOULD send a comment line (or an event) every 15 seconds to prevent ALTO clients and proxy servers from dropping the HTTP connection. Note that although TCP also provides a Keep-Alive function, the interval between TCP Keep-Alive messages can depend on the OS configuration and varies. The preceding recommended SSE Keep-Alive allows the SSE client to detect the status of the update stream server with more certainty.