Advanced Bucket Accessors in Couchbase make it possible to access advanced key-value store (KV) functionality using the following built-in operators.

They utilize the same bucket bindings defined in the handler as Basic Bucket Accessors, but expose a richer set of options and operators that can be used to:

  1. Set or retrieve expirations
  2. Solve race conditions via CAS
  3. Manipulate hot KV items under high contention

Note that Basic Bucket Accessors are much easier to use, have a trivial API, and are also a bit faster than the corresponding Advanced Bucket Accessors.

In Couchbase Server 6.6.1 the following Advanced Bucket Accessors have been added:

These seven new Bucket Accessors make it possible to utilize and leverage CAS directly to handle contention and/or set a document expiration (or TTL) in the Data Service (or KV) via Eventing plus perform distributed atomic counter operations.

For example, rather than blindly relying on Basic Bucket Accessors for an upsert like operation src_bkt[id_str] = some_doc, the Advanced Accessors allow you to resolve contention (or possible contention) on keys that have concurrent mutations form different sources with JavaScript-driven logic in your Eventing Function.

    • If the document doesn’t exist you can use couchbase.insert(src_bkt, {"id: id_str}, some_doc) and check the return value for success
    • If the document exists you can use couchbase.replace(src_bkt, {"id: id_str, "cas": current_cas}, some_doc) and check the return value for success or a CAS mismatch.

To view complete examples including JavaScript, input mutations, output mutations and/or log messages for each Advanced Bucket Accessor, refer to Scriptlets: Advanced Accessor Handlers in the examples section of the documentation.

Advanced GET: result = couchbase.get(binding, meta)

This operation allows reading a document along with metadata from the bucket and subsequent operations to utilize CAS or check/modify the expiry_date.

Contrast this to the Basic Bucket Accessor GET operation which merely exposes a JavaScript binding or map, var adoc = src_bkt[meta.id], where the return value is just the document without any metadata.

Below is an example of the Advanced GET operation.

Some example return values:

 

Advanced INSERT: result = couchbase.insert(binding, meta, doc)

This operation allows creating a fresh document in the bucket. This operation will fail if the document with the specified key already exists. It allows specifying an expiration time (or TTL) to be set on the document.

There is no analogous Basic Bucket Accessor operation to the Advanced INSERT operation (as src_bkt[meta.id] = adoc is more like an upsert).

Below is an example of the Advanced INSERT operation.

 

Some example return values:

 

Advanced UPSERT: result = couchbase.upsert(binding, meta, doc)

This operation allows updating an existing document in the bucket, or if absent, creating a fresh document with the specified key. The operation does not allow specifying CAS (it will be silently ignored). It also allows specifying an expiration time (or TTL) to be set on the document.

Contrast this to the Basic Bucket Accessor SET operation which merely uses an exposed JavaScript map defined via a bucket binding alias src_bkt[meta.id] = adoc. For the basic SET operation there is no return value (no status and no metadata) thus no way to check the CAS value.

Below is an example of the Advanced UPSERT operation.

 

An example return value:

 

Advanced REPLACE: result = couchbase.replace(binding, meta, doc)

This operation replaces an existing document in the bucket. This operation will fail if the document with the specified key does not exist. This operation allows specifying a CAS value that must be matched as a pre-condition before proceeding with the operation. It also allows specifying an expiration time (or TTL) to be set on the document.

There is no analogous Basic Bucket Accessor operation to the Advanced REPLACE operation (as src_bkt[meta.id] = adoc is more like an upsert).

Below is an example of the Advanced REPLACE operation.

 

Some example return values:

 

Advanced DELETE: result = couchbase.delete(binding, meta)

This operation allows deleting a document in the bucket specified by key. Optionally, a CAS value may be specified which will be matched as a pre-condition to proceed with the operation.

Contrast this to the Basic Bucket Accessor DEL operation which merely uses an exposed a JavaScript binding or map, delete src_bkt[meta.id], where there is no return value (no status and no metadata).

Below is an example of the Advanced DELETE operation.

 

Some example return values:

 

Advanced INCREMENT: result = couchbase.increment(binding, meta)

This operation atomically increments the field count in the specified document. The document must have the below structure:

 

The increment operation returns the post-increment value.

If the specified counter document does not exist, one is created with count value as 0 and the structure noted above. And so, the first returned value will be 1.

Due to limitations in KV engine API, this operation cannot currently manipulate full document counters.

There is no analogous Basic Bucket Accessor operation to the Advanced INCREMENT operation.

Below is an example of the Advanced INCREMENT operation.

 

An example return value, assume you create this KEY "my_atomic_counter:1" DOC {"count": 23} if the Eventing function above is deployed the count will be immediately incremented:

 

Advanced DECREMENT: result = couchbase.decrement(binding, meta)

This operation atomically decrements the field count in the specified document. The document must have the below structure:

 

The decrement operation returns the post-decrement value.

If the specified counter document does not exist, one is created with the count value as 0 and the structure noted above. As a result, the first returned value will be -1.

Due to limitations in KV engine API, this operation cannot currently manipulate full document counters.

There is no analogous Basic Bucket Accessor operation to the Advanced DECREMENT operation.

Below is an example of the Advanced DECREMENT operation.

 

An example return value, assume you create this KEY "my_atomic_counter:1" DOC {"count": 23} if the Eventing function above is deployed the count will be immediately decremented:

 

References

 

Author

Posted by Jon Strabala, Principal Product Manager, Couchbase

Jon Strabala is a Principal Product Manager, responsible for the Couchbase Eventing Service. Before joining Couchbase, he spent more than 20 years building software products across various domains, starting with EDA in aerospace then transitioning to building enterprise software focused on what today is coined “IoT” and “at-scale data.” Jon worked for several small software consultancies until eventually starting and managing his own firm. He has extensive experience in NoSQL/NewSQL, both in contributing and commercializing new technologies such as compressed bitmaps and column stores. Jon holds a bachelor’s degree in electrical engineering and a master's in computer engineering, both from the University of Southern California, and an MBA from the University of California at Irvine.

Leave a reply