Sub-document or primitives and CAS?

Hi, I’d like to read an entire dictionary primitive document, search for an entry based on a matching value and update the value in the stored dictionary using the dictionary API while preventing overwrites from other accesses.

I know I can use the CAS when dealing with entire documents but can I use it when writing back with the dictionary or collections API? Am I doing it wrong? Or in order to use CAS can I only do whole document operations?

Hi @SLam,

The various collections (CouchbaseDictionary, CouchbaseList, etc) use the SubDocument API behind the scenes. The SubDocument API is used to modify a portion of a document without sending the whole document back and forth across the wire. Per the Data Structures documentation, the operations involved with these structures all use CAS behind the scenes.

Are you experiencing a problem or is something not working how you’d expect?

I’m just trying to get a handle on the best way to find an entry in a dictionary and then update that entry if found,without the dictionary changing in between the read and the write. I don’t see how to do this with the primitive docs api.

Perhaps @jmorris or @MikeGoldsmith will chime in to correct me, but I don’t see a way to explicitly manage the CAS yourself with these classes. But since the documentation indicates that the CAS is already handled by these classes (i.e. it’s already performing locking for you), I don’t think you need to.

I think you could always fall back to reading/writing the document as if it were a plain Couchbase document (a CouchbaseDictionary behind the scenes is just a single document with an array after all) and manage the CAS that way.

Ok, but how is the CAS handled? How does the API synchronize my read and write? What is the context used to determine what CAS value is compared when?
Or should I be locking the SyncRoot for the read and write?

I’m just having a look at the source code for “Add” - https://github.com/couchbase/couchbase-net-client/blob/release27/Src/Couchbase/Collections/CouchbaseDictionary.cs#L243

It looks like it doesn’t actually look at CAS values (so perhaps the documentation needs updated). It will check to see if the dictionary key exists. If not, it will add it. If there is a race condition and it’s added in the middle of those, it looks like it will throw an exception.

For Upsert, there is no check, so it will simply succeed (MutateIn is an atomic operation) or throw an exception. Same for Remove.

There is a SyncRoot available - https://github.com/couchbase/couchbase-net-client/blob/release27/Src/Couchbase/Collections/CouchbaseDictionary.cs#L82 - so it stands to reason that you could use that. Of course, if there are OTHER processes reading/writing this document, they can ignore that lock.

Ok, thanks for taking a look. I agree. I was looking at the source too and saw no use of CAS anywhere. I’ll look at implementing my own synchronization scheme for my business logic.