couchbase 1.2.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts CHANGED
@@ -2,4 +2,4 @@
2
2
  --no-private
3
3
  -
4
4
  README.markdown
5
- HISTORY.markdown
5
+ RELEASE_NOTES.markdown
@@ -387,18 +387,22 @@ The result is represented as a hash with the server node address as
387
387
  the key and stats as key-value pairs.
388
388
 
389
389
  {
390
- "172.16.16.76:12008"=>
390
+ "threads"=>
391
391
  {
392
- "threads"=>"4",
393
- "connection_structures"=>"22",
394
- "ep_max_txn_size"=>"10000",
392
+ "172.16.16.76:12008"=>"4",
393
+ "172.16.16.76:12000"=>"4",
395
394
  # ...
396
395
  },
397
- "172.16.16.76:12000"=>
396
+ "connection_structures"=>
398
397
  {
399
- "threads"=>"4",
400
- "connection_structures"=>"447",
401
- "ep_max_txn_size"=>"10000",
398
+ "172.16.16.76:12008"=>"22",
399
+ "172.16.16.76:12000"=>"447",
400
+ # ...
401
+ },
402
+ "ep_max_txn_size"=>
403
+ {
404
+ "172.16.16.76:12008"=>"1000",
405
+ "172.16.16.76:12000"=>"1000",
402
406
  # ...
403
407
  },
404
408
  # ...
@@ -3,6 +3,25 @@
3
3
  This document is a list of user visible feature changes and important
4
4
  bugfixes. Do not forget to update this doc in every important patch.
5
5
 
6
+ ## 1.3.0 (2014-05-07)
7
+
8
+ * [major] RCBC-46 implement Couchbase::ConnectionPool to allow
9
+ applications (and ActiveSupport::Cache::CouchbaseStore) use it in
10
+ multi-threaded environment
11
+
12
+ * [major] Introduce Transcoders. This mechanism is more flexible, and
13
+ similar to how other clients encode values.
14
+
15
+ * [minor] Deprecate numeric argument to 'default_format'. Instead
16
+ of this style:
17
+
18
+ Couchbase.connect(:default_format => Couchbase::Bucket::FMT_MARSHAL)
19
+
20
+ Symbol notation or explicit transcoder entity should be used
21
+
22
+ Couchbase.connect(:default_format => :marshal)
23
+ Couchbase.connect(:transcoder => Couchbase::Transcoder::Marshal)
24
+
6
25
  ## 1.2.3 (2013-04-02)
7
26
 
8
27
  * [major] Make ActiveSupport::Cache::CouchbaseStore threadsafe
@@ -37,6 +37,7 @@ Gem::Specification.new do |s|
37
37
 
38
38
  s.add_runtime_dependency 'yaji', '~> 0.3.2'
39
39
  s.add_runtime_dependency 'multi_json', '~> 1.0'
40
+ s.add_runtime_dependency 'connection_pool', '~> 0.9.2'
40
41
 
41
42
  s.add_development_dependency 'rake'
42
43
  s.add_development_dependency 'minitest'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'couchbase'
4
+ gem 'goliath'
5
+ gem 'grape'
@@ -0,0 +1,50 @@
1
+ # Couchbase + Grape + Goliath = <3
2
+
3
+ This demo shows how to integrate these cool things to build
4
+ asynchronous REST service
5
+
6
+ # Usage
7
+
8
+ 1. Clone the repository. Navigate to `examples/chat-goliath-grape/`
9
+ directory
10
+
11
+ 2. Install libcouchbase (http://www.couchbase.com/develop/c/current).
12
+ For MacOS users it will look like:
13
+
14
+ brew update
15
+ brew install libcouchbase
16
+
17
+ 3. Install all ruby dependencies. This demo has been tested on latest
18
+ stable version of ruby (`ruby 2.0.0p0 (2013-02-24 revision 39474)
19
+ [x86_64-linux]`)
20
+
21
+ gem install bundler
22
+ bundle install
23
+
24
+ 4. Setup your Couchbase server
25
+ (http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-getting-started.html).
26
+ It should have `default` bucket. Or you can edit connection options
27
+ in `config/app.rb` file.
28
+
29
+ 5. Start the server up
30
+
31
+ ruby app.rb -sv
32
+
33
+ 6. Create an message:
34
+
35
+ $ curl -X POST -Fmessage="Hello world" http://localhost:9000/messages
36
+ {"ok":true,"id":"msg:1","cas":11880713153673363456}
37
+
38
+ 7. If you create a design document called `messages` and put a view
39
+ named `all` with this map function:
40
+
41
+ function(doc, meta) {
42
+ if (doc.timestamp) {
43
+ emit(meta.id, doc)
44
+ }
45
+ }
46
+
47
+ You can fetch all messages with this command:
48
+
49
+ curl -X GET http://localhost:9000/messages
50
+ {"ok":true,"messages":[{"id":"msg:1","key":"msg:1","value":{"timestamp":"2013-04-11T12:43:42+03:00","message":"Hello world"},"cas":11880713153673363456}]}
@@ -0,0 +1,67 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'em-synchrony'
19
+ require 'couchbase'
20
+ require 'goliath'
21
+ require 'grape'
22
+ require 'date'
23
+
24
+ class Chat < Grape::API
25
+
26
+ format :json
27
+
28
+ resource 'messages' do
29
+ get do
30
+ view = env.couchbase.design_docs["messages"].all(:include_docs => true)
31
+ msgs = view.map do |r|
32
+ {
33
+ "id" => r.id,
34
+ "key" => r.key,
35
+ "value" => r.value,
36
+ "cas" => r.meta["cas"],
37
+ # "doc" => r.doc
38
+ }
39
+ end
40
+ {"ok" => true, "messages" => msgs}
41
+ end
42
+
43
+ post do
44
+ payload = {
45
+ "timestamp" => DateTime.now.iso8601,
46
+ "message" => params["message"]
47
+ }
48
+ id = env.couchbase.incr("msgid", :initial => 1)
49
+ id = "msg:#{id}"
50
+ cas = env.couchbase.set(id, payload)
51
+ {"ok" => true, "id" => id, "cas" => cas}
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ class App < Goliath::API
58
+ def response(env)
59
+ Chat.call(env)
60
+ rescue => e
61
+ [
62
+ 500,
63
+ {'Content-Type' => 'application/json'},
64
+ MultiJson.dump(:error => e, :stacktrace => e.backtrace)
65
+ ]
66
+ end
67
+ end
@@ -0,0 +1,20 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ config['couchbase'] = EventMachine::Synchrony::ConnectionPool.new(:size => 5) do
19
+ Couchbase::Bucket.new(:engine => :eventmachine)
20
+ end
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'couchbase'
@@ -0,0 +1,59 @@
1
+ # Gzip Transcoder
2
+
3
+ This example demonstrates advanced usage of client-side transcoders.
4
+ In particular it uses GzipWriter and GzipReader classes from ruby
5
+ standard library to keep documents compressed. The example shows basic
6
+ technique, so that it can be used as a starting point to write your
7
+ custom data filters and adaptors.
8
+
9
+ ## Usage
10
+
11
+ 1. Clone the repository. Navigate to directory `examples/transcoders`.
12
+
13
+ 2. Install libcouchbase (http://www.couchbase.com/develop/c/current).
14
+ For MacOS users it will look like:
15
+
16
+ brew update
17
+ brew install libcouchbase
18
+
19
+ 3. Install all ruby dependencies. This demo has been tested on latest
20
+ stable version of ruby (`ruby 2.0.0p0 (2013-02-24 revision 39474)
21
+ [x86_64-linux]`)
22
+
23
+ gem install bundler
24
+ bundle install
25
+
26
+ 4. Setup your Couchbase server
27
+ (http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-getting-started.html).
28
+ It should have `default` bucket. Or you can specify different
29
+ bucket using CLI options.
30
+
31
+ 5. Store some file to the cluster:
32
+
33
+ $ ./cb-zcp Gemfile
34
+ Run with arguments: {:bucket=>"default", :hostname=>"127.0.0.1", :port=>8091, :username=>nil, :password=>nil}
35
+ store "Gemfile" ... ok
36
+
37
+ 6. Get the data back:
38
+
39
+ $ ./cb-zcat Gemfile
40
+ Run with arguments: {:bucket=>"default", :hostname=>"127.0.0.1", :port=>8091, :username=>nil, :password=>nil}
41
+ Gemfile:
42
+ source 'https://rubygems.org'
43
+
44
+ gem 'couchbase'
45
+
46
+ 7. To make sure that the data is in compressed state, you can check it in `irb`:
47
+
48
+ $ bundle exec irb
49
+ 2.0.0p0 (main):001:0> require 'couchbase'
50
+ true
51
+ 2.0.0p0 (main):002:0> conn = Couchbase.connect(:transcoder => nil)
52
+ #<Couchbase::Bucket:0x007fa344886fc8 "http://localhost:8091/pools/default/buckets/default/" transcoder=nil, default_flags=0x0, quiet=false, connected=true, timeout=2500000>
53
+ 2.0.0p0 (main):003:0> File.open("Gemfile.gz", "w+"){|f| f.write(conn.get("Gemfile"))}
54
+ 65
55
+
56
+ $ zcat Gemfile.gz
57
+ source 'https://rubygems.org'
58
+
59
+ gem 'couchbase'
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ # Author:: Couchbase <info@couchbase.com>
3
+ # Copyright:: 2013 Couchbase, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'bundler'
20
+ Bundler.setup
21
+
22
+ require 'couchbase'
23
+
24
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
25
+ require 'gzip_transcoder'
26
+ require 'options'
27
+
28
+ STDERR.puts "Run with arguments: #{OPTIONS.inspect}"
29
+ begin
30
+ conn = Couchbase.connect(OPTIONS)
31
+ conn.transcoder = GzipTranscoder.new
32
+
33
+ ARGV.each do |filename|
34
+ STDERR.puts "#{filename}:"
35
+ STDOUT.puts(conn.get(filename))
36
+ end
37
+ rescue Couchbase::Error::Base => ex
38
+ STDERR.puts "ERROR: #{ex}"
39
+ exit 1
40
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # Author:: Couchbase <info@couchbase.com>
3
+ # Copyright:: 2013 Couchbase, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'bundler'
20
+ Bundler.setup
21
+
22
+ require 'couchbase'
23
+
24
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
25
+ require 'gzip_transcoder'
26
+ require 'options'
27
+
28
+ STDERR.puts "Run with arguments: #{OPTIONS.inspect}"
29
+ begin
30
+ conn = Couchbase.connect(OPTIONS)
31
+ conn.transcoder = GzipTranscoder.new
32
+
33
+ ARGV.each do |filename|
34
+ STDERR.print "store \"#{filename}\" ... "
35
+ if File.exists?(filename)
36
+ conn.set(filename, File.read(filename))
37
+ STDERR.puts "ok"
38
+ else
39
+ STDERR.puts "not found"
40
+ end
41
+ end
42
+ rescue Couchbase::Error::Base => ex
43
+ STDERR.puts "ERROR: #{ex}"
44
+ exit 1
45
+ end
@@ -0,0 +1,49 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'zlib'
19
+ require 'stringio'
20
+
21
+ # This class wraps any other transcoder and performs compression
22
+ # using zlib
23
+ class GzipTranscoder
24
+ FMT_GZIP = 0x04
25
+
26
+ def initialize(base = nil)
27
+ @base = base || Couchbase::Transcoder::Plain
28
+ end
29
+
30
+ def dump(obj, flags, options = {})
31
+ obj, flags = @base.dump(obj, flags, options)
32
+ io = StringIO.new
33
+ gz = Zlib::GzipWriter.new(io)
34
+ gz.write(obj)
35
+ gz.close
36
+ [io.string, flags|FMT_GZIP]
37
+ end
38
+
39
+ def load(blob, flags, options = {})
40
+ # decompress value only if gzip flag set
41
+ if (flags & FMT_GZIP) == FMT_GZIP
42
+ io = StringIO.new(blob)
43
+ gz = Zlib::GzipReader.new(io)
44
+ blob = gz.read
45
+ gz.close
46
+ end
47
+ @base.load(blob, flags, options)
48
+ end
49
+ end
@@ -0,0 +1,54 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'optparse'
19
+
20
+ # just output extra empty line on CTRL-C
21
+ trap("INT") do
22
+ STDERR.puts
23
+ exit
24
+ end
25
+
26
+ OPTIONS = {
27
+ :bucket => "default",
28
+ :hostname => "127.0.0.1",
29
+ :port => 8091,
30
+ :username => nil,
31
+ :password => nil
32
+ }
33
+
34
+ OptionParser.new do |opts|
35
+ opts.banner = "Usage: #{$0} [options] keys"
36
+ opts.on("-h", "--hostname HOSTNAME", "Hostname to connect to (default: #{OPTIONS[:hostname]}:#{OPTIONS[:port]})") do |v|
37
+ host, port = v.split(':')
38
+ OPTIONS[:hostname] = host.empty? ? '127.0.0.1' : host
39
+ OPTIONS[:port] = port.to_i > 0 ? port.to_i : 8091
40
+ end
41
+ opts.on("-u", "--user USERNAME", "Username to log with (default: none)") do |v|
42
+ OPTIONS[:username] = v
43
+ end
44
+ opts.on("-p", "--password PASSWORD", "Password to log with (default: none)") do |v|
45
+ OPTIONS[:password] = v
46
+ end
47
+ opts.on("-b", "--bucket NAME", "Name of the bucket to connect to (default: #{OPTIONS[:bucket]})") do |v|
48
+ OPTIONS[:bucket] = v
49
+ end
50
+ opts.on_tail("-?", "--help", "Show this message") do
51
+ STDERR.puts opts
52
+ exit
53
+ end
54
+ end.parse!