diff --git a/content/realtime/channel-params.textile b/content/realtime/channel-params.textile index 75cf596cc1..2105699fba 100644 --- a/content/realtime/channel-params.textile +++ b/content/realtime/channel-params.textile @@ -139,3 +139,109 @@ h3(#rewind-examples-mqtt). Rewind example with MQTT ... }); ``` + +h2(#delta). Delta parameter + +The @delta@ channel parameter allows subscribers to expresse their desire to receive deltas (diffs) between the previous and current message instead of the current message in full on a given channel. The effects of this parameter are invisible to message senders and only affect subscribers that specify it - i.e. the sender sends messages in full and Ably computes and sends the message deltas to any subscriber which subscribed using this parameter. + +Note that requesting deltas does not guarantee that every message received will be a delta, as the server may chose to send some messages in full depending on system load and other factors. Therefore a subscriber using the @delta@ parameter should be prepared to handle a random mix of delta and full messages. + +The @delta@ parameter can take only the value @vcdiff@. VCDIFF is the format of the deltas. It is an open format specified in "RFC 3284":https://tools.ietf.org/html/rfc3284. + +Ably provides a JavaScript "delta codec library":https://github.com/ably/delta-codec-js to help you avoid writing boilerplate VCDIFF handling code. Some examples follow. + +h3(#delta-example-sse). Delta example with enveloped SSE + +```[jsall] +const key = '{{API_KEY}}'; +const channel = 'sample-app-sse'; +const url = `https://realtime.ably.io/event-stream?channels=${channel}&v=1.1&key=${key}&delta=vcdiff`; +const eventSource = new EventSource(url); +const channelDecoder = new DeltaCodec.CheckedVcdiffDecoder(); + +eventSource.onmessage = (event) => { + /* event.data is JSON-encoded Ably Message (see https://www.ably.io/documentation/realtime/types#message) */ + const message = JSON.parse(event.data); + const { id, extras } = message; + let { data } = message; + + try { + if (extras && extras.delta) { + data = channelDecoder.applyBase64Delta(data, id, extras.delta.from).asUtf8String(); + } else { + channelDecoder.setBase(data, id); + } + } catch(e) { + /* Delta decoder error */ + console.log(e); + } + + /* Process decoded data */ + console.log(data); +}; +``` + +h3(#delta-example-unenv-sse). Delta example with unenveloped SSE + +```[jsall] +const key = '{{API_KEY}}'; +const channel = 'sample-app-sse'; +const url = `https://realtime.ably.io/event-stream?channels=${channel}&v=1.1&key=${key}&delta=vcdiff&enveloped=false`; +const eventSource = new EventSource(url); +const channelDecoder = new DeltaCodec.VcdiffDecoder(); + +eventSource.onmessage = (event) => { + let data = event.data; + + try { + if (DeltaCodec.VcdiffDecoder.isBase64Delta(data)) { + data = channelDecoder.applyBase64Delta(data).asUtf8String(); + } else { + channelDecoder.setBase(data); + } + } catch(e) { + /* Delta decoder error */ + console.log(e); + } + + /* Process decoded data */ + console.log(data); +}; +``` + +h3(#delta-example-mqtt). Delta example with MQTT + +```[jsall] +const mqtt = require('mqtt'); +const { VcdiffDecoder } = require('./lib'); + +const options = { + keepalive: 30, + username: 'FIRST_HALF_OF_API_KEY', + password: 'SECOND_HALF_OF_API_KEY', + port: 8883 +}; +const client = mqtt.connect('mqtts:mqtt.ably.io', options); +const channelName = 'sample-app-mqtt'; +const channelDecoder = new VcdiffDecoder(); + +client.on('message', (_, payload) => { + let data = payload; + + try { + if (VcdiffDecoder.isDelta(data)) { + data = channelDecoder.applyDelta(data).asUint8Array(); + } else { + channelDecoder.setBase(data); + } + } catch(e) { + /* Delta decoder error */ + console.log(e); + } + + /* Process decoded data */ + console.log(data); +}); + +client.subscribe(`[?delta=vcdiff]${channelName}`); +```