Skip to content

Instantly share code, notes, and snippets.

@danbev
Created Oct 14, 2013
Embed
What would you like to do?
Non-relational data storage for AeroGear SimplePush Server

Storing data using CouchDB

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.

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.

CHANNEL view

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});
    }
}

UAID view

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});
        }
}

Token view

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});
    }
}

UNACKS view

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 using Redis

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

Endpoint tokens are mapped to a version. This allows for easy lookups of a version for a specific token:

> get rl5828nRuadNLWw_dB3om0CchlmgR-qveWUMZ5yhccUmgTNJwnMlqCZBM1VcnrHDwRFgCluft1fZ4MDiwjHZ9w 
"1"

Token lookup

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.

ChannelId lookup

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"

UAID lookup

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment