Please be aware that you are viewing our bleeding edge unstable documentation. Unless you wanted to view the bleeding edge (and possibly unstable) documentation, we recommend you use our stable docs.

Go to Ably's stable canonical documentation »

I know what I'm doing, let me see the bleeding edge docs »

You are viewing our bleeding edge unstable documentation. We recommend you use our stable documentation »
Fork me on GitHub

Reactor Functions

Reactor Functions allow your server-less functions to be invoked following channel lifecycle events (such as channel creation), presence events (such as members entering or leaving) or messages being published. Reactor Functions are offered as part of our Ably Reactor Event service, a service available to all customers of the Ably platform.

Reactor Functions are rate limited and designed for low to medium volumes of updates. If you expect a high volume of events and messages (upwards of 20 per second), then you should consider using our message queues or firehose instead as they are designed to scale without limits.

Generally, customers who want to receive events as they happen, use our message queues or firehose, or alternatively our realtime client libraries and subscribe to events and messages published. However, some customers prefer a server-less architecture and want to have their code invoked when a user publishes a message, attaches to a channel, or enters the presence set on a channel. For example, a developer may want to send a welcome message to someone when they first enter a chat channel. A Reactor Function can be used to achieve this.

Reactor Functions are designed to trigger server-less functions on common cloud platforms such as Amazon, Google and Microsoft. If you are looking to trigger the execution of code on your own servers over HTTP when a message is published or an event occurs, see our Reactor WebHooks or contact us to discuss setting up a custom endpoint.


Ably Reactor Functions diagram

Ably currently supports two types of Functions:

You can configure functions from the Reactor tab in your app on a per app basis which can apply to one or more channels in that app. Reactor Functions can be filtered by channel naming using a regular expression, for example ^click_.*_mouse$. This would match the string ‘click_’ followed by a string followed by ‘_mouse’, for example, ‘click_left_mouse’.

Messages

If you are unfamiliar with how channels work in Ably, we recommend you first review the realtime channel documentation.

When a Message is published on a channel, a Reactor Function message event is triggered, which in turn will send a message to your server-less function.

Every request will contain your message within the HTTP message body part of the request. The contents of the HTTP message body depends on whether you’ve used an envelope or not. If you don’t use an envelope, the HTTP message body will only contain the Message payload from your message event. If you do use an envelope, the HTTP message body will contain a number of attributes, which are the following:

source
the source of the request, namely “channel.message
appId
the ID of your application on Ably
channel
name of the channel on which the Message was published
site
an internal site identifier indicating the data center from which the message was published
ruleId
an ID for the rule which has created this request
messages
an Array containing your Message contents

See examples of enveloped and non-enveloped message events.

Please note that the messages attribute is an Array so that future envelope options may allow messages to be bundled into a single envelope (WebHooks currently bundle messages). However, with the current queue rule design, an envelope will only ever contain one message.

Decoding messages

Each member of messages is a ‘raw’ message, with the contents of your Message within it. Messages sent over the realtime service are automatically decoded into the Message object by the Ably client library. With Reactor Functions you need to to do this explicitly, using Message.fromEncodedArray on the messages array, or Message.fromEncoded on an individual member of that array. This will transform them into an array of Message (or in the case of fromEncoded, an individual Message). Using the Ably client library to decode messages has several advantages:

We recommend you do this for all messages you receive through Reactor Functions. For example (using ably-js):

const messages = Ably.Realtime.Message.fromEncodedArray(request.body.messages);
context.log(messages.toString());

Please note that if you are planning to receive messages via Ably Functions, it is theoretically very easy to exceed the transport rate limits we impose on Reactor Functions to prevent DoS attacks against your endpoints. We recommend you consider message queues instead for a more scalable solution, or firehose.

Presence events

If you are unfamiliar with how presence works in Ably and what events are supported, we recommend you first review the realtime presence documentation.

When a member enters, updates, or leaves a channel, a presence event is triggered. Every Reactor Function request instigated by a presence event will contain details of the presence event within the HTTP message body attribute.

Every request will contain your message within the HTTP message body part of the request. The contents of the HTTP message body depends on whether you’ve chosen to use an envelope in your Reactor Rule. If you don’t use an envelope, the HTTP message body will only contain the PresenceMessage payload from the presence event. If you do use an envelope, the HTTP message body will contain a number of attributes, which are the following:

source
the source of the request, namely “channel.presence
appId
the ID of your application with Ably
channel
name of the channel the Ably message was published on
site
an internal site identifier indicating the data center from which the message was published
ruleId
an ID for the rule which has created this request
presence
an Array containing your PresenceMessage contents

See examples of enveloped and non-enveloped presence events.

Please note that the presence attribute is an Array so that future envelope options may allow presence messages to be bundled into a single envelope (WebHooks currently bundle messages). However, with the current queue rule design, an envelope will only ever contain one presence message.

Decoding presence events

Each member of presence is a ‘raw’ presence event. Presence messages sent over the realtime service are automatically decoded into PresenceMessage objects by the Ably client library. With Reactor Functions you need to to do this explicitly, using PresenceMessage.fromEncodedArray on the presence array, or PresenceMessage.fromEncoded on an individual member of that array. This will transform them into an array of PresenceMessage (or in the case of fromEncoded, an individual PresenceMessage). Using the Ably client library to decode presence has several advantages:

We recommend you do this for all presence messages you receive through Reactor Functions. For example (using ably-js):

const presMsgs = Ably.Realtime.PresenceMessage.fromEncodedArray(request.body.presence);
console.log(presMsgs.toString());

Payload Encoding

The encoding of payloads sent is defined when setting up a Reactor Rule in the Reactor tab of your app. You can have the message sent in JSON format, or as a MessagePack payload.

Envelopes

When you configure a Function rule, you are given the option to envelope messages, which is enabled by default. In most cases, we believe an enveloped message provides more flexibility as it contains additional metadata in a portable format that can be useful such as the clientId of the publisher, or the channel name the message originated from.

However, where performance is a primary concern, you may choose not to envelope messages and instead have only the message payload (data element) published. This has the advantage of requiring one less parsing step, however decoding of the raw payload in the published message will be your responsibility.

Note that messages published to queues are by default encoded as JSON (a text format), however you can choose to have messages encoded with MsgPack (a binary format) in your queue rules.

Enveloped and non-enveloped message examples

When you configure a Function rule, you are given the option to envelope messages, which is enabled by default. In most cases, we believe an enveloped message provides more flexibility as it contains additional metadata in a portable format that can be useful such as the clientId of the publisher, or the channel name the message originated from.

However, where performance is a primary concern, you may choose not to envelope messages and instead have only the message payload (data element) published. This has the advantage of requiring one less parsing step, however decoding of the raw payload in the published message will be your responsibility.

Note that messages published to queues are by default encoded as JSON (a text format), however you can choose to have messages encoded with MsgPack (a binary format) in your queue rules.

Enveloped message example

Headers: none

Data:

{
  "id": "cOOo9g|108YY6nPAA3SrE56067277:10",
  "source": "channel.message",
  "channel": "foo",
  "site": "eu-west-1-A",
  "ruleId": "cOOo9g",
  "timestamp": 1485914937984,
  "messageId": "vjzxPR-XK3:3",
  "messages": [
    {
      "id": "vjzxPR-XK3:3:0",
      "name": "",
      "connectionId": "vjzxPR-XK3",
      "timestamp": 1485914937909,
      "data": "textPayload"
    }
  ]
}

Please note that the messages attribute is an Array so that future envelope options may allow messages to be bundled into a single envelope (WebHooks currently bundle messages). However, with the current queue rule design, an envelope will only ever contain one message.

Non-enveloped message example

Headers:

Data:

textPayload

Enveloped presence message example

Headers: none

Data:

{
  "id": "z8R85g|108YY6nPAA3SrE56067277:12",
  "source": "channel.presence",
  "channel": "foo",
  "site": "eu-west-1-A",
  "ruleId": "z8R85g",
  "timestamp": 1485916832965,
  "messageId": "vjzxPR-XK3:5",
  "presence": [
    {
      "id": "vjzxPR-XK3:5:0",
      "clientId": "bob",
      "connectionId": "vjzxPR-XK3",
      "timestamp": 1485916832961,
      "action": "enter",
      "data": "clientData"
    }
  ]
}

Please note that the presence attribute is an Array so that future envelope options may allow presence messages to be bundled into a single envelope (WebHooks currently bundle messages). However, with the current queue rule design, an envelope will only ever contain one presence message.

Non-enveloped presence message example

Headers:

Data:

clientData

Server-less platform support

We currently support the following:

We also offer custom endpoints to our Enterprise customers.

Troubleshooting Functions

If you are finding it hard to debug a problem with Reactor Functions, we recommend you review our recommendations for debugging Functions. If this does not help, please get in touch with us so that we can help you with your problem.

Next steps


Back to top