6

I am trying to introduce myself to Riak with Haskell driver and I am stuck with a simple put operation. I am confused with the signature of the put function. and there isn't a single example anywhere out there.

So with this signature:

put :: (FromJSON c, ToJSON c, Resolvable c) => Connection -> Bucket 
       -> Key -> Maybe VClock -> c -> W -> DW -> IO (c, VClock)

I have a couple of questions.

What is a Maybe VClock? Do I have to generate it somehow or is it enough to just specify Nothing there? And why do I get this VClock back in the returned tuple?

Do I have to write FromJSON and ToJSON instances for every simple value I put even if it is a simple string value? Like if I want to put a value "Stitch" with the key "Name", how do I do it?

What is Resolvable instance? How do I make a Text or String value resolvable? I understand that I have to define the resolve function but I don't quite get what it means and how to do it.

Tanmay Patil
  • 6,882
  • 2
  • 25
  • 45
r.sendecky
  • 9,933
  • 9
  • 34
  • 62

2 Answers2

4

Maybe VClock is either the VClock of the object you are updating (Just vclock) or Nothing. You can specify Nothing here if there is no object for this key already in the database.

The VClock wrapped in IO (IO (c, VClock)) is the VClock of the inserted object, returned from the database.

Your datatype will need a ToJSON and a FromJSON instance to use that put function. Aeson has instructions for writing this automatically. You can store non-JSON data by using the Network.Riak.Value modules, but this is more complicated.

Resolvable is used for resolving two siblings and looks like this where a and b are MyDataTypes:

instance Resolvable MyDataType where resolve a b = a

Ideally your resolve function does something more intelligent than just picking a or b as the ordering is not guaranteed and may be called multiple times if there are multiple siblings.

here is some code for creating a pool of Riak connections you may find useful.

You will end up with something that looks like this:

put conn bucket key Nothing value Quorum Quorum

where value is your data. More on Quorum here.

Chris Biscardi
  • 3,148
  • 2
  • 20
  • 19
  • Thank you for the answer.I kind of got the VClock. I got that value has to be a JSON. I understand Quorum too. But I did not get the `Resolvable` side of it. So every time I insert a value I have to make it an instance of `Resolvable` and implement `resolve` function, is this correct? So how do I write this `resolve` function? Can you show a simple example, please? – r.sendecky Apr 23 '14 at 04:33
3

I hope following code of simple put and get operation may help you:

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE UndecidableInstances #-}

module Main where
import Data.Aeson
import qualified Network.Riak as Riak 
import Network.Riak.Types
import Data.ByteString.Char8 hiding (putStrLn)
import Data.ByteString.Lazy as L hiding (pack,putStrLn)
import GHC.Generics hiding (R)

-- convert String to lazy ByteString
toBS :: String -> L.ByteString
toBS str = L.fromChunks (pack (str):[])

putBucket :: Bucket
putBucket = toBS "Bucket"

putKey :: Key
putKey = toBS "key"

r :: R
r = Default

w :: W
w = Default

dw :: DW
dw = Default

rw :: RW
rw = Default 

-- declare a data and create its instances
data Coord = Coord { x :: Double, y :: Double } deriving (Generic, Show)

instance FromJSON Coord

instance ToJSON Coord

instance (Show Coord) => Riak.Resolvable Coord where
    resolve a b = a

value :: Coord
value = Coord {
  x = 2.2,
  y = 3.3
}


main :: IO ()
main = do
    -- establish a connection
    let client = Riak.defaultClient
    con <- Riak.connect client
    -- simple put operation
    put_ret <- (Riak.put con putBucket putKey Nothing value w dw)
    putStrLn (show put_ret)
    buckets <- Riak.listBuckets con
    print buckets
    -- simple get operation
    get_ret <- (Riak.get con putBucket putKey r) :: IO ( Maybe (Coord, VClock))
    putStrLn (show get_ret)
    -- delete a value
    Riak.delete con putBucket putKey rw
    -- if try to get that value we will find "Nothing"
    get_ret <- (Riak.get con putBucket putKey r) :: IO ( Maybe (Coord, VClock))
    putStrLn (show get_ret)
    -- print the final bucket list
    buckets <- Riak.listBuckets con
    print buckets
safat siddiqui
  • 311
  • 1
  • 3
  • 7