A single channel is store in a single document that looks like this:
{
"_id": "7b604e3e465f0baa7ccd59830a198f5a",
"_rev": "2-f48636eeed43538d5423680ca0c5215e",
"chid": "testingChannelId",
"type": "channel",
"token": "lmG5Rk0nYgFXOWJsuxzsmY8uKeButKQGa-HmrvtpJgGrzBCpUTAUe5TxyuH5TtlmQpJLmt1MA5sJLMFfAkE5EA",
"uaid": "603cbe10-6e88-418e-92ee-18fed948bd24",
"version": "334"
}
The type
field is used to differentiate between different types, which at the moment are channel
and ack
.
We store both channels and acks is documents. Orignally the idea was to use the token
as the _id
field but there are restrictions for the value of ids which prevented them depending on the token. This might be solvable and something to look into as it might enable more efficient lookups.
To query for data we use views.
The CouchDBDataStore uses CouchDB permanent views to help query for data. The views can be found in _simplepush/design/channels and are represented as Views class.
A view contains a function that should accept a single argument: the document object. To produce results, it should call the implicitly available emit(key, value)
function. For every invocation of emit
, a result row is added to the view.
The rows in the computed table are updated automatically with any changes that have been made (additions, edits, or deletions) since the view was created.
The channel view allows us look up a saved channel document using the channelId. The map function looks like follows:
function(doc) {
if (doc.type == "channel") {
emit(doc.chid, {"doc": doc, "rev": doc._rev});
}
}
The uaid view allows us look up a saved channel document using the User Agent ID. It emits both channel document and it's revision. The map function looks like follows:
function(doc) {
if (doc.type == "channel") {
emit(doc.uaid, {"doc": doc, "rev": doc._rev});
}
}
The token view allows us look up a saved channel document using the endpointToken. The map function looks like follows:
function(doc) {
if (doc.type == "channel") {
emit(doc.token, {"doc": doc});
}
}
The unacks view allows us look up a saved acknowledgement document using the User Agent Id. The map function looks like follows:
function(doc) {
if (doc.type == "ack") {
emit(doc.uaid, {"doc": doc});
}
}
CouchDBDataStore uses Ektorp
which is a Java client library to manipulate the above data structures.
Storing data in Redis is done with the following constructs. To illustrate how data is stored redis-cli is used to show queries and their output.
Endpoint tokens are mapped to a version. This allows for easy lookups of a version for a specific token:
> get rl5828nRuadNLWw_dB3om0CchlmgR-qveWUMZ5yhccUmgTNJwnMlqCZBM1VcnrHDwRFgCluft1fZ4MDiwjHZ9w
"1"
To get the channelID for a token the following lookup is available:
> get token:lookup:rl5828nRuadNLWw_dB3om0CchlmgR-qveWUMZ5yhccUmgTNJwnMlqCZBM1VcnrHDwRFgCluft1fZ4MDiwjHZ9w
"redis"
In this case the channelId was registered as redis
, and the token is the same as in the previous example.
This enables the ability to lookup a token
and/or uaid
using a channelId
> hmget chid:lookup:redis token
1) "rl5828nRuadNLWw_dB3om0CchlmgR-qveWUMZ5yhccUmgTNJwnMlqCZBM1VcnrHDwRFgCluft1fZ4MDiwjHZ9w"
> hmget chid:lookup:redis uaid
1) "34dea956-22a6-4610-a12a-02d326ee223e"
This enables the look up of all channelIds that have been registered for a given uaid
.
> SMEMBERS uaid:lookup:34dea956-22a6-4610-a12a-02d326ee223e
1) "redis"
RedisDataStore uses Jedis
which is a Java client library to manipulate the above data structures.