The examples described on this page are very simple and their only purpose is to indicate how to use some features of riak-scala-client.
These examples have been bundled as a complete example mini-app, which can be found in the examples folder of the Github project.
For this example, let's shamelessly steal the domain used by the ReactiveMongo project for their BSON Example, i.e music albums and their artists.
Let's start with the domain. For now we will be using the default spray-json
serialization support and not worry about any secondary indexes yet. A simplified domain would probably
look something like this:
A simple RiakAlbumRepository
actor would need to respond to a number of messages
and reply with some other messages. Something like:
Using the above domain and message protocol, let's write a failing unit test for the
RiakAlbumRepository
.
This is only one of the tests and without any of the test data or helper functions. Have a look at the full code for this unit test to see the rest.
With some failing unit tests in place, we can now implement the repository:
In both cases, we convert raw RiakValue
instances to instances of Album
(or Option[Album]
) by mapping over the Future
and then we register a callback
function to send the result to the actor that sent the request when the future completes successfully.
That's basically all it takes for a ery simple non-blocking Riak repository.
Note that in the above example, the StoreAlbum
message takes an instance of Album
.
This is fine for new albums but what if we wanted to update albums? The current implementation would not
send along any vclock information and, if the albums
bucket is configured to allow siblings,
this will lead to conflicts that could have been prevented.
Depending on your situation, sometimes it is a good idea to keep the values returned from a low-level
class like our album repository boxed inside a RiakMeta
instance so you can use the meta data
at a later time to perform an update. This would look something like:
And the unit tests would look something like this:
So what if we want to customize the serialization format for some reason. Let's say you are writing an enterprise app and some guy in the standards department absolutely insists on you storing all data as XML (because it is a standard!)? After grumbling to your team mates and making fun of the guy, you might come up with something like this:
This is definitely not the best (de)serialization code ever written (e.g. absolutely no error handling whatsoever) but hopefully it gives a good impression of what it would take to write custom (de)serialization code.
Riak does not exactly offer the most powerfull query API and you probably knew that when you selected Riak for your project. But sometimes a little is more than enough and, in the case of our album repository, let's say all you need is some way to get a list of all albums for a certain artist and all albums released in a certain period. Secondary indexes to the rescue!
Implementing some indexes for our Album class is very easy. Just add a RiakIndexer[T}
to the companion object (or anywhere else and import it where you need it). Something like:
This custom indexer will be automatically used whenever an Album
(or a RiakMeta[Album]
)
gets stored using one of the store
methods on RiakBucket
.
Implementing index queries in our repository is now pretty simple:
And that's it for our Riak albums repository.