Introduction

A newer version of this software is available

You are viewing the documentation for an older version of this software. To find the documentation for the current version, visit the Couchbase documentation home page.

This guide provides information for developers who want to use the Couchbase Ruby SDK to build applications that use Couchbase Server.

Getting Started

Now that you’ve installed Couchbase and have probably created a cluster of Couchbase servers, it is time to install the client library for Ruby, and start manipulating data.

Here’s a quick outline of what you’ll learn in this article:

  1. Installing the Ruby Couchbase Client (Gem) Couchbase.

  2. Writing a simple program to demonstrate connecting to Couchbase and saving some data.

  3. Exploring some of the API methods that will take you further than the simple program.

This section assumes that you have installed Couchbase Ruby SDK and you have installed the Couchbase server on your development machine. We assume you have at least one instance of Couchbase Server and one data bucket established. If you need to set up these items in Couchbase Server, you can do with the Couchbase Administrative Console, or Couchbase Command-Line Interface (CLI), or the Couchbase REST API. For information and instructions, see:

The TCP/IP port allocation on Windows by default includes a restricted number of ports available for client communication. For more information on this issue, including information on how to adjust the configuration and increase the available ports, see MSDN: Avoiding TCP/IP Port Exhaustion.

After you have your Couchbase Server set up and you have installed the Couchbase SDK, you can compile and run the following basic program.

Installing the Couchbase Client Library

Before continuing you should ensure you have a working Ruby environment up and running. We recommend the following:

You can verify that Ruby and RubyGems are installed by typing the following commands:

shell> ruby -v

and

shell> gem --version

The Ruby version should be 1.8.7 or higher. Rubygems must be 1.3.6 or higher.

  1. Install the package libevent.

  2. Then install the Couchbase C Client library, libcouchbase

  3. The next step is to install libvbucket which is also part of the Couchbase client library.

  4. You may need to install rubygems as well, if not already installed.

  5. Once you have Rubygems installed you can simply use it to install Couchbase as below.``` shell> gem install couchbase

    <a id="couchbase-sdk-ruby-getting-started-hello"></a>

Hello Couchbase

Let’s look at a very simple Ruby program to interact with Couchbase. We want to set a key and on subsequent runs of the application we will output the key if it exists or create it if it does not. We’ll also set a Time to Live (TTL) so that the key we set will expire after 10 seconds.

If you want to follow along with this example, to make things easier we’ve provided a repository of the code used in this tutorial. To that we’ve added a Gemfile for use with Bundler.

If you want a head start you can grab the example code and get going straight away. Open up a new Terminal window and type the following: shell> git clone git@github.com:avsej/couchbase-examples-ruby.git shell> cd couchbase-examples-ruby shell> sudo bundle install

Now that you have a copy of the code, let's look at what's happening.

Listing 1: `Gemfile`

In the above, we simply require all Gem dependencies for the `hello-world.rb`
example. If you didn't have them already they will be installed when you run
`bundle install` as below.

shell> sudo bundle install

or, if you have already installed the dependencies, you can run the sample
program by simply running the command

shell> ruby hello-world.rb

Listing 2: `hello-world.rb`

require ‘rubygems’ require ‘couchbase’

client = Couchbase.connect(“http://127.0.0.1:8091/pools/default”) client.quiet = false begin spoon = client.get “spoon” puts spoon rescue Couchbase::Error::NotFound => e puts “There is no spoon.” client.set “spoon”, “Hello World!”, :ttl => 10 end

The first 3 lines are some bootstrap code for `Bundler`, to load it and then
have it load all the Gems specified in our `Gemfile`.

We then create a new connection to our Couchbase Server. Remember to change the
connection details `127.0.0.1:8091` if you are working with couchbase remotely
or on another port.

The last few lines are the meat of what's happening, let's go through them in
more detail:

begin … rescue Couchbase::Error::NotFound => e … end

If we try to retrieve a key from Couchbase that does not exist it will raise a
`Couchbase::Error::NotFound` error. So to be able to handle this we start a
begin/rescue block and specify we want to only rescue from that error.

spoon = client.get “spoon” puts spoon

Now we attempt to `get` the contents of the key "spoon". If it exists, we
continue and output the value of that key.

puts “There is no spoon.” client.set “spoon”, “Hello World!”, 10

Lastly if the key doesn't exist and our attempt to `get` raises a
`Couchbase::Error::NotFound` error then our rescue block will be triggered. In
which we're just outputting to the terminal again and then setting a value for
our key "spoon". For the purposes of the example we're passing a 3rd (optional)
paramter to the `set` method specifying a `TTL` Time to Live (expiry time in
seconds).

That's it. We're ready to run our first Couchbase program.

shell> ruby hello-world.rb

The first time you run the program it should produce the following output

shell> ruby hello-world.rb There is no spoon.

If you are to run it again within 10 seconds it should produce this output

shell> ruby hello-world.rb Hello World!

If you are to run it after 10 seconds it should produce the following output
based on the Time To Live (TTL) specified.

shell> ruby hello-world.rb There is no spoon. ```

Way to go! You’ve just interacted with Couchbase for the first time. We’ve looked at getting and setting the value of a key and expiring the cache.

Conclusion

You now know how to obtain the Ruby Couchbase Client, and write small Ruby programs to connect with your Couchbase cluster and interact with it. Congratulations, you will be able to save your servers from burning down, and impress your users with the blazing fast response that your application will be able to achieve.

Couchbase and Rails Tutorial

Now that you’ve installed Couchbase and have probably created a cluster of Couchbase servers, it is time to install the client library library, and start manipulating the data.

Here’s a quick outline of what you’ll learn in this article:

  1. Install the Ruby Couchbase Client (Gem) Dependencies Couchbase.

  2. Write a more advanced program using Rails to connect, save and update data in couchbase

This section assumes that you have installed Couchbase Ruby SDK and you have installed the Couchbase server on your development machine. We assume you have at least one instance of Couchbase Server and one data bucket established. If you need to set up these items in Couchbase Server, you can do with the Couchbase Administrative Console, or Couchbase Command-Line Interface (CLI), or the Couchbase REST API. For information and instructions, see:

After you have your Couchbase Server set up and you have installed the Couchbase SDK, you can compile and run the following basic program.

Installing the Couchbase Client Library Dependencies

Before continuing you should ensure you have a working Ruby environment up and running. We recommend the following:

Example Rails Application (Squish)

For the purposes of this tutorial, we have specially prepared an example application for you to follow along with. You can download Squish from Github. Squish is a simple URL shortener implemented with Couchbase.

To get started, lets first get the source code. Open up a new Terminal window and type the following:

shell> git clone git://github.com/couchbaselabs/couchbase-squish.git
shell> cd couchbase-squish
shell> bundle install

Now that you have the source and all of the dependencies, we can start the application and see what’s happening.

shell> rails server

In a URL shortening application there are a number of features we would like to accomplish. Let’s define what they are:

  • User should be able to save a valid URL. client.set

  • User can visit the shortened URL and is redirected to the long one. client.get

  • A user visiting a URL should increment number of hits for a given URL. client.set

Not your mother’s ActiveRecord

Rails is based on conventions, one of those is that you’ll want to be using a SQL database. We don’t. So what things should we do differently.

Listing 1: Gemfile

source 'http://rubygems.org'

# Rails 3.1, Asset Pipeline and Javascript
gem 'rails', '3.1.0'
group :assets do
  gem 'sass-rails', "  ~> 3.1.0"
  gem 'coffee-rails', "~> 3.1.0"
  gem 'uglifier'
end
gem 'jquery-rails'

# Required to give an executable JS environment
# in Production on Heroku
group :production do
  gem 'therubyracer-heroku', '0.8.1.pre3'
end

# Development / Test only.
group :development, :test do
  gem 'ruby-debug'
end
group :test do
  gem 'turn', :require => false
end

# Squish Application Dependencies
gem "couchbase", 1.0.0
gem "validate_url"

The major difference from this Gemfile and a freshly generated Rails application is that we’re not using sqlite and we have required couchbase instead.

Listing 2: config/application.rb

require File.expand_path('../boot', __FILE__)

  # require 'rails/all'
  #
  # require "active_record/railtie"
  require "action_controller/railtie"
  # require "action_mailer/railtie"
  # require "active_resource/railtie"
  # require "rails/test_unit/railtie"

  if defined?(Bundler)
    # If you precompile assets before deploying to production, use this line
    # Bundler.require *Rails.groups(:assets => %w(development test))
    # If you want your assets lazily compiled in production, use this line
    Bundler.require(:default, :assets, Rails.env)
  end

  module CouchbaseTinyurl
    class Application  Rails::Application
      # ...
      config.encoding = "utf-8"

      # Configure sensitive parameters which will be filtered from the log file.
      config.filter_parameters += [:password]

      # Enable the asset pipeline
      config.assets.enabled = true
    end
  end

Out of the box, Rails will require rails/all which will load all aspects of Rails. For this application we only need action_controller. This cuts the boot time down significantly.

Listing 3: config/environments/development.rb

CouchbaseTinyurl::Application.configure do
  # ...
  # config.action_mailer.raise_delivery_errors = false
  # ...
end

One last thing to ensure unloading all those other Rails modules doesn’t hurt us. We need to remove the action_mailer configuration options for Development and Test environments.

Now that we’ve got our application configured just right for using Couchbase we can start connecting with the server. You would connect to the address of the server (in this case it is 127.0.0.1 which is the IPV4 address of localhost.

Connecting to Couchbase

Listing 5: app/models/couch.rb

module Couch

      class << self

        def domain
          return "http://#{ENV['COUCHBASE_DOMAIN']}" if ENV['COUCHBASE_DOMAIN']
          case Rails.env.to_s
            when "production"  then "http://127.0.0.1"
            when "test"        then "http://127.0.0.1"
            when "development" then "http://127.0.0.1"
          end
        end

        def client
          @client ||= Couchbase.new "#{domain}:8091/pools/default"
        end

      end

    end

Because we have the concept of an environment in Rails, we wrote this small module to enable us to configure where our couchbase instance is located. Then throughout our code we can reference Couch.client which will return our Couchbase Client object.

Defining an API

Just because we aren’t using ActiveRecord doesn’t mean we can’t have a nice API, thanks to ActiveModel we can very easily create a simple Model to encapsulate our Link object. What would such an API look like? Let’s define how we would interact with a Couchbase model from our Controller.

Listing 6: app/controllers/links_controller.rb

class LinksController < ApplicationController
  def create
    @link = Link.new(params[:link])
    @link.session_id = session[:session_id]
    if @link.save
      respond_to do |format|
        format.html { redirect_to @link }
        format.js
      end
    else
      respond_to do |format|
        format.html { render :new }
        format.js
      end
    end
  end

  def short
    @link = Link.find(params[:id])
    redirect_to root_path unless @link
    @link.views += 1
    @link.save
    redirect_to @link.url
  end

  def show
    @link = Link.find(params[:id])
  end

  def new
    @link = Link.new
  end
end

So, in looking at our sketched out Controller above we can see how we would like to interact with our Link object.

  • We can initialize a new Link with a Hash of attributes. e.g. Link.new( params[:link] )

  • We can access and set a Link ’s attributes. e.g. @link.session_id = session[:session_id]

  • We can save a new Link to couchbase. e.g. @link.save

  • We can find and instantiate a Link object. e.g. Link.find( params[:id] )

Defining a Couchbase Model

Now that we know what kind of an API we want to expose from our Link Model, let’s define it.

Listing 7: app/models/link.rb

class Link

  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Callbacks
  extend ActiveModel::Naming

  # Couch Model

  attr_accessor :url, :key, :views, :session_id, :created_at

  define_model_callbacks :save
  validates :url, :presence => true, :url => {:allow_nil => true, :message => "This is not a valid URL"}
  before_save :generate_key

  def generate_key
    while self.key.nil?
      random = SecureRandom.hex(2)
      self.key = random if self.class.find(random).nil?
    end
  end

  # ActiveModel

  def initialize(attributes = {})
    @errors = ActiveModel::Errors.new(self)
    attributes.each do |name, value|
      setter = "#{name}="
      next unless respond_to?(setter)
      send(setter, value)
    end
    self.views ||= 0
    self.created_at ||= Time.zone.now
  end

  def to_param
    self.key
  end

  def persisted?
    return false unless (key && valid?)
    # TODO need a better way to track if an object is *dirty* or not...
    self.class.find(key).url == self.url
  end

  def save
    return false unless valid?
    run_callbacks :save do
      Couch.client.set(self.key, {
        :type => self.class.to_s.downcase,
        :url => self.url,
        :key => self.key,
        :views => self.views,
        :session_id => self.session_id,
        :created_at => self.created_at
      })
    end
    true
  end

  def self.find(key)
    return nil unless key
    begin
      doc = Couch.client.get(key)
      self.new(doc)
    rescue Couchbase::Error::NotFound => e
      nil
    end
  end

end

Might seem like a lot to take in at once, let’s break it down into the three main responsibilities of the Class.

  • Creating a basic ActiveModel implementation to integrate with Couchbase

  • Defining some Model logic for the Link.

Couchbase + ActiveModel

Listing 7a: app/models/link.rb [line:3..6]

include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Callbacks
extend ActiveModel::Naming

Firstly we include all the aspects of ActiveModel that we would like to use.

Listing 7b: app/models/link.rb [line:8]

attr_accessor :url, :key, :views, :session_id, :created_at

Our model needs some Attributes so we define them.

Listing 7c: app/models/link.rb [line:23..32]

def initialize(attributes = {})
    @errors = ActiveModel::Errors.new(self)
    attributes.each do |name, value|
      next unless @@keys.include?(name.to_sym)
      send("#{name}=", value)
    end
    self.views ||= 0
    self.created_at ||= Time.zone.now
  end

In our initialize method we are doing the following:

  • Initializing an ActiveModel::Errors object that will work with the validations we’ll define later.

  • Iterating through the Hash of attributes passed in. We check if our list of attribute keys and if it matches we assign that attribute to the passed in value.

Listing 7d: app/models/link.rb [line:34..36]

def to_param
             self.key
           end

To work with rails link_to methods we need to implement this method. As we would like to use our generated key.

Listing 7e: app/models/link.rb [line:38..42]

def persisted?
             return false unless (key && valid?)
             # TODO use a better way to track if an object is *dirty* or not...
             self.class.find(key).url == self.url
           end

So that our Link objects know wether they are a new? object or not, we implemented this method. There are better ways to track this, just to demonstrate things working, once a Link is valid? we are checking to see if the object has been persisted and that the url matches.

Listing 7f: app/models/link.rb [line:44..56]

def save
   return false unless valid?
   run_callbacks :save do
     # TODO should client.set return nil if successful? don't think so
     Couch.client.set(self.key, {
       :type => self.class.to_s.downcase,
       :url => self.url,
       :key => self.key,
       :views => self.views,
       :session_id => self.session_id,
       :created_at => self.created_at
     })
   end
 end

Saving a complex document to Couchbase is a simple as passing a Hash of attributes as the second parameter to client.set(key, value).

Listing 7g: app/models/link.rb [line:58..66]

def self.find(key)
   return nil unless key
   begin
     doc = Couch.client.get(key)
     self.new(doc)
   rescue Couchbase::Error::NotFound => e
     nil
   end
 end

Here we’ve implemented a simple find method that will get a given document from couchbase based on the key. It’s worth noting that Couchbase will raise an error if the document you’re trying to access doesn’t exist in which case we rescue and return a nil.

Everything we’ve done up to now is providing a bit of framework to our code to allow us to create our Link object.

Listing 7h: app/models/link.rb [line:8..19]

attr_accessor :url, :key, :views, :session_id, :created_at

define_model_callbacks :save
validates :url, :presence => true, :url => {:allow_nil => true}
before_save :generate_key

def generate_key
  while self.key.nil?
    random = SecureRandom.hex(2)
    self.key = random if self.class.find(random).nil?
  end
end

What we are left with here is quite simple, we’ve already mentioned defining the attributes. Next, we’re telling ActiveModel that it should give us a callback to bind to for the save method of a Link. Next we setup a validation on the url attribute, we’re using the built-in presence validator and we’ve included a third party validation by way of the validate_url Gem. Finally we setup our save callback to call the generate_key method which takes care of creating a unique short key for our Links.

Conclusion

And that’s it. You now know how to install all the dependencies for working with Couchbase and Rails. You can integrate Couchbase with your Rails projects, whilst keeping a decent object orientated structure and we’ve started to explore some of the other features of Couchbase.

Ruby Method Summary

The Ruby Client Library supports the full suite of API calls to Couchbase.

Synchronous Method Calls

The Ruby Client Library supports the core Couchbase API methods as direct calls to the Couchbase server through the API call. These direct methods can be used to provide instant storage, retrieval and updating of Couchbase key/value pairs.

For example, the following fragment stores and retrieves a single key/value pair:

couchbase.set("foo", 3600, value);

foo = couchbase.get("foo");

In the example code above, the client will wait until a response has been received from one of the configured Couchbase servers before returning the required value or an exception.

Asynchronous Method Calls

In addition, the library also supports a range of asynchronous methods that can be used to store, update and retrieve values without having to explicitly wait for a response. For asynchronous operations, the SDK will return control to the calling method without blocking the current thread. You can pass the block to a method and it will be called with the result when the operations completes. You need to use an event loop, namely an event loop in the form of a run.. do |return| block to perform asynchronous calls with the Ruby SDK:

couchbase = Couchbase.connect(:async => true)

couchbase.run do |conn|
      conn.get("foo") {|ret| puts ret.value}
      conn.set("bar", "baz")
end

The asynchronous callback will recieve an instance of Couchbase::Result which can respond to several methods:

  • success? : Returns true if asynchronous operation succeeded.

  • error : Returns nil or exception object (subclass of Couchbase::Error::Base) if asynchronous operation failed.

  • key : Returns key from asynchronous call.

  • value : Returns value from asynchronous call.

  • flags : Returns flags from asynchronous call.

  • cas : CAS value obtained from asynchronous call.

  • node : Node used in asynchronous call.

  • operation : Symbol representing the type of asynchronous call.

Ruby — Connection Operations

Creates a connection with the Couchbase Server. There are several ways to establish new connection to Couchbase Server. By default a Couchbase SDK uses the http://localhost:8091/pools/default/buckets/default as the endpoint. The client will automatically adjust configuration when the cluster rebalances, when the cluster returns from failover, or when you add or delete nodes. Returns the exception object Couchbase::Error::Connect if it fails to connect. The following creates a default connection:

c = Couchbase.connect
c2 = Couchbase.new

Note that Couchbase.new is a new alias for connect, as of the 1.1 version of the Ruby SDK.

The following are equivalent alternatives to connect to the same node, using different syntax:

#creates connection to the default bucket on default node
c = Couchbase.connect("http://localhost:8091/pools/default/buckets/default")

#shorter method to connect to default bucket
c = Couchbase.connect("http://localhost:8091/pools/default")

#connecting to default bucket
c = Couchbase.connect("http://localhost:8091")

#connecting via default port to default bucket
c = Couchbase.connect(:hostname => "localhost")

#provide host and port as Ruby symbols
c = Couchbase.connect(:hostname => "localhost",
                      :port => 8091)

c = Couchbase.connect(:pool => "default", :bucket => "default")

You can also provide a list of possible nodes to connect to in order to avoid a failure to connect due to a missing node. After your Couchbase client successfully connects, it will use the most current cluster topology, not this list, to connect to a node after rebalance or failover. To provide multiple possible nodes for initial connection:

c = Couchbase.connect(:bucket => "mybucket",
                      :node_list => ['example.com:8091', 'example.net'])

Here is creating a connection to a protected bucket by providing a username and password. Notice that the username you provide is the same as the bucket:

Couchbase.connect(:bucket => 'protected',
                  :username => 'protected',
                  :password => 'secret')

Couchbase.connect('http://localhost:8091/pools/default/buckets/protected',
                  :username => 'protected',
                  :password => 'secret')

The possible errors that can occur when you try to connect are:

  • Couchbase::Error::BucketNotFound. Occurs if the bucket name your provide does not exist.

  • Couchbase::Error::Connect. Occurs if the socket to connect to Couchbase Server does not respond in time or cannot accept the connection.

You can persist a Couchbase client storing it in a way such that the Ruby garbage collector does not remove from memory. To do this, you can create a singleton object that contains the client instance and the connection information. You should access the class-level method, Couchbase.bucket instead of Couchbase.connect to get the client instance.

When you use Couchbase.bucket it will create a new client object when you first call it and then store the object in thread storage. If the thread is still alive when the next request is made to the ruby process, the SDK will not create a new client instance, but rather use the existing one:

# Simple example to connect using thread local singleton

Couchbase.connection_options = {:bucket => "my",
                                :hostname => "example.com",
                                :password => "secret"}

# this call will user connection_options to initialize new connection.

# By default Couchbase.connection_options can be empty

Couchbase.bucket.set("foo", "bar")

# Amend the options of the singleton connection in run-time

Couchbase.bucket.reconnect(:bucket => "another")

The first example demonstrates how you can create a client instance as a singleton object, the second one will use the class-level Couchbase.bucket constructor to create a persistent connection. The last example demonstrates how you can update the properties of the singleton connection if you reconnect.

In the case of the Ruby SDK, you can set a timeout for the initial connection, and then change the timeout setting. This new connection-level setting will apply to any subsequent read/write requests made with the client instance:

#sets timeout for initial client instance and connection to server

conn = Couchbase.connect(:timeout => 3_000_000)

#resets the connection timeout for subsequent operations on connection

conn.timeout = 1_500_000

#set a value using client instance

conn.set("foo", "bar")

In this example, we create a new Couchbase client instance with Couchbase.connect() and set the connection time out to 3 seconds. If the client instance fails to connect in the three seconds, it will timeout and return a failure to connect error. Then we set the timeout to 1_500_000, or 1.5 seconds, which will be the timeout level of any requests made with that client instance, such as the set().

Ruby — Storage Operations

The Couchbase Ruby Client Library store operations set information within the Couchbase database. These are distinct from the update operations in that the key does not have to exist within the Couchbase database before being stored.

Add Operations

The add method adds a value to the database with the specified key, but will fail if the key already exists in the database.

API Call object.add(key, value, options)
Asynchronous no
Description Add a value with the specified key that does not already exist. Will fail if the key/value pair already exist.
Returns fixnum ( The CAS value for the object stored. A fixed number )
Arguments
string key Document ID used to identify the value
object value Value to be stored
hash options Hash containing option/value pairs used during a set operation.
Structure definition:
:ttl (int)
Time for document to exist in server before it is automatically destroyed. This option symbol is :ttl and the value can be any number representing seconds.
:flags (fixnum)
Flags used during the set. These flags are ignored by the Couchbase server but preserved for use by a client. This includes default flags recorded for new values and was used as part of the memcached protocol.
:format (symbol)
Determines how a value is represented in storage. Possible values include :document for JSON data, :plain for string storage, and :marshal to serialize your ruby object using Marshall.dump and Marshal.load.
:cas (fixnum)
The CAS value for an object. This value was created on the server and is guaranteed to be unique for each value for a given key. You provide this value as an option when you want basic optimistic concurrency control while doing sets.
Exceptions
ArgumentError Exception object indicating failed attempt to pass a block in synchronous mode.
Couchbase::Error::Connect Exception object specifying failure to connect to a node.
Couchbase::Error::KeyExists Exception object indicating the key already exists on the server.
Couchbase::Error::ValueFormat Exception object indicating the value cannot be serialized with chosen encoder, for instance, occurs if you try to store Hash in :plain mode.

The add method adds a value to the database using the specified key.

couchbase.add("someKey", 0, someObject);

Unlike Set Operations the operation can fail (and return false) if the specified key already exists.

For example, the first operation in the example below may complete if the key does not already exist, but the second operation will always fail as the first operation will set the key:

c.add("foo", "bar")   # stores successully
c.add("foo", "baz")   # raises Couchbase::Error::KeyExists:
                      # fails to store value (key="foo", error=0x0c)

Replace Operations

The replace methods update an existing key/value pair in the database. If the specified key does not exist, then the operation will fail.

API Call object.replace(key, value [, ruby-replace-options ])
Asynchronous no
Description Update an existing key with a new value
Returns fixnum ( The CAS value for the object stored. A fixed number )
Arguments
string key Document ID used to identify the value
object value Value to be stored
hash ruby-replace-options Hash of options containing key/value pairs
Exceptions
Couchbase::Error::Connect Exception object specifying failure to connect to a node.
Couchbase::Error::KeyExists Exception object indicating the CAS value does not match the one for the record already on the server.
Couchbase::Error::NotFound Exception object specifying a given key cannot be found in datastore.

The first form of the replace method updates an existing value setting while supporting the explicit setting of the expiry time on the item. For example to update the samplekey :

couchbase.replace("samplekey","updatedvalue",0);

Set Operations

The set operations store a value into Couchbase or Memcached using the specified key and value. The value is stored against the specified key, even if the key already exists and has data. This operation overwrites the existing with the new data.

API Call object.set(key, value, options)
Asynchronous no
Description Store a value using the specified key, whether the key already exists or not. Will overwrite a value if the given key/value already exists.
Returns fixnum ( The CAS value for the object stored. A fixed number )
Arguments
string key Document ID used to identify the value
object value Value to be stored
hash options Hash containing option/value pairs used during a set operation.
Structure definition:
:ttl (int)
Time for document to exist in server before it is automatically destroyed. This option symbol is :ttl and the value can be any number representing seconds.
:flags (fixnum)
Flags used during the set. These flags are ignored by the Couchbase server but preserved for use by a client. This includes default flags recorded for new values and was used as part of the memcached protocol.
:format (symbol)
Determines how a value is represented in storage. Possible values include :document for JSON data, :plain for string storage, and :marshal to serialize your ruby object using Marshall.dump and Marshal.load.
:cas (fixnum)
The CAS value for an object. This value was created on the server and is guaranteed to be unique for each value for a given key. You provide this value as an option when you want basic optimistic concurrency control while doing sets.
Exceptions
Couchbase::Error::Connect Exception object specifying failure to connect to a node.
Couchbase::Error::KeyExists Exception object indicating the key already exists on the server.
Couchbase::Error::ValueFormat Exception object indicating the value cannot be serialized with chosen encoder, e.g. if you try to store the Hash in :plain mode.

Examples of using set as follows:

#Store a key/value which expires in 2 seconds using relative TTL

c.set("foo", "bar", :ttl => 2)


#Store the key that expires in 2 seconds using absolute TTL

c.set("foo", "bar", :ttl => Time.now.to_i + 2)

#Apply JSON document format for value at set

c.set("foo", {"bar" => "baz}, :format => :document)

#Use index and value as hash syntax to store value during set

c.set["foo"] = {"bar" => "baz}

#Use extended hash syntax to store a value at set

c["foo", {:flags => 0x1000, :format => :plain}] = "bar"

c["foo", :flags => 0x1000] = "bar"  # for ruby 1.9.x only

#Set application specific flags (note that it will be OR-ed with format flags)

c.set("foo", "bar", :flags => 0x1000)

#Perform optimistic locking by specifying last known CAS version

c.set("foo", "bar", :cas => 8835713818674332672)

#Perform asynchronous call

c.run do
      c.set("foo", "bar") do |ret|
            ret.operation   #=> :set
            ret.success?    #=> true
            ret.key         #=> "foo"
            ret.cas
      end
end

Flush Operation

The flush operation deletes all values in a Couchbase bucket.

API Call object.flush()
Asynchronous no
Description Deletes all values from the corresponding bucket
Returns Boolean ( Boolean (true/false) )
Arguments
None

This operation is deprecated as of the 1.8.1 Couchbase Server, to prevent accidental, detrimental data loss. Use of this operation should be done only with extreme caution, and most likely only for test databases as it will delete, item by item, every persisted record as well as destroy all cached data.

Third-party client testing tools may perform a flush operation as part of their test scripts. Be aware of the scripts run by your testing tools and avoid triggering these test cases/operations unless you are certain they are being performed on your sample/test database.

Inadvertent use of flush on production databases, or other data stores you intend to use will result in permanent loss of data. Moreover the operation as applied to a large data store will take many hours to remove persisted records.

couchbase.flush

Ruby — Retrieve Operations

The retrieve operations get information from the Couchbase database. A summary of the available API calls is listed below.

API Call object.get(keyn [, ruby-get-options ] [, ruby-get-keys ])
Asynchronous no
Description Get one or more key values
Returns hash ( Container with key/value pairs )
Arguments
String/Symbol/Array/Hash keyn One or more keys used to reference a value
Structure definition:
key (string)
Key as string.
keys (strings)
Comma-separated strings for each key, e.g. client.get( “foo”, “bar”)
symbol (symbol)
Symbol for each key to be retrieved, e.g. :foo.
hash (hash)
Key-expiration pairs provided in a hash-map, e.g. c.get(“foo” => 10, “bar” => 20). Returns has of key-values for given keys.
hash ruby-get-options Hash of options containing key/value pairs
Structure definition:
:extended (boolean)
Default is false. If set to true, returns ordered with pairs. Pairs follow this convention: key => value, flags, cas. If you are getting one key, returns an array. More than one pair returned as a hash.
:ttl (int)
Time for document to exist in server before it is automatically destroyed. This option symbol is :ttl and the value can be any number representing seconds.
:quiet (boolean)
Suppresses errors while in synchronous mode. Default is true. If set to true, will return nil, and raise no error. In asynchronous mode, this option ignored.
:format (symbol)
Determines how a value is represented. Default is nil. Explicitly choose the decoder for this option (:plain, :document, :marshal).
hash ruby-get-keys Hash of options containing key/value pairs
Structure definition:
key (string)
Key as string.
keys (strings)
Comma-separated strings for each key, e.g. client.get( “foo”, “bar”)
symbol (symbol)
Symbol for each key to be retrieved, e.g. :foo.
hash (hash)
Key-expiration pairs provided in a hash-map, e.g. c.get(“foo” => 10, “bar” => 20). Returns has of key-values for given keys.
Exceptions
ArgumentError Exception object indicating failed attempt to pass a block in synchronous mode.
Couchbase::Error::Connect Exception object specifying failure to connect to a node.
Couchbase::Error::NotFound Exception object specifying a given key cannot be found in datastore.

The get method obtains an object stored in Couchbase using the default transcoder for serialization of the object.

For example:

object = couchbase.get("someKey");

In this case, couchbase is the Couchbase client instance which stores a connection to the server. Transcoding of the object assumes the default transcoder was used when the value was stored. The returned object can be of any type.

If the request key does no existing in the database then the returned value is null.

The following show variations for using a get with different parameters and settings:

#get single value; returns value or nil

c.get("foo")

#doing a get with hash-like syntax

c["foo"]

#get single value in verbose error mode setting
#returns ruby error if :quiet => false
#returns nil if :quiet => true

c.get("missing-foo", :quiet => false)
c.get("missing-foo", :quiet => true)

#get and update expiration time for single value

c.get("foo", :ttl => 10)

#get multiple keys

c.get("foo", "bar", "baz")

#perform an extended get, which returns ordered list of elements
#returns value, flags and cas and assigned to respective variable

val, flags, cas = c.get("foo", :extended => true)

#returns {"foo" => [val1, flags1, cas1], "bar" => [val2, flags2, cas2]}

c.get("foo", "bar", :extended => true)

#perform an asynchronous get

c.run do
    c.get("foo", "bar", "baz") do |ret|
      ret.operation   #=> :get
      ret.success?    #=> true
      ret.key         #=> "foo", "bar" or "baz" in separate calls
      ret.value
      ret.flags
      ret.cas
    end
end

Ruby — Update Operations

The update methods support different methods of updating and changing existing information within Couchbase. A list of the available methods is listed below.

Append Methods

The append methods allow you to add information to an existing key/value pair in the database. You can use this to add information to a string or other data after the existing data.

The append methods append raw serialized data on to the end of the existing data in the key. If you have previously stored a serialized object into Couchbase and then use append, the content of the serialized object will not be extended. For example, adding an Array of integers into the database, and then using append to add another integer will result in the key referring to a serialized version of the array, immediately followed by a serialized version of the integer. It will not contain an updated array with the new integer appended to it. De-serialization of objects that have had data appended may result in data corruption.

API Call object.append(key, value [, ruby-append-options ])
Asynchronous no
Description Append a value to an existing key
Returns fixnum ( The CAS value for the object stored. A fixed number )
Arguments
string key Document ID used to identify the value
object value Value to be stored
hash ruby-append-options Hash of options containing key/value pairs
Structure definition:
:cas (fixnum)
The CAS value for an object. This value was created on the server and is guaranteed to be unique for each value for a given key. You provide this value as an option when you want basic optimistic concurrency control while doing sets.
:format (symbol)
Determines how a value is represented in storage. Possible values include :plain for string storage.
Exceptions
ArgumentError Exception object indicating failed attempt to pass a block in synchronous mode.
Couchbase::Error::Connect Exception object specifying failure to connect to a node.
Couchbase::Error::KeyExists Exception object indicating the key already exists on the server.
Couchbase::Error::NotStored Exception object indicating the key/value does not exist in the database.

The append appends information to the end of an existing key/value pair. The append function requires a CAS value. For more information on CAS values, see Ruby — Retrieve Operations.

For example, to append a string to an existing key:

#sets foo key to text 'Hello'

couchbase.set("foo", "Hello")

#adds text to end of key foo, resulting in 'Hello, world!'

couchbase.append("foo", ", world!")

#gets foo
couchbase.get("foo")
#=> "Hello, world!"

Other examples of using append are as follows:

#Perform a simple append

c.set("foo", "aaa")
c.append("foo", "bbb")
c.get("foo")           # returns "aaabbb"

#Perform optimistic locking. The operations fails if the
#given CAS does not match the CAS for the key

ver = c.set("foo", "aaa")
c.append("foo", "bbb", :cas => ver)


#Creates custom data groups/sets using append
#appends minus to indicate item not part of set
#appends plus to indicate item is part of set

def set_add(key, *values)
    encoded = values.flatten.map{|v| "+#{v} "}.join
    append(key, encoded)
end

def set_remove(key, *values)
    encoded = values.flatten.map{|v| "-#{v} "}.join
    append(key, encoded)
end

def set_get(key)
    encoded = get(key)
    ret = Set.new

    encoded.split(' ').each do |v|
          op, val = v[0], v[1..-1]
          case op
                when "-"
                    ret.delete(val)
                when "+"
                    ret.add(val)
          end
    end
    ret
end

Compare and Swap

Takes a given key, gets the value for the key, and yields it to a block. Replaces the value in the datastore with the result of the block as long as the key has not been updated in the meantime. If the key has been successfully updated in the datastore, a new CAS value will be returned raises Error::KeyExists.

CAS stands for “compare and swap”, and avoids the need for manual key mutexing.

API Call object.cas(key [, ruby-cas-options ])
Asynchronous yes
Description Compare and set a value providing the supplied CAS key matches
Returns ( Check and set object )
Arguments
string key Document ID used to identify the value
hash ruby-cas-options Hash of options containing key/value pairs
Structure definition:
:ttl (int)
Time for document to exist in server before it is automatically destroyed. This option symbol is :ttl and the value can be any number representing seconds.
:format (symbol)
Determines how a value is represented in storage. Possible values include :document for JSON data, :plain for string storage, and :marshal to serialize your ruby object using Marshall.dump and Marshal.load.
:flags (fixnum)
Flags used during the commit. These flags are ignored by the Couchbase server but preserved for use by a client. This includes default flags recorded for new values and was used as part of the memcached protocol.
Exceptions
Couchbase::Error::KeyExists Exception object indicateing the key was updated before the codeblock has completed and therefore the CAS value had changed.

The following illustrates use of the cas function:

#appends to a JSON-encoded value
# first sets value and formatting for stored value
        c.default_format = :document
        c.set("foo", {"bar" => 1})

#perform cas and provide value to block
        c.cas("foo") do |val|
              val["baz"] = 2
              val
        end

# returns {"bar" => 1, "baz" => 2}
        c.get("foo")

Decrement Methods

The decrement methods reduce the value of a given key if the corresponding value can be parsed to an integer value. These operations are provided at a protocol level to eliminate the need to get, update, and reset a simple integer value in the database. All the Ruby Client Library methods support the use of an explicit offset value that will be used to reduce the stored value in the database.

API Call object.decrement(key [, offset ] [, ruby-incr-decr-options ])
Asynchronous no
Description Decrement the value of an existing numeric key. The Couchbase Server stores numbers as unsigned values. Therefore the lowest you can decrement is to zero.
Returns fixnum ( Value for a given key. A fixed number )
Arguments
string key Document ID used to identify the value
offset Integer offset value to increment/decrement (default 1)
hash ruby-incr-decr-options Hash of options containing key/value pairs
Structure definition:
:create (boolean)
Default is false. If set to true, it will initialize the key with zero value and zero flags (use :initial option to set another initial value). Note: this will not increment or decrement the missing value once it is initialized.
:initial (fixnum)
Default is 0. Can be an integer (up to 64 bits) for missing key initialization. This option automatically implies the :create option is true, regardless of the setting.
:ttl (int)
Time for document to exist in server before it is automatically destroyed. This option symbol is :ttl and the value can be any number representing seconds.
:extended (boolean)
Default is false. If set to true, the operation will return an array, [value, cas], otherwise it returns just the value.

The first form of the decr method accepts the keyname and offset value to be used when reducing the server-side integer. For example, to decrement the server integer dlcounter by 5:

couchbase.set("counter", 10)
couchbase.decr("counter", 5)
couchbase.get("counter") #returns 5

The following demonstrates different options available when using decrement:

#decrement key by one (default)

c.decr("foo")

#decrement by 50

c.decr("foo", 50)

#decrement key or initialize with zero

c.decr("foo", :create => true)

#decrement key or initialize with 3

c.decr("foo", 50, :initial => 3)

#decrement key and get CAS value

val, cas = c.decr("foo", :extended => true)

#decrementing signed number

c.set("foo", -100)
c.decrement("foo", 100500)   #=> 0

#decrementing zero
c.set("foo", 0)
c.decrement("foo", 100500)   #=> 0

#asynchronous use of decrement
c.run do
      c.decr("foo") do |ret|
            ret.operation   #=> :decrement
            ret.success?    #=> true
            ret.key         #=> "foo"
            ret.value
            ret.cas
      end
end

Delete Methods

The delete method deletes an item in the database with the specified key. Delete operations are synchronous only.

API Call object.delete(key [, ruby-delete-options ])
Asynchronous no
Description Delete a key/value
Returns Boolean ( Boolean (true/false) )
Arguments
string key Document ID used to identify the value
hash ruby-delete-options Hash of options containing key/value pairs
Structure definition:
:quiet (boolean)
If set to true, the operation returns nil for failure. Otherwise it will raise error in synchronous mode. In asynchronous mode this option ignored.
:cas (fixnum)
The CAS value for an object. This value created on the server and is guaranteed to be unique for each value of a given key. This value is used to provide simple optimistic concurrency control when multiple clients or threads try to update/delete an item simultaneously.
Exceptions
ArgumentError Exception object indicating failed attempt to pass a block in synchronous mode.
Couchbase::Error::Connect Exception object specifying failure to connect to a node.
Couchbase::Error::KeyExists Exception object indicating mismatch of given cas and cas for record.
Couchbase::Error::NotFound Exception object indicating key is missing. Occurs in verbose mode.

For example, to delete an item you might use code similar to the following:

couchbase.delete("foo")

The following illustrates use of delete in Ruby along with various parameters and settings:

#set and delete for key 'foo' in default mode

c.set("foo", "bar")
c.delete("foo")        #=> true

#attempt second delete in default mode

c.delete("foo")        #=> false

#attempt to delete a key with quiet mode and then verbose

c.set("foo", "bar")
c.delete("foo", :quiet => false)   #=> true
c.delete("foo", :quiet => true)    #=> nil (default behavior)
c.delete("foo", :quiet => false)   #=> will raise Couchbase::Error::NotFound

#attempt to delete with version check using cas value

ver = c.set("foo", "bar")          #=> 5992859822302167040
c.delete("foo", :cas => 123456)    #=> will raise Couchbase::Error::KeyExists
c.delete("foo", :cas => ver)       #=> true

Increment Methods

The increment methods enable you to increase a given stored integer value. These are the incremental equivalent of the decrement operations and work on the same basis; updating the value of a key if it can be parsed to an integer. The update operation occurs on the server and is provided at the protocol level. This simplifies what would otherwise be a two-stage get and set operation.

API Call object.increment(key [, offset ] [, ruby-incr-decr-options ])
Asynchronous no
Description Increment the value of an existing numeric key. Couchbase Server stores numbers as unsigned numbers, therefore if you try to increment an existing negative number, it will cause an integer overflow and return a non-logical numeric result. If a key does not exist, this method will initialize it with the zero or a specified value.
Returns fixnum ( Value for a given key. A fixed number )
Arguments
string key Document ID used to identify the value
offset Integer offset value to increment/decrement (default 1)
hash ruby-incr-decr-options Hash of options containing key/value pairs
Structure definition:
:create (boolean)
Default is false. If set to true, it will initialize the key with zero value and zero flags (use :initial option to set another initial value). Note: this will not increment or decrement the missing value once it is initialized.
:initial (fixnum)
Default is 0. Can be an integer (up to 64 bits) for missing key initialization. This option automatically implies the :create option is true, regardless of the setting.
:ttl (int)
Time for document to exist in server before it is automatically destroyed. This option symbol is :ttl and the value can be any number representing seconds.
:extended (boolean)
Default is false. If set to true, the operation will return an array, [value, cas], otherwise it returns just the value.

The first form of the incr method accepts the keyname and offset (increment) value to be used when increasing the server-side integer. For example, to increment the server integer dlcounter by 5:

couchbase.set("counter", 10)
couchbase.incr("counter", 5)
couchbase.get("counter") #=> 15

The second form of the incr method supports the use of a default value which will be used to set the corresponding key if that value does already exist in the database. If the key exists, the default value is ignored and the value is incremented with the provided offset value. This can be used in situations where you are recording a counter value but do not know whether the key exists at the point of storage.

For example, if the key counter does not exist, the following fragment will return 1000:

counter = couchbase.incr("counter", 1, :initial => 1000); #=> 1000

The following demonstrates different options available when using increment and the output they produce:

#increment key by one (default)

c.incr("foo")

#increment by 50

c.incr("foo", 50)

#increment key or initialize with zero

c.incr("foo", :create => true)

#increment key or initialize with 3

c.incr("foo", 50, :initial => 3)

#increment key and get CAS value

val, cas = c.incr("foo", :extended => true)

#integer overflow from incrementing signed number

c.set("foo", -100)
c.get("foo")           #=> -100
c.incr("foo")          #=> 18446744073709551517

#asynchronous use of increment

c.run do
    c.incr("foo") do |ret|
          ret.operation   #=> :increment
          ret.success?    #=> true
          ret.key         #=> "foo"
          ret.value
          ret.cas
    end
end

Prepend Methods

The prepend methods insert information before the existing data for a given key. Note that as with the append method, the information will be inserted before the existing binary data stored in the key, which means that serialization of complex objects may lead to corruption when using prepend.

API Call object.prepend(key, value [, ruby-prepend-options ])
Asynchronous no
Description Prepend a value to an existing key
Returns fixnum ( The CAS value for the object stored. A fixed number )
Arguments
string key Document ID used to identify the value
object value Value to be stored
hash ruby-prepend-options Hash of options containing key/value pairs
Structure definition:
:cas (fixnum)
The CAS value for an object. This value was created on the server and is guaranteed to be unique for each value for a given key. You provide this value as an option when you want basic optimistic concurrency control while doing sets.
:format (symbol)
Determines how a value is represented in storage. Possible values include :plain for string storage.
Exceptions
ArgumentError Exception object indicating failed attempt to pass a block in synchronous mode.
Couchbase::Error::Connect Exception object specifying failure to connect to a node.
Couchbase::Error::KeyExists Exception object indicating the key already exists on the server.
Couchbase::Error::NotStored Exception object indicating the key/value does not exist in the database.

For example, to prepend a string to an existing key:

#set inital key, foo

couchbase.set("foo", "world!")

#prepend text 'Hello, ' to foo

couchbase.prepend("foo", "Hello, ")

#get new foo value

couchbase.get("foo") #=> "Hello, world!"

Other examples of using prepend are as follows:

#simple prepend example

c.set("foo", "aaa")
c.prepend("foo", "bbb")
c.get("foo")           #=> "bbbaaa"

#Perform optimistic locking. The operations fails if the
#given CAS does not match the CAS for the key

ver = c.set("foo", "aaa")
c.prepend("foo", "bbb", :cas => ver)


#Use explicit format options

c.default_format       #=>defaults to :document, or JSON document
c.set("foo", {"y" => "z"})

#sets added text to plain data and adds
c.prepend("foo", '[', :format => :plain)
c.append("foo", ', {"z": "y"}]', :format => :plain)

#get updated value
c.get("foo")           #=> [{"y"=>"z"}, {"z"=>"y"}]

Touch Methods

The touch methods allow you to update the expiration time on a given key. This can be useful for situations where you want to prevent an item from expiring without resetting the associated value. For example, for a session database you might want to keep the session alive in the database each time the user accesses a web page without explicitly updating the session value, keeping the user’s session active and available.

In Ruby, touch can be used to update or more keys.

API Call object.touch-one(key [, ruby-touch-options ] [, ruby-touch-keys ])
Asynchronous no
Description Update the expiry time of an item
Returns Boolean ( Boolean (true/false) )
Arguments
string key Document ID used to identify the value
hash ruby-touch-options Hash of options containing key/value pairs
Structure definition:
:ttl (fixnum)
Expiration time for record. Default is indefinite, meaning the record will remain until an explicit delete command is made. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times from the epoch.
hash ruby-touch-keys Hash of options containing key/value pairs

The following examples demonstrate use of touch with a single key:

#update record so no expiration (record held indefinitely long)

c.touch("foo")

#update expiration to 10 seconds

c.touch("foo", :ttl => 10)

#alternate syntax for updating single value

c.touch("foo" => 10)

API Call object.touch-many(keyn)
Asynchronous no
Description Update the expiry time of an item
Returns hash ( Container with key/value pairs )
Arguments
String/Symbol/Array/Hash keyn One or more keys used to reference a value
Structure definition:
key (string)
Key as string.
keys (strings)
Comma-separated strings for each key, e.g. client.get( “foo”, “bar”)
symbol (symbol)
Symbol for each key to be retrieved, e.g. :foo.
hash (hash)
Key-expiration pairs provided in a hash-map, e.g. c.get(“foo” => 10, “bar” => 20). Returns has of key-values for given keys.

The following examples demonstrate use of touch with multiple keys, which are provided as a hash:

#update two records with 10 and 20 second expirations
#returns hash with key and success/fail
#{"foo" => true, "bar" => true}

c.touch("foo" => 10, :bar => 20)

#Update several values in asynchronous mode
c.run do
      c.touch("foo" => 10, :bar => 20) do |ret|
          ret.operation   #=> :touch
          ret.success?    #=> true
          ret.key         #=> "foo" and "bar" in separate calls
      end
end

Ruby — Statistics Operations

The Couchbase Ruby Client Library includes support for obtaining statistic information from all of the servers defined within a couchbase object. A summary of the commands is provided below.

couchbase.stats
#=> {...}

The stats command gets the statistics from all of the configured nodes. The information is returned in the form of a nested Hash, first containing the address of the configured server and then within each server the individual statistics for that server as key value pairs.

{
    "172.16.16.76:12008"=>
    {
        "threads"=>"4",
        "connection_structures"=>"22",
        "ep_max_txn_size"=>"10000",
          ...
    },
    "172.16.16.76:12000"=>
    {
        "threads"=>"4",
        "connection_structures"=>"447",
        "ep_max_txn_size"=>"10000",
          ...
    },
    ...
}

API Call object.stats([ statname ])
Asynchronous no
Description Get the database statistics
Returns object ( Binary object )
Arguments
statname Group name of a statistic for selecting individual statistic value

Ruby — Troubleshooting

Creating Timed Operations

One approach you can try if you get temporary out of memory errors from the server is to explicitly pace the timing of requests you make. You can do this in any SDK by creating a timer and only perform a Couchbase request after a specific timed interval. This will provide a slight delay between server requests and will reduce the risk of an out of memory error. For instance in Ruby:

c.set("foo", 100)
n = 1

c.run do
    c.create_periodic_timer(500000) do |tm|
          c.incr("foo") do
              if n == 5
                  tm.cancel
              else
                  n += 1
              end
          end
    end
end

In this example we create a sample record foo with the initial fixnum value of 100. Then we create a increment count set to one, to indicate the first time we will create a Couchbase request. In the event loop, we create a timing loop that runs every.5 seconds until we have repeated the loop 5 times and our increment is equal to 5. In the timer loop, we increment foo per loop.

Appendix: Release Notes

The following sections provide release notes for individual release versions of Couchbase Client Library Ruby. To browse or submit new issues, see Couchbase Client Library Ruby Issues Tracker.

Release Notes for Couchbase Client Library Ruby 1.1.5 GA (17 September 2012)

Fixes in 1.1.5

  • Fixed installing issue on Mac OS X.

    Issues : RCBC-81

Release Notes for Couchbase Client Library Ruby 1.1.4 GA (30 August 2012)

Fixes in 1.1.4

Release Notes for Couchbase Client Library Ruby 1.1.3 GA (27 July 2012)

Fixes in 1.1.3

  • The Couchbase::Bucket class hasn’t implemented the #dup method. So it caused SEGFAULT. The patch is implementing correct function, which copy the internals and initializes new connection.

    Issues : RCBC-64

  • make object_space gc protector per-bucket object

    previous version provided not completely thread-safe bucket instance, because it was sharing global hash for protecting objects, created in extension, from garbage collecting.

    Issues : RCBC-60

  • The flags might be reset if caller will use Couchbase::Bucket#cas operation. Here is IRB session demostrating the issue:

    irb> Couchbase.bucket.set("foo", "bar", :flags => 0x100)
     17982951084586893312
     irb> Couchbase.bucket.cas("foo") { "baz" }
     1712422461213442048
     irb> Couchbase.bucket.get("foo", :extended => true)
     ["baz", 0, 1712422461213442048]
    

    Issues : RCBC-59

Release Notes for Couchbase Client Library Ruby 1.1.2 GA (05 June 2012)

Fixes in 1.1.2

  • Upgrade libcouchbase dependency to 1.0.4. Version 1.0.4 includes important stability fixes.

  • Backport debugger patch. The gem used to require debugger as development dependency. Unfortunately ruby-debug19 isn’t supported anymore for ruby 1.9.x. But there is new gem ‘debugger’. This patch replaces this dependency.

Release Notes for Couchbase Client Library Ruby 1.1.1 GA (19 March 2012)

Fixes in 1.1.1

  • Flags are used differently in different clients for example between Python and Ruby. This fix will force the format to a known value irrespective of the flags.

  • Calls between Ruby and C libraries for Couchbase which involved default arguments had an associated arity of -1 which was not being handled correctly. That is being handled correctly now.

Release Notes for Couchbase Client Library Ruby 1.1.0 GA (07 March 2012)

New Features and Behavior Changes in 1.1.0

  • With the usage of the URI parser from stdlib it is possible to validate the bucket URI more strictly. Also, it is possible to specify credentials in the URI like: http://username:password@example.com:8091/pools/default/buckets/custom

  • The “default” connection is available in thread local storage. This mean that using the Couchbase.bucket method it is possible to get access to current connection and there is no need to share connections when running in multi-thread environment. Each thread has its own connection reference.

  • The direct dependency on libevent and sasl has been removed. Now the library doesn’t require libevent headers installed.

  • The disconnect and reconnect interfaces are implemented which provide routines for explicit resource management. Connections were freed only when the Garbage Collector found that the connection was not being used. Now it’s possible for the client to check if the bucket was connected using 'connected?' or 'disconnect' it manually or 'reconnect' using old settings.

Fixes in 1.1.0

  • It is not required to install libcouchbase or libvbucket on windows.

  • Based on the time out fix (CCBC-20),clients will be notified when the connection was dropped or host isn’t available.

  • It is possible to store nil as a value. It is possible to distinguish a nil value from a missing key by looking at at the value returned and the flags and CAS values as well.

  • There were spurious timeout issues with a compound statement like below. connection.run do connection.get("foo") {|ret| puts "got foo = #{ret.value}"} sleep(5) end

No timeout will occur unless there is a problem with the connection.