History
The history feature enables you to retrieve previously sent messages.
Two minutes of message history is available to retrieve by default. This can be extended by configuring the storage options for an app.
History versus rewind
You can retrieve previously published messages using the history feature or using the rewind channel option. There are several differences between the two features that are important to be aware of:
- History can return up to 1000 messages in a single call, as a paginated list. Rewind returns at most 100 messages.
- The
history()
method can be called repeatedly with different parameters. Rewind only has an effect on an initial channel attachment. - You can define a custom start and end time to retrieve messages from using history. Rewind returns either a given number of messages, or messages up to a point in time in the past.
- History is available when using the realtime and REST interfaces of an SDK. Rewind is only available using the realtime interface.
- Only history can return previously published presence events.
Retrieve channel history
The Ably SDKs provide a straightforward API to retrieve paginated message event history. By default each page of history contains up to 100 messages and is ordered from most recent to oldest. You can retrieve channel history by using the history()
method.
The following example retrieves the latest message sent on a channel:
const realtime = new Ably.Realtime('<loading API key, please wait>');
const channel = realtime.channels.get('bet-pet-tar');
await channel.publish('example', 'message data');
const history = await channel.history();
const lastMessage = history.items[0];
console.log('Last message: ' + lastMessage.id + ' - ' + lastMessage.data);
Demo OnlyCopyCopied!
Channel history parameters
The following query parameters can be included in the options
object when making a call to history()
. Note that untilAttach
is only available when using the realtime interface of an Ably SDK:
Parameter | Description |
---|---|
start | earliest time in milliseconds since the epoch for any messages retrieved |
end | latest time in milliseconds since the epoch for any messages retrieved |
direction | forwards or backwards |
limit | maximum number of messages to retrieve, up to 1,000 |
untilAttach | when true, ensures message history is up until the point of the channel being attached. See continuous history for more info. Requires the direction to be backwards (the default). If the channel is not attached, or if direction is set to forwards , this option will result in an error. |
It is possible to use the history API to retrieve the last message published to a channel that has been persisted for up to a year with the persist-last feature, if enabled, even if there is no history available from normal persisted history (if there have been no messages published on the channel for longer than the history retention period). To do this, make a history query with limit=1
and no start
or end
time.
Continuous history
By using rewind or history’s untilAttach
, it is possible to obtain message history that is continuous with the realtime messages received on an attached channel. For example, a user joining a navigation app with traffic updates would receive the latest traffic update and be subscribed to any new traffic updates.
Rewind
If you wish to obtain history as part of attaching to a channel, you can use the rewind channel parameter. This will act as though you had attached to a channel from a certain message or time in the past, and play through all messages since that point. Rewind can only be used when first attaching to a channel.
A rewind
value that is a number (n
) is a request to attach to the channel at a position of n
messages before the present position. rewind
can also be a time interval, specifying a number of seconds (15s
) or minutes (1m
) to replay messages from.
Note that this is only available with the realtime interface.
The following example will subscribe to the channel and relay the last 3 messages:
const realtime = new Ably.Realtime('<loading API key, please wait>');
const channel = realtime.channels.get('bet-pet-tar', {
params: {rewind: '3'}
})
await channel.subscribe((message) => {
console.log('Received message: ', message)
});
Demo OnlyCopyCopied!
Note: You can also qualify a channel name with rewind when using the service without a library, such as with SSE or MQTT.
History with untilAttach
It is possible to obtain message history that is continuous with the realtime messages received on an attached channel, in the backwards direction from the point of attachment. When a channel instance is attached, it’s automatically populated by the Ably service with the serial number of the last published message on the channel. As such the serial number can be used to make a history request to the Ably service for all messages published before the channel was attached. Any new messages therefore are received in real time via the attached channel, and any historical messages are accessible via the history method.
In order to benefit from this functionality, the untilAttach
option can be used when making history requests on attached channels. If the channel is not yet attached, this will result in an error.
const realtime = new Ably.Realtime('<loading API key, please wait>');
const channel = realtime.channels.get('bet-pet-tar');
await channel.publish('example', 'message data');
await channel.attach();
const history = await channel.history({untilAttach: true});
const lastMessage = history.items[0];
console.log('Last message before attach: ' + lastMessage.data);
Demo OnlyCopyCopied!
Retrieve presence history
Retrieve presence history using the history()
method on the presence object. This enables a client to retrieve historical presence events from the channel.
The following example retrieves a paginated list of historical presence events published:
await channel.presence.enter('enter');
const history = await channel.presence.history();
console.log(history.items.length + ' presence events received in first page');
if (history.hasNext()) {
const nextHistory = await history.next();
console.log(nextHistory.items.length);
}
CopyCopied!
Presence history parameters
The following query parameters can be included in the options
object when making a call to presence.history()
:
Parameter | Description |
---|---|
start | earliest time in milliseconds since the epoch for any messages retrieved |
end | latest time in milliseconds since the epoch for any messages retrieved |
direction | forwards or backwards |
limit | maximum number of messages to retrieve, up to 1,000 |
Ordering of historical messages
The order in which historical messages are returned with history is based on the message timestamp that was assigned by the channel in the region that the message was published in. This ordering is what Ably calls the canonical global order.
It is important to note that this is not necessarily the order that messages were received by a realtime client. The order in which each realtime client receives a message depends on which region the client is in.
Ably preserves ordering for a specific publisher on a specific channel but, for example, if two publishers in regions A and B publish message-one and message-two simultaneously, then it is very possible that a subscriber in region A will receive message-one before message-two, but that a subscriber in region B will receive message-two before message-one.
There are some instances where messages will not be in canonical global order when using continuous history. Continuous history utilizes either a REST history call with the untilAttach
parameter set to true
, or the rewind feature on a realtime connection. Messages that are less than two minutes old are retrieved from live ephemeral storage and are ordered only by region. This is to ensure that they correctly mesh with the live stream of messages currently being published in that region. Messages older than two minutes are retrieved from persisted history (if it is enabled). These messages will be in canonical global order. Ably ensures that the transition between those messages retrieved from ephemeral storage, and those from persisted storage, occurs without duplication or missed messages.