Brian,

In StoreObject's execute() method, this condition, is it a bug or intended?

        ...
        ...
        if (!doNotFetch) {
            resolved = fetchObject.execute();
            vclock = fetchObject.getVClock();
        }
        ...
        ...

My reasoning is: if do not fetch then shouldn't the resolved object be the one passed? I'm doing some tests and if I do store a mutation returning the body without fetching, I get a new mutated object and not the one I passed + mutation. So I'm wondering if that was the original intention.

Thanks,

Guido.

On 11/08/13 18:49, Guido Medina wrote:
Hi Brian,

I probably asked a similar question before, let's say you have an in-memory cache and a single writer (I know, not the best distributed design), if you do the following, take into account that we use mutations but we have no siblings enabled:

/bucket.store(record).returnBody(true).withoutFetch().withMutation(myMutation);/

Will it do the following?

 1. Not fetch the object from Riak?
 2. Mutate the passed object?
 3. Return the mutated object?

I know I can probably go and see the source code, so to save sometime don't worry about the specifics, a yes no with a very short reason of why not will suffice.

Thanks,

Guido.


On 11/08/13 18:11, Brian Roach wrote:
Matt,

The original design of StoreObject (which is what Bucket.store()
returns) was that it would encapsulate the entire read/modify/write
cycle in a very Java-y / enterprise-y way. This is why it takes a
Resolver and a Mutator; it does a fetch, resolves conflicts, passes
the resolved object to the Mutator, then stores the result of the
mutation to Riak.

Several users put in requests to make the fetch/resolve portion of
that optional as they had a workflow where that wasn't ideal and
didn't wanted to store a previously fetched value without fetching it
again. This is why the 'withoutFetch()' method was introduced along
with the @RiakVClock annotation.

When using withoutFetch() no fetch is performed, and no conflict
resolution occurs. Any ConflictResolver you pass in is simply not used
/ ignored ... except possibly if you're using returnBody()

Your code here:

bucket.store(record).returnBody(true).withoutFetch().withResolver(myConflictResolver);

is not doing a fetch or conflict resolution before storing your data.
It's just storing `record` in Riak. If that POJO has a vclock from a
previous fetch available via a @RiakVClock annotated field it will be
used. Otherwise, you're doing a store without a vclock.

I suspect where your confusion is stemming from is that you've also
specified 'returnBody()' and you're creating a sibling in that store
operation. When that's the case the "body" is going to be multiple
objects (all the siblings) which require resolution as
StoreObject.execute() only returns a single object back to the caller.
The same Resolver used if you had done the pre-fetch is employed. If
you haven't passed in a Resolver then the DefaultResolver is used
which ... isn't really a "resolver" - it simply passes through an
object if there's only one, or throws an exception if there's multiple
(siblings) present.

Thanks,
- Roach




On Sun, Aug 11, 2013 at 5:41 AM, Guido Medina<[email protected]>  wrote:
Hi Matt,

Like Sean said, you should have a mutator if you are dealing with conflict
resolution in domain objects; a good side effect of using a mutator is that
Riak Java client will fetch-modify-write so your conflict resolver will be
called once(?), if you don't use mutators, you get the effect you are
describing(?) or in other words, you have to treat the operations as
non-atomic and do things twice.

There are two interfaces for mutations: Mutation and
ConditionalStoreMutation, the 2nd interface will write only if the object
was actually mutated, you must return true or false to state if it was
mutated or not, which can be helpful if you are "mutating" an object and you
discover the change you are requesting to make was already in place, then to
save I/O, siblings creation and all implied on a write operation you decide
not to write back.

Mutation and conflict resolution are two separate concerns, but if you
specify a mutator and a conflict resolver, conflict resolution will happen
after the object is fetched and it is ready to be modified, which will
emulate an atomic operation if you use a domain object.

If you use a raw RiakObject, you must fetch, resolve the conflicts and on
the write operation pass the VClock which is not a trivial nor easy to
understand in code.

HTH,

Guido.



On 11/08/13 03:32, Sean Cribbs wrote:

I'm sure Roach will correct me if I'm off-base, but I believe the store
operation does a fetch and resolve before writing. I think the ideal way to
do that is to create a Mutation<T> (T being your POJO) as well, in which
case it's less of a "store" and more of a "fetch-modify-write". The way to
skip the fetch/modify is to use the withoutFetch() option on the operation
builder.


On Sat, Aug 10, 2013 at 6:50 PM, Matt Painter<[email protected]>  wrote:
Hi,

I've just rolled up my sleeves and have started to make my application
more robust with conflict resolution.

I am currently using a @RiakVClock in my POJO (I need to think more about
whether the read/modify/write approach is preferable or whether I'd have to
rearchitect things).

I read in the Riak Handbook the recommendation that conflicts are best
resolved on read -  not write - however the example App.java snipping on the
Storing data in Riak page in the Java client's doco uses a resolver on both
the store() and fetch() operations.

Indeed, if I don't specify my conflict resolver in my store(), things blow
up (in my unit test, mind - I'm still getting my head around the whole area
so my test may be a bit contrived).

However when I use it in both places, my conflicts are being resolved
twice. Is this anticipated?

My store is:


bucket.store(record).returnBody(true).withoutFetch().withResolver(myConflictResolver);

and my fetch is:

bucket.fetch(id, Record.class).withResolver(myConflictResolver).execute();

The order of operations in my test is:

Store new record
Fetch the record as firstRecord
Fetch the record as secondRecord
Modify a field on firstRecord and secondRecord
Save firstRecord
Save secondRecord - this invokes my resolver with two siblings
Read record - this also invokes my resolver with the two siblings

Am I missing something? Or is this what's supposed to happen? I'm not too
worried - the double-handling is hardly that intensive - but I'm keen to get
it right.

Thanks in advance,
Matt

_______________________________________________
riak-users mailing list
[email protected]
http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com


--
Sean Cribbs<[email protected]>
Software Engineer
Basho Technologies, Inc.
http://basho.com/


_______________________________________________
riak-users mailing list
[email protected]
http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com



_______________________________________________
riak-users mailing list
[email protected]
http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com

_______________________________________________
riak-users mailing list
[email protected]
http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com


_______________________________________________
riak-users mailing list
[email protected]
http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com

Reply via email to