Tutorials

History Tutorial

Ably’s history feature enables you to store messages published on channels that can later be retrieved using the channel history API.

By default, channels will only store messages in memory for up to two minutes. However, using channel rules, you can configure messages published on matching channels to be persisted to disk for typically 24 – 72 hours. Those messages will then be immediately available for retrieval via our Realtime and REST API clients for as long as the message is stored on disk.

Using our history API is trivial. Let’s get started.

Step 1 – Set up a free account with Ably

In order to run these tutorials locally, you will need an Ably API key. If you are not already signed up, you should sign up now for a free Ably account. Once you have an Ably account:

  1. Log into your app dashboard
  2. Under “Your apps”, click on “Manage app” for any app you wish to use for this tutorial, or create a new one with the “Create New App” button
  3. Click on the “API Keys” tab
  4. Copy the secret “API Key” value from your Root key and store it so that you can use it later in this tutorial

    Copy API Key screenshot

Step 2 – Configure all channels within a namespace to persist messages to disk

Channels can be named using any unicode string characters with the only restriction that they cannot start with a [ or : character as these are used as “special” characters. A colon : is used to delimit channel namespaces in a format such as namespace:channel. Namespaces provide a flexible means to group channels together. Channel grouping can be useful when, for example, configuring permissions (capabilities) for a set of channels within a client token or setting up rules to apply to one or more channels.

We will be using channel rules in this tutorial to ensure all channels in the persisted namespace are configured to persist messages to disk i.e. we will explicitly enable the history feature. Follow these steps:

  1. Visit your account dashboard, navigate to the same app you chose in Step 1 when obtaining your API key earlier
  2. Click on the Settings tab and scroll down to the “Channel rules” section
  3. Click the “Add new rule” button (see below)

    Add new channel rule screenshot
  4. Once the modal has opened, enter “persisted” for the namespace, check the Persisted check box to enable history, and click the “Create channel rule” button (see below)

    Create channel rule screenshot

You have now enabled history for all channels in the persisted namespace i.e. any channel with a name matching the pattern persisted:* will store published messages to disk.

Step 3 – Install AblyStep 3 – Setup an Xcode project and install AblyStep 3 – Set up environment and install Ably

To start using Ably in your JRE application, you need to include the Ably Client library. We recommend that you include the latest client library via Gradle in your project’s gradle.build file.

apply plugin: 'application'
mainClassName = 'io.ably.tutorial.Example'

repositories {
  jcenter()
}

dependencies {
    compile 'io.ably:ably-java:1.0.0'
}

In the above example a specific version of the library is referenced, however we recommend you check which is the latest stable version and always use that. Follow link to get the latest stable release for Java.

After you add necessary dependencies, you can import AblyRest class into your code and initialize it.

import io.ably.lib.rest.AblyRest;

public class Example {
  private final static String API_KEY = "INSERT-YOUR-API-KEY-HERE";

  public static void main(String[] args) {
      try {
        initAbly();
      } catch (AblyException e) {
        e.printStackTrace();
      }
  }

  private static void initAbly() throws AblyException {
      AblyRest ablyRest = new AblyRest(API_KEY);
  }
}

See this step in Github

To build your own Android Project, please visit Android Developers website and get familiar with steps necessary to set up your own application.
To start using Ably in your Android app, you need to include the Ably Client library. We recommend that you include the latest client library via Gradle in your module-level gradle.build file.

apply plugin: 'com.android.application'
...
dependencies {
    ...
    compile 'io.ably:ably-android:1.0.0'
}

In the above example a specific version of the library is referenced, however we recommend you check which is the latest stable version and always use that. Follow link to get the latest stable release for Android.

After you add necessary dependencies, you can import AblyRealtime class into your code and initialize it.

import io.ably.lib.realtime.AblyRealtime;

public class ExampleActivity extends AppCompatActivity {
  private final static String API_KEY = "INSERT-YOUR-API-KEY-HERE";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_example);
      try {
          initAbly();
      } catch (AblyException e) {
          e.printStackTrace();
      }
  }

  private void initAbly() throws AblyException {
      AblyRealtime ablyRealtime = new AblyRealtime(API_KEY);
  }
}

See this step in Github

To start using Ably in your web app, you first need to include the Ably library. We recommend that you include the latest client library from our CDN using a simple <script> tag. The client library must be instanced with the API key you copied in Step 1. Note in production we recommend you always use the token authentication scheme for browser clients, however in this example we use an API key for simplicity.

Include the code below just before your closing your HTML </html> tag.

<script src="//cdn.ably.io/lib/ably.min-1.js"></script>

<script type="text/javascript">
  var realtime = new Ably.Realtime(apiKey);
</script>

See this step in Github

To start using Ably you first need to install the Ably RubyGem. The RubyGem can be installed as follows:

gem install ably

Or if using bundler, simply add the following to your Gemfile and run bundle install:

gem 'ably'

The client library must be instanced with the API key you copied in Step 1. API keys used with basic authentication for your own servers is generally preferred, however clients running on insecure devices should always use the token authentication scheme instead. In this example, we use an API key for simplicity.

As we do not need asynchronous access to the realtime API for this tutorial, we’ll be using the simpler REST client library. However, in some cases where users want to subscribe to events asynchronously from Ruby, we recommend the use of the Realtime client library.

require 'ably'
ably = Ably::Rest.new(key: api_key)

See this step in Github

The REST library for Python is hosted on Github and is published on PyPI and can be installed as follows:

pip install ably

Then it can be imported and instantiated as follows:

from ably import AblyRest
client = AblyRest(api_key)

For the purpose of this tutorial let’s create history.py file with the code above, we’ll be using this file as base later on.

Note on string encodings

Since Ably supports both string and binary payloads, to avoid ambiguity, we recommend that strings passed to the library for publishing to Ably (eg as an event name or payload data) should be unicode strings. In Python 3 this is the normal string type, but in Python 2 it is not, so we suggest you prefix string literals with u prefix (eg u'eventname' – or alternatively, use from __future__ import unicode_literals, which will make this automatic), and to explicitly decode any user input (eg raw_input().decode(sys.stdin.encoding).

See this step in Github

To start using Ably you first need to install composer package on packagist into your composer.

composer require ably/ably-php --update-no-dev

The client library must be instanced with the API key you copied in Step 1. API keys used with basic authentication for your own servers is generally preferred, however clients running on insecure devices should always use the token authentication scheme instead. In this example, we use an API key for simplicity.

Add the following to a file named history.php to instance the Ably library inside your php script:

require_once __DIR__ . '/../vendor/autoload.php';
$ably = new \Ably\AblyRest("{{ApiKey}}");

See this step in Github

We will start by creating an Xcode project for this tutorial. To build your own Xcode Project in Swift visit Apple developer website and get familiar with steps necessary to setup your own application.
When you setup your application delete the default ViewController.swift add new File → New → File… and choose Cocoa Touch Class.

Create new Cocoa Touch Class

Name your new class “ExampleViewController” and choose Swift as language:

Name new Cocoa Touch Class

After that navigate to Main.storyboard in your project, click on the ViewController that has already been added by default during project creation and from the Utilities that are located on the right choose Identity Inspector. Find the field labeled “Class” and select “ExampleViewController”.

Interface design

See this step in Github

To start using Ably you first need to install the Ably pod via CocoaPods. You need to add a Podfile to your project directory:

touch Podfile

Then add this line to your application’s Podfile:

pod 'Ably'

Install it with:

pod install

To learn more about using CocoaPods in your project visit official CocoaPods guide.

Then in your files in which you will be using Ably import:

import Ably

To connect to Ably, you need to instance the client library with the API key you copied in Step 1. API keys used with basic authentication for your own servers is generally preferred, however clients running on insecure devices should always use the token authentication scheme instead. In this example, we use an API key for simplicity.

Add the following to the file in which you imported the Ably library:

let API_KEY = "INSERT-YOUR-API-KEY-HERE"
let client = ARTRealtime(key: API_KEY)

See this step in Github

Step 4 – Publishing messages to be stored with channel history

Before we can use the history API to retrieve previously published messages, we need to publish some messages to a channel. In the example code below, we publish 3 messages to the channel.

Channel channel = ablyRest.channels.get("persisted:sounds");

/* Publish three messages, specify event name first, then payload */
channel.publish("play", "bark");
channel.publish("play", "meow");
channel.publish("play", "cluck");

See this step in Github

public class ExampleActivity extends AppCompatActivity {
  ...
  private Channel channel;
  ...
  private void initAbly() throws AblyException {
      ...
      channel = ablyRealtime.channels.get("persisted:sounds");
  }

  private void publishMessages() throws AblyException {
      channel.publish("play", "bark");
      channel.publish("play", "meow");
      channel.publish("play", "cluck");
  }
  ...
}

See this step in Github

var channel = realtime.channels.get("persisted:sounds");
channel.publish("play", "bark");
channel.publish("play", "meow");
channel.publish("play", "cluck");

See this step in Github

channel = ably.channels.get('persisted:sounds')
channel.publish 'play', 'bark'
channel.publish 'play', 'meow'
channel.publish 'play', 'cluck'

See this step in Github

$channel = $ably->channels->get("persisted:sounds");
$channel->publish("play", "bark");
$channel->publish("play", "meow");
$channel->publish("play", "cluck");

Now you can check how it works by running php history.php in console.

See this step in Github

channel = client.channels.get('persisted:sounds')
channel.publish('play', 'bark')
channel.publish('play', 'meow')
channel.publish('play', 'cluck')

If you would like to try running this now, you can do so with python history.py.

See this step in Github

If you have not previously had a chance to build a basic user interface in Xcode, please refer to Apple developer guide on how to build a simple UI and also learn more about adding IBOutlets and IBActions.
To be able to subscribe to a channel and send some initial messages add a button that will do that. Go to your ExampleViewController and add an UIButton from Object library. Name the action “publishAction”.

Binding UI objects

Add this code to previously added IBAction:

let channel = client.channels.get("persisted:sounds")
channel.publish("play", data: "bark")
channel.publish("play", data: "meow")
channel.publish("play", data: "cluck")
See this step in Github

Step 5 – Retrieving messages from history

Now that we have published messages on a channel that is configured to store messages on disk, we can retrieve them using the history method of the channel object.

/* Fetch historical messages from channel, you can customize history query with
parameters, when no parameters are needed just pass null */
Message[] historicMessages = channel.history(null).items();
for (Message message : historicMessages) {
    System.out.println("message: " + message.id + " - " + message.data);
}

See this step in Github

private void fetchHistory() throws AblyException {
    Message[] historicMessages = channel.history(null).items();
    for (Message message : historicMessages) {
        Toast.makeText(getBaseContext(), "message: "
              + message.id + " - " + message.data), Toast.LENGHT_SHORT).show();
    }
}

See this step in Github

var channel = realtime.channels.get("persisted:sounds");
channel.history(function(err, resultPage) {
  alert("Last message published: " + JSON.stringify(resultPage.items[0].data));
});

See this step in Github

channel = ably.channels.get('persisted:sounds')
result_page = channel.history
puts "Last message published: #{result_page.items.first.data}"

See this step in Github

channel = client.channels.get('persisted:sounds')
paginatedResult = channel.history()
for message in paginatedResult.items:
    print('Last message published: {}'.format(message.data))

If you would like to try running this now, you can do so with python history.py.

See this step in Github

$channel = $ably->channels->get("persisted:sounds");
$paginatedResult = $channel->history();
foreach ($paginatedResult->items as $message) {
  echo sprintf(
    "Latest message published: %s\n",
    $message->data
  );
}

Run php history.php to see messages retrieved from channel history.

See this step in Github

We want the retrieved history to show in our ExampleViewController. In this tutorial we will load retrieved messages to a table view. Add UITableView from Object library to your view and bind it in code as “tableView” also remember to change:

class ExampleViewController: UIViewController {

To:

class ExampleViewController: UIViewController, UITableViewDataSource {

Our class has to become a delegate for the dataSource. In viewDidLoad() add this line:

tableView.dataSource = self

We will store all the messages retrieved from Ably history in array named “historyMessages”.

private var historyMessages: [String] = []

Retrieved messages will be shown in table view cells. In Interface Builder choose your tableView in Attributes Inspector find Prototype Cells and change it to 1.

Add prototype cell

Choose your prototype cell in Attributes Inspector find Style and pick “Basic” then find Identifier and change it to “Cell”.

Change cell style

Navigate to Size Inspector to find Row Height and change it’s value to 40.

Change cell height

Your class has to confirm to UITableViewDataSource protocol. To achieve that simply add these three methods to your code:

  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
      return 1
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
      return historyMessages.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath
                 indexPath: NSIndexPath) -> UITableViewCell {

      let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

      let row = indexPath.row
      cell.textLabel?.text = historyMessages[row]

      return cell
}

Your view should now look similar to this:

ExampleViewController view

To read more about using UITableView visit Apple developer guide

Now add another UIButton and bind it to an action named “retrieveHistoryAction”.
Add this code to previously added IBAction:

channel = client.channels.get("persisted:sounds")
historyMessages = []

channel.history() { (messages, error) in
    guard error == nil else {
        return self.showAlert("Error", message: "There was a an error retrieving messages history.")
    }

    let historyMessages = messages?.items as? [ARTMessage] ?? [ARTMessage]()
    historyMessages.forEach { message in
      self.historyMessages.append("\(message.data)")
    }
    self.tableView.reloadData()
  }

See this step in Github

We’re done, it’s that simple. We have now shown you how to set up a channel to use persisted history using channel rules, then we published some messages on that channel, and later retrieved them using the history API.

Live demo

In this demo we use the history API to replay up to the last 10 keys pressed on the piano. Try playing the piano, which in turn will publish a message to Ably for each key. Then press the “Replay piano from Ably history” button, which will retrieve the piano key press history on the channel and play the sequence again on the piano.

Sustain ON
Ably console:

PS. You can also open this piano in another browser window and play together using our realtime pub/sub channels.

Download tutorial source code

The complete source code for each step of this tutorial is available on Github.

We recommend that you clone the repo locally:

git clone https://github.com/ably/tutorials.git

Checkout the tutorial branch:

git checkout history-java

Then you can run project inside your console. Be sure to switch into project’s directory and then use these commands in your terminal:

./gradlew assemble
./gradlew run

Don’t forget to replace your ExampleActivity#API_KEY field with Ably API key.

The complete source code for each step of this tutorial is available on Github.

We recommend that you clone the repo locally:

git clone https://github.com/ably/tutorials.git

Checkout the tutorial branch:

git checkout history-android

And then run the demo on your Android device. Check Android Developers website if you are not familiar on how to run an Android Project. Don’t forget to replace your ExampleActivity#API_KEY field with Ably API key.

The complete source code for each step of this tutorial is available on Github.

We recommend that you clone the repo locally:

git clone https://github.com/ably/tutorials.git

Checkout the tutorial branch:

git checkout history-javascript

And then run the demo locally by adding your Ably API key to example.html and opening the page in your browser.

The complete source code for each step of this tutorial is available on Github.

We recommend that you clone the repo locally:

git clone https://github.com/ably/tutorials.git

Checkout the tutorial branch:

git checkout history-ruby

And then run the demo locally by adding your Ably API key to example.rb and running the demo bundle exec ruby example.rb

The complete source code for each step of this tutorial is available on Github.

We recommend that you clone the repo locally:

git clone https://github.com/ably/tutorials.git

Checkout the tutorial branch:

git checkout history-php

And then run the demo locally by adding your Ably API key to history.php, install the composer dependencies with:

composer install

and run this script with php history.php.

The complete source code for each step of this tutorial is available on Github.

We recommend that you clone the repo locally:

git clone https://github.com/ably/tutorials.git

Checkout the tutorial branch:

git checkout history-python

And then run the demo locally by adding your Ably API key to history.py, install the required libraries with:

pip install ably

and run this script with python history.py.

The complete source code for each step of this tutorial is available on Github

We recommend that you clone the repo locally:

git clone https://github.com/ably/tutorials.git

Checkout the tutorial branch:

git checkout history-swift

In the project directory simply run:

pod install

Open example.xcworkspace and build the demo on your preferred iPhone simulator or device. Don’t forget to replace your ExampleViewController#API_KEY field by adding your Ably API key to ExampleViewController.swift.

Next steps

1. If you would like to find out more about how to use the history API from your devices and apps, see the Realtime history documentation. Typically on servers customers prefer to use the REST history API
2. Learn more about Ably features by stepping through our other Ably tutorials
3. Gain a good technical overview of how the Ably realtime platform works
4. Get in touch if you need help