Search code examples
scalariakcrdt

Riak Dataypes: default values vs non-existing keys


It seems that Riak Datatype API does not allow to distinguish between non-existing keys and default values. For example, if I query for non-existing key as follows:

val fetchOp = new FetchCounter.Builder(key).build()
val c = client.execute(fetchOp).getDatatype

I'll get a counter that holds 0. Now, if I put counter with value 0 at this key and run the query, I get the same result. Is there any way to distinguish between these two different states?

Note: when working with sets there is a context that I can check. If I fetch a set and the context is null, it means that the set does not exist under this key. This trick does not work for counters though, as they do not maintain context.

Update: Dmitri's suggestion below leads to the following solution:

val fetchOp = new FetchValue.Builder(location).withOption(FetchValue.Option.HEAD, java.lang.Boolean.TRUE).build()
val res = client.execute(fetchOp) // res.isNotFound should equal(true)

However, the downside is that now I need to make an additional query.


Solution

  • From what I understand, this is a limitation of that particular client (what language is that, by the way?). Feel free to open an issue on Github for it.

    The HTTP API, at least, does distinguish between a non-existent counter and a counter whose value happens to be 0.

    For example, here's the result of trying to access an existing key (with a value set to 0):

    $ curl http://localhost:8098/types/counters/buckets/room_occupancy/datatypes/room-215 -v
    > GET /types/counters/buckets/room_occupancy/datatypes/room-215 HTTP/1.1
    > Accept: */*
    > 
    < HTTP/1.1 200 OK
    < Vary: Accept-Encoding
    * Server MochiWeb/1.1 WebMachine/1.10.8 (that head fake, tho) is not blacklisted
    < Server: MochiWeb/1.1 WebMachine/1.10.8 (that head fake, tho)
    < Date: Thu, 20 Aug 2015 03:38:56 GMT
    < Content-Type: application/json
    < Content-Length: 28
    < 
    * Connection #0 to host localhost left intact
    {"type":"counter","value":0}
    

    And here's the result of retrieving the value of a non-existent key:

    curl http://localhost:8098/types/counters/buckets/room_occupancy/datatypes/non-existent-room -v
    > GET /types/counters/buckets/room_occupancy/datatypes/non-existent-room HTTP/1.1
    > User-Agent: curl/7.37.1
    > Host: localhost:8098
    > Accept: */*
    > 
    < HTTP/1.1 404 Object Not Found
    < Vary: Accept-Encoding
    * Server MochiWeb/1.1 WebMachine/1.10.8 (that head fake, tho) is not blacklisted
    < Server: MochiWeb/1.1 WebMachine/1.10.8 (that head fake, tho)
    < Date: Thu, 20 Aug 2015 03:32:51 GMT
    < Content-Type: application/json
    < Content-Length: 37
    < 
    {"type":"counter","error":"notfound"}
    

    There's a workaround you can do with your existing client, however.

    You can issue a regular Fetch Object operation (preferably setting the 'HEAD only' option to true) for that counter. A Riak counter (or any other data type) still exists as a regular object, and you can issue a HEAD request to it (as opposed to a Fetch Counter or whatever), and it'll return a 404 as expected.