As a follow to the previous DP2 in June, we are releasing another developer preview, DP3. This developer preview, adds a plethora of bug fixes, features and most importantly, changes to the public API by way of a) providing methods for working with “documents” and b) changing the way a cluster object is instantiated. We have also moved the repo from CouchbaseLabs to Couchbase proper on Github; I’ll touch on that a bit later.
Documents, Documents Everywhere!
One of the major changes in this developer preview and a departure from the earlier .NET SDK, is the evolution of Couchbase from a Key/Value store to a document database – which in turn is reflected in the public API’s. What this means is that we now have methods that take and return a document object rather than a K/V pair. All of the other Couchbase goodness like CAS and durability constraints and other features are still provided, but we now wrap them in to a single “document” object, from which by settings the various properties, you get the behavior that you desire.
To support the “document” concept, a series of document based methods were add to the IBucket interface that support a new Document
The result of a call using one of these new document methods is a DocumentResult
For example, here is how you would now (using DP3) store a JSON document in Couchbase using the Upsert method:
If you’re wondering, Upsert() is a method which either inserts or updates a document depending upon if it exists or not. Other document based methods include:
- Insert(): insert a document, failing of it exists.
- Replace(): replace an existing document, failing if it doesn’t exist.
- Remove(): removes a document if it exists.
- GetDocument(): returns a document for a given id.
Does this mean that Couchbase is no longer supporting the traditional K/V based Memcached operations? Absolutely not! The API’s will still support these operations, however, the hope is that the new “document” based approach will make it easier for developer’s to use the API’s and Couchbase in general for a wider range of applications. At the least it should make the semantics of working with JSON documents simpler to grasp and more intuitive.
Singleton’s? We Don’t Need No Stink’n Singleton’s!
In DP1 and DP2 to instantiate a CouchbaseCluster object, since it was a lazy-loaded Singleton, you would first create a ClientConfiguration and pass it into the static Initialize() method and then call Get() on the CouchbaseCluster class to get a reference to the cluster object. While the intention was good (ensure that the CouchbaseCluster is a global object), the tradeoffs made it less than a stellar design choice: it meant you could have one and only one CouchbaseCluster object per AppDomain (what if you had two separate Couchbase clusters you were using in a single app?) and it was a bit of a funky way to get started using a bucket – an uncomfortable programming experience.
In DP3 we decided to do away with the explicit requirement for a Singleton and instead split the class into a standard CouchbaseCluster class, with no limits to number that could be instantiated and a ClusterHelper class which is a wrapper singleton around CouchbaseCluster in the case you wanted to be assured that only on instance would be created. The best of both worlds.
Here is an example of creating a CouchbaseCluster object in DP3:
Here is an example of using the ClusterHelper class to ensure that only a single CouchbaseCluster object would be created per AppDomain:
var cluster = ClusterHelper.Get();
If you’re wondering why we even include a ClusterHelper object? It’s because the CouchbaseCluster object is a very expensive object to create and works best when it’s created when the application starts and is destroyed when the application ends. I’ll have more about that in a future post!
Try It Out (and Please Provide Feedback)!
Download the binaries below or checkout the source on Github and let us know what you think. Also, don’t forget that this is pre-release and things will definitely change before Beta and GA. Most of the changes will be internally, especially around the IO portions and namespaces. Depending upon community feedback the public interfaces may change as well.
Please, please do not use this in production either, while the base functionality works, the code has yet to make through and exhaustive set of situational tests, so things will like fail during a Failover/Swap/Rebalance scenario.