GoGo V4 Storage & Playback Tutorial for Realtime Apps

 

These docs are for PubNub 4.0 for Go which is our latest and greatest! For the docs of the older versions of the SDK, please check PubNub 3.0 for Go.

If you have questions about the PubNub for Go SDK, please contact us at support@pubnub.com.

Requires that the Storage and Playback add-on is enabled for your key. How do I enable add-on features for my keys? - see http://www.pubnub.com/knowledge-base/discussion/644/how-do-i-enable-add-on-features-for-my-keys
PubNub's Storage and Playback feature enables developers to store messages as they are published, and retrieve them at a later time. Before using this feature it must be enabled in the PubNub Admin Console.
Being able to pull an archive of messages from storage has many applications:
  • Populate chat, collaboration and machine configuration on app load.
  • Store message streams with real-time data management.
  • Retrieve historical data streams for reporting, auditing and compliance (HIPAA, SOX, Data Protection Directive, and more).
  • Replay live events with delivery of real-time data during rebroadcasting.
As needed, specific messages can be marked "do not archive" when published to prevent archiving on a per-message basis, and storage retention time can range from 1 day to forever.
These code samples build off code defined in the Pub & Sub tutorial, so before proceeding, be sure you have completed the Pub & Sub tutorial first.
To begin, lets populate a new channel with some test publishes that we'll pull from storage using the History() method.
res, status, err = pn.History().
    Channel("history_channel").
    Count(100).
    IncludeTimetoken(true). // include timetoken with each entry
    Execute()
for i := 0; i < 500; i++ {
    pn.Publish().
        Message("message #" + strconv.Itoa(i)). // the payload (Required)
        Channel("history_channel"). // destination of the message (Required)
        ShouldStore(true). // store in history (defaults to account default)
        Meta(map[string]interface{}{
            "random": "value",
        }). // optional meta data object which can be used with the filtering ability
        UsePost(true). // use POST to publish, defaults to false.
        Execute()
}
In the above example, we subscribe to history_channel, and onConnect, we'll publish a barrage of test messages to it. You should see these messages as they are published on the console.
Now that we've populated storage, we can pull from storage using the History() method call:
res, status, err := pn.History().
    Channel("history_channel"). // where to fetch history from
    Count(2). // how many items to fetch
    Execute()

fmt.Println(res, status, err)
The response format is
[
	["message1", "message2", "message3",... ],
	"Start Time Token",
	"End Time Token"
]
By default, History() returns the last 100 messages, first-in-first-out (FIFO). Although we specified 100 for the Count, that is the default, and if we hadn't specified a Count, we would have still received 100. Try this example again, but specify 5 for Count to see what is returned.
Setting the reverse attribute to true will return the first 100 messages, first-in-first-out (FIFO). Try this example again, but specify true for Reverse to see what is returned.
The timetoken response value is a string, representing 17-digit precision unix time (UTC). To convert PubNub's timetoken to Unix timestamp (seconds), divide the timetoken number by 10,000,000 (10^7).
Given this example, you will get the last two messages published to the channel:
res, status, err := pn.History().
    Channel("history_channel").  // where to fetch history from
    Count(2). // how many items to fetch
    Execute()

fmt.Println(res, status, err)
[[498,499],14272454823679518,14272454845442942]
To page for the next 2, use the set the start attribute to start timetoken value, and request again with all other settings the same:
[[496,497],14272454791882580,14272454823679518]
As illustrated, paging with the default Reverse as true pages 2 at-a-time starting from newest, in FIFO order. If you repeat these Paging example steps with Reverse as false, you will page 2 at-a-time as well, starting instead from the oldest messages, but still in FIFO order. You will know you are at the end of history when the returned start timetoken is 0.

func getAllMessages(startTT int64) {
	res, _, _ := pn.History().
		Channel("history_channel").
		Count(2).
		Execute()

	msgs := res.Messages
	start := res.StartTimetoken
	end := res.EndTimetoken

	if len(msgs) > 0 {
		fmt.Println(len(msgs))
		fmt.Println("start " + strconv.Itoa(int(start)))
		fmt.Println("end " + strconv.Itoa(int(end)))
	}

	if len(msgs) == 100 {
		getAllMessages(start)
	}
}

getAllMessages(int64(14759343456292767))
To pull from a slice of time, just include both Start and End attributes:
res, status, err = pn.History().
    Channel("history_channel").
    Count(100).
    Start(int64(13847168620721752)). // first timestamp
    End(int64(15090358935871532)). // last timestamp
    Execute()
res, status, status := pn.History().
    Channel("history_channel").
    Count(100).
    IncludeTimetoken(true).
    Execute()

fmt.Println(res, status, err)

Retrieves up to 100 messages starting with the message stored before the start timetoken parameter value and older. In other words, the retrieval is from newest to oldest or in descending time direction.

first msg ------------ start tt ------------ last msg
               <------]

Retrieves up to 100 messages starting with the message stored at the end timetoken parameter (if one exists with that timetoken) value and newer. In other words, the retrieval is from oldest to newest or in ascending time direction.

first msg ------------ end tt ------------ last msg
                      [------------>

Retrieves up to 100 messages starting with the message stored after the start timetoken parameter value and newer. In other words, the retrieval is from oldest to newest or in ascending time direction.

first msg ------------ start tt ------------ last msg
                               [-------->

Retrieves up to 100 messages starting with the message stored at the end timetoken (if one exists with that timetoken) parameter value and older. In other words, the retrieval is from newest to oldest or in descending time direction.

first msg ------------ end tt ------------ last msg
                <------------]

Retrieves up to 100 messages starting with the message stored at the end timetoken (if one exists with that timetoken) parameter value and older but not older than the message stored after the start timetoken. In other words, the retrieval is from newest to oldest or in descending time direction ending with the message that comes after (is older) than the start timetoken value.

first msg ----- start tt -------- end tt ---- last msg
                        [   <-----------]