Vadim Dalecky3 years ago

JSON-Rx

JSON-Rx is extension of JSON-RPC Compact protocol to allow for subscriptions. Such as WebSocket subscriptions, for example, for GraphQL.

The protocol is bi-directional, so both sides of the protocol can simultaneously initiate as well as respond to requests. Client is the side which initiates the request, and server is the side which responds.

The client can: (1) subscribe; and (2) un-subscribe. The server can: (1) complete the subscription, or (2) send an error, which implicitly also completes the subscription; (3) send data, which keeps the subscription active, and server will still follow up with more data or a complete message.

The semantics are analogous to RxJs observables, where a user can .subscribe() to an observable and later .unsubscribe() from it. During the subscription, the observable can emit zero or more values. Observable can also complete, in which case no new data or errors are emitted. Or, observable can error, in which case an error is received and it implicitly completes the observable.

Message types

JSON-RPC Compact defines four message types:

  • Request message

  • Success (response) message

  • Error (response) message

  • Notification message

JSON-Rx extends the message set with two new message types:

  • Un-subscribe message

  • Data message

JSON-Rx also renames the first two messages of JSON-RPC Compact as follows:

  • Request message to Subscribe message

  • Success message to Complete message

Hence, the JSON-Rx protocol consists of six message types:

  • Subscribe message

  • Un-subscribe message

  • Data message

  • Complete message

  • Error message

  • Notification message

Message semantics

The subscribe message is sent out by the client and starts a subscriptions, client can also follow up at any time with unsubscribe message

Server responds to a subscription with data message; and complete or error message.

Client can also send a notification message at any time.

Subscribe message

Subscribe message is defined exactly as Request message in JSON-RPC Compact.

Subscribe message is a 3-tuple, which consists of: (1) message ID; (2) remote method name; (3) JSON parameters. It can also be a 2-tuple if the JSON parameters are omitted, e.g. the method has no arguments.

Message ID must be a positive integer. Usually it is an incrementing counter, which starts from 1 and is incremented with every request.

Remote method name is a string. In must be at least 1 character long, and no longer than 128 characters.

JSON parameters is the third member of the tuple and is a JSON object which represents the arguments for the remote method.

Examples:

Un-subscribe message

Un-subscribe message allows client to stop subscription on the server. Un-subscribe message can be sent at any time. Effectively, this allows to cancel any request or subscription, even without receiving back any data.

Un-subscribe message is a 2-tuple: (1) the first member is always equal to -3; (2) the second member is the ID of the subscription.

Data message

Data message is used by the server to send subscription data to the client. There could be any number of data messages sent. No data messages should be sent, nor accepted, after the subscription received a complete message or error message.

Data message is always a 3-tuple, which consists of: (1) the first member is always -2; (2) the second member is set to the subscription ID; (3) the third member is a JSON payload.

Data message cannot be a 2-tuple.

Complete message

Complete message is defined exactly as Success message in JSON-RPC Compact. When complete message is sent out by the server, it notifies the client that the subscription should complete and no further data will be sent out.

Complete message is a 3-tuple. Tuple members are as follows: (1) first member is always 0 and signifies a complete message; (2) second member is the message ID of the request; (3) third member is the response payload in JSON format.

Success response might also be a 2-tuple if it is not expected to ever return anything, i.e. it is a method with side-effects only. If the method is expected to return some response at least in some situations, the third member of the 3-tuple should always be present in every response message.

Examples:

Error message

Error message is defined exactly as JSON-RCP Complete error message. When error message is sent out by the server, it notifies the client that the subscription should complete and no further data will be sent out.

Error message is a 3-tuple. It is always a 3-tuple and cannot be be reduced to 2-tuple. Error message 3-tuple is specified as follows: (1) first member is always set to -1; (2) second member is the message ID of the request message; (3) is the error in JSON format.

The third tuple member is an arbitrary JSON value, specific to the application. Usually it is an object with at least "message" field.

Notifcation message

JSON-Rc notification message is defined exactly as JSON-RPC Compact notification message.

Notification message is a one way message, for which no direct response is expected (at the level of this protocol, although you can still use it to implement a higher level protocol).

Notification message is a 2-tuple, which consists of: (1) first member is a string specifying a remote message; (2) second member is JSON payload.

The first string member must be at least 1 character long and no more than 128 characters in length.

Notification message may also be 1-tuple, in which case semantically it is treated as a notification message without arguments.

Examples

Request/response example

Request:

Response:

The complete message returns the response and completes the subscription.

Subscription example

Below is a GraphQL subscription example.

Client can subscribe to timer GraphQL subscription:

Server would emit timer values periodically:

Client can un-subscribe:

After which client will not accept any in-flight data message, and server removes the subscription state on the server once it receives the message.