Skip to content

WebSocket Based Changes Feed

Jens Alfke edited this page Apr 22, 2016 · 4 revisions

Couchbase Lite supports a WebSocket connection to the server's _changes feed. This is an extension of the CouchDB sync API.

WebSocket mode is conceptually the same as continuous mode -- both leave the socket open and send new notifications from the server as changes occur -- but it should avoid issues with proxy servers and gateways that cause continuous mode to fail in many real-world mobile use cases. (The primary problem is buggy HTTP chunked-mode body parsing that buffers up the entire response before sending any of it on; since the continuous feed response never ends, nothing gets through to the client.)

Connecting

The client requests WebSockets by setting the _changes URL's feed query parameter to websocket, and opening a WebSocket connection to that URL:

GET /db/_changes?feed=websocket HTTP/1.1
Connection: Upgrade
Upgrade: websocket
...

(Unfortunately Apache CouchDB does not return an error on such a request, even though it doesn't support WebSockets; instead it just reverts to normal feed. This means a client will have to determine whether the server supports WebSockets before requesting a _changes feed, probably from reading the tea leaves returned by GET /.)

Specifying options

The client then sends a single textual message to the server, specifying the feed options. This message is identical to the body of a regular HTTP POST to _changes, i.e. it's a JSON object whose keys are the parameters (for example, {"since": 112233, "include_docs": true})

After this, the client does not send any further messages.

Messages

Once the server receives the options, it will begin to send text-format messages. The messages are JSON; each contains one or more change notifications (in the same format as the regular feed) wrapped in an array:

[ {"seq":1022,"id":"beer_Indiana_Amber","changes":[{"rev":"1-e8f6b2e1f220fa4c8a64d65e68469842"}]},
  {"seq":1023,"id":"beer_Iowa_Pale_Ale","changes":[{"rev":"1-db962c6d93c3f1720cc7d3b6e50ac9df"}]}
]

(The current server implementation sends at most one notification per message, but this could change. Clients should accept any number.)

An empty array is a special case: it denotes that at this point the feed has finished sending the backlog of existing revisions, and will now wait until new revisions are created. It thus indicates that the client has "caught up" with the current state of the database.

The websocket mode behaves like the continuous mode: after the backlog of notifications (if any) is sent, the connection remains open and new notifications are sent as they occur.

Compressed Feed

For efficiency, the feed can be sent in compressed form; this greatly reduces the bandwidth and is highly recommended.

To signal that it accepts a compressed feed, the client adds "accept_encoding":"gzip" to the feed options in the initial message it sends.

Compressed messages are sent from the server as binary. This is of course necessary as they contain gzip data, and it also lets the client distinguish them from uncompressed messages. (The server will only ever send one kind.)

The compressed messages sent from the server constitute a single stream of gzip-compressed data. They cannot be decompressed individually! Instead, the client should open a gzip decompression session when the feed opens, and write each binary message to it as input as it arrives. The output from the decompressor consists of a sequence of JSON arrays, each of which has the same interpretation as a text message (above).

Clone this wiki locally