libcouchbase-mapo 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/.travis.yml +38 -0
- data/Gemfile +4 -0
- data/LICENSE +24 -0
- data/README.md +445 -0
- data/Rakefile +76 -0
- data/ext/README.md +6 -0
- data/ext/Rakefile +19 -0
- data/lib/libcouchbase.rb +40 -0
- data/lib/libcouchbase/bucket.rb +825 -0
- data/lib/libcouchbase/callbacks.rb +69 -0
- data/lib/libcouchbase/connection.rb +886 -0
- data/lib/libcouchbase/design_docs.rb +92 -0
- data/lib/libcouchbase/error.rb +68 -0
- data/lib/libcouchbase/ext/libcouchbase.rb +1175 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdbase.rb +23 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdcounter.rb +36 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdendure.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdfts.rb +24 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdget.rb +30 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdgetreplica.rb +49 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdhttp.rb +58 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdn1ql.rb +40 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdobseqno.rb +33 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdobserve.rb +30 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdstore.rb +40 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdstoredur.rb +45 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +61 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdverbosity.rb +29 -0
- data/lib/libcouchbase/ext/libcouchbase/cmdviewquery.rb +61 -0
- data/lib/libcouchbase/ext/libcouchbase/contigbuf.rb +14 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st.rb +15 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st0.rb +23 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st1.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st2.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/create_st3.rb +26 -0
- data/lib/libcouchbase/ext/libcouchbase/crst_u.rb +20 -0
- data/lib/libcouchbase/ext/libcouchbase/durability_opts_st_v.rb +11 -0
- data/lib/libcouchbase/ext/libcouchbase/durability_opts_t.rb +14 -0
- data/lib/libcouchbase/ext/libcouchbase/durabilityopt_sv0.rb +63 -0
- data/lib/libcouchbase/ext/libcouchbase/enums.rb +1007 -0
- data/lib/libcouchbase/ext/libcouchbase/fragbuf.rb +18 -0
- data/lib/libcouchbase/ext/libcouchbase/ftshandle.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/histogram.rb +34 -0
- data/lib/libcouchbase/ext/libcouchbase/http_request_t.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/keybuf.rb +20 -0
- data/lib/libcouchbase/ext/libcouchbase/multicmd_ctx.rb +30 -0
- data/lib/libcouchbase/ext/libcouchbase/mutation_token.rb +17 -0
- data/lib/libcouchbase/ext/libcouchbase/n1qlhandle.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/n1qlparams.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/respbase.rb +29 -0
- data/lib/libcouchbase/ext/libcouchbase/respcounter.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/respendure.rb +49 -0
- data/lib/libcouchbase/ext/libcouchbase/respfts.rb +40 -0
- data/lib/libcouchbase/ext/libcouchbase/respget.rb +44 -0
- data/lib/libcouchbase/ext/libcouchbase/resphttp.rb +48 -0
- data/lib/libcouchbase/ext/libcouchbase/respmcversion.rb +38 -0
- data/lib/libcouchbase/ext/libcouchbase/respn1ql.rb +41 -0
- data/lib/libcouchbase/ext/libcouchbase/respobseqno.rb +52 -0
- data/lib/libcouchbase/ext/libcouchbase/respobserve.rb +41 -0
- data/lib/libcouchbase/ext/libcouchbase/respserverbase.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/respstats.rb +38 -0
- data/lib/libcouchbase/ext/libcouchbase/respstore.rb +32 -0
- data/lib/libcouchbase/ext/libcouchbase/respstoredur.rb +38 -0
- data/lib/libcouchbase/ext/libcouchbase/respsubdoc.rb +35 -0
- data/lib/libcouchbase/ext/libcouchbase/respviewquery.rb +67 -0
- data/lib/libcouchbase/ext/libcouchbase/sdentry.rb +22 -0
- data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +31 -0
- data/lib/libcouchbase/ext/libcouchbase/t.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase/valbuf.rb +22 -0
- data/lib/libcouchbase/ext/libcouchbase/valbuf_u_buf.rb +14 -0
- data/lib/libcouchbase/ext/libcouchbase/viewhandle.rb +7 -0
- data/lib/libcouchbase/ext/libcouchbase_libuv.rb +22 -0
- data/lib/libcouchbase/ext/tasks.rb +39 -0
- data/lib/libcouchbase/n1ql.rb +78 -0
- data/lib/libcouchbase/query_full_text.rb +147 -0
- data/lib/libcouchbase/query_n1ql.rb +123 -0
- data/lib/libcouchbase/query_view.rb +135 -0
- data/lib/libcouchbase/results_fiber.rb +281 -0
- data/lib/libcouchbase/results_native.rb +220 -0
- data/lib/libcouchbase/subdoc_request.rb +139 -0
- data/lib/libcouchbase/version.rb +5 -0
- data/libcouchbase.gemspec +68 -0
- data/spec/bucket_spec.rb +290 -0
- data/spec/connection_spec.rb +257 -0
- data/spec/design_docs_spec.rb +31 -0
- data/spec/error_spec.rb +26 -0
- data/spec/fts_spec.rb +135 -0
- data/spec/n1ql_spec.rb +206 -0
- data/spec/results_libuv_spec.rb +244 -0
- data/spec/results_native_spec.rb +259 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/design.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/data-0000.cbb +0 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/failover.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/meta.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/seqno.json +1 -0
- data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/snapshot_markers.json +1 -0
- data/spec/subdoc_spec.rb +192 -0
- data/spec/view_spec.rb +201 -0
- data/windows_build.md +36 -0
- metadata +265 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true, encoding: ASCII-8BIT
|
2
|
+
|
3
|
+
module Libcouchbase; end;
|
4
|
+
class Libcouchbase::SubdocRequest
|
5
|
+
|
6
|
+
def initialize(key, quiet, bucket: nil, exec_opts: nil)
|
7
|
+
@key = key.to_s
|
8
|
+
raise ArgumentError.new("invalid document key #{key.inspect}") unless @key.length > 0
|
9
|
+
@refs = []
|
10
|
+
@mode = nil
|
11
|
+
@quiet = quiet
|
12
|
+
@specs = []
|
13
|
+
@ignore = []
|
14
|
+
|
15
|
+
@bucket = bucket
|
16
|
+
@exec_opts = exec_opts
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :mode, :key, :ignore
|
20
|
+
|
21
|
+
# Internal use only
|
22
|
+
def to_specs_array
|
23
|
+
return @mem if @mem # effectively freezes this object
|
24
|
+
number = @specs.length
|
25
|
+
@mem = FFI::MemoryPointer.new(::Libcouchbase::Ext::SDSPEC, number, false)
|
26
|
+
@specs.each_with_index do |spec, index|
|
27
|
+
struct_bytes = spec.to_ptr.get_bytes(0, ::Libcouchbase::Ext::SDSPEC.size) # (offset, length)
|
28
|
+
@mem[index].put_bytes(0, struct_bytes) # (offset, byte_string)
|
29
|
+
end
|
30
|
+
@specs = nil
|
31
|
+
[@mem, number]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Internal use only
|
35
|
+
def free_memory
|
36
|
+
@refs = nil
|
37
|
+
@mem = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# When not used in block form
|
41
|
+
def execute!(**opts)
|
42
|
+
opts = @exec_opts.merge(opts)
|
43
|
+
@exec_opts = nil
|
44
|
+
bucket = @bucket
|
45
|
+
@bucket = nil
|
46
|
+
bucket.subdoc_execute!(self, **opts)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# =========
|
51
|
+
# Lookups
|
52
|
+
# =========
|
53
|
+
|
54
|
+
[ :get, :exists, :get_count ].each do |cmd|
|
55
|
+
command = :"sdcmd_#{cmd}"
|
56
|
+
define_method cmd do |path, quiet: nil, **opts|
|
57
|
+
quiet = @quiet if quiet.nil?
|
58
|
+
new_spec(quiet, path, command, :lookup)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
end
|
62
|
+
alias_method :exists?, :exists
|
63
|
+
|
64
|
+
|
65
|
+
# ===========
|
66
|
+
# Mutations
|
67
|
+
# ===========
|
68
|
+
|
69
|
+
def remove(path, quiet: nil, **opts)
|
70
|
+
quiet = @quiet if quiet.nil?
|
71
|
+
new_spec(quiet, path, :sdcmd_remove, :mutate)
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
[
|
76
|
+
:dict_add, :dict_upsert, :array_add_first, :array_add_last, :array_add_unique, :counter
|
77
|
+
].each do |cmd|
|
78
|
+
command = :"sdcmd_#{cmd}"
|
79
|
+
define_method cmd do |path, value, create_intermediates: true, **opts|
|
80
|
+
spec = new_spec(false, path, command, :mutate, create_intermediates)
|
81
|
+
set_value(spec, value)
|
82
|
+
self
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
[
|
87
|
+
:replace, :array_insert
|
88
|
+
].each do |cmd|
|
89
|
+
command = :"sdcmd_#{cmd}"
|
90
|
+
define_method cmd do |path, value, **opts|
|
91
|
+
spec = new_spec(false, path, command, :mutate, false)
|
92
|
+
set_value(spec, value)
|
93
|
+
self
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
protected
|
99
|
+
|
100
|
+
|
101
|
+
# http://docs.couchbase.com/sdk-api/couchbase-c-client-2.8.2/group__lcb-subdoc.html#ga53e89dd6b480e81b82fb305d04d92e18
|
102
|
+
def new_spec(quiet, path, cmd, mode, create_intermediates = false)
|
103
|
+
@mode ||= mode
|
104
|
+
raise "unable to perform #{cmd} as mode is currently #{@mode}" if @mode != mode
|
105
|
+
|
106
|
+
spec = ::Libcouchbase::Ext::SDSPEC.new
|
107
|
+
spec[:sdcmd] = ::Libcouchbase::Ext::SUBDOCOP[cmd]
|
108
|
+
spec[:options] = ::Libcouchbase::Ext::SDSPEC::MKINTERMEDIATES if create_intermediates
|
109
|
+
|
110
|
+
loc = path.to_s
|
111
|
+
str = ref(loc)
|
112
|
+
spec[:path][:type] = :kv_copy
|
113
|
+
spec[:path][:contig][:bytes] = str
|
114
|
+
spec[:path][:contig][:nbytes] = loc.bytesize
|
115
|
+
|
116
|
+
@ignore << quiet
|
117
|
+
@specs << spec
|
118
|
+
spec
|
119
|
+
end
|
120
|
+
|
121
|
+
# http://docs.couchbase.com/sdk-api/couchbase-c-client-2.8.2/group__lcb-subdoc.html#ga61009762f6b23ae2a9685ddb888dc406
|
122
|
+
def set_value(spec, value)
|
123
|
+
# Create a JSON version of the value.
|
124
|
+
# We throw it into an array so strings and numbers etc are valid, then we remove the array.
|
125
|
+
val = [value].to_json[1...-1]
|
126
|
+
str = ref(val)
|
127
|
+
spec[:value][:vtype] = :kv_copy
|
128
|
+
spec[:value][:u_buf][:contig][:bytes] = str
|
129
|
+
spec[:value][:u_buf][:contig][:nbytes] = val.bytesize
|
130
|
+
value
|
131
|
+
end
|
132
|
+
|
133
|
+
# We need to hold a reference to c-strings so they are not GC'd
|
134
|
+
def ref(string)
|
135
|
+
str = ::FFI::MemoryPointer.from_string(string)
|
136
|
+
@refs << str
|
137
|
+
str
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.expand_path("../lib/libcouchbase/version", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "libcouchbase-mapo"
|
5
|
+
gem.version = Libcouchbase::VERSION
|
6
|
+
gem.license = 'MIT'
|
7
|
+
gem.authors = ["Stephen von Takach"]
|
8
|
+
gem.email = ["steve@cotag.me"]
|
9
|
+
gem.homepage = "https://github.com/cotag/libcouchbase"
|
10
|
+
gem.summary = "libcouchbase bindings for Ruby"
|
11
|
+
gem.description = "A wrapper around libcouchbase for Ruby"
|
12
|
+
|
13
|
+
gem.extensions << "ext/Rakefile"
|
14
|
+
|
15
|
+
gem.required_ruby_version = '>= 2.1.0'
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
|
18
|
+
gem.add_runtime_dependency 'ffi', '~> 1.9'
|
19
|
+
gem.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
20
|
+
gem.add_runtime_dependency 'libuv', '>= 3.2.2', '< 5'
|
21
|
+
|
22
|
+
gem.add_development_dependency 'rake', '~> 11.2'
|
23
|
+
gem.add_development_dependency 'rspec', '~> 3.5'
|
24
|
+
gem.add_development_dependency 'yard', '~> 0.9'
|
25
|
+
gem.add_development_dependency 'uv-rays', '~> 2.0' # for libuv results spec
|
26
|
+
gem.add_development_dependency 'em-synchrony', '~> 1.0' # for eventmachine spec
|
27
|
+
|
28
|
+
# https://github.com/stakach/ffi-gen
|
29
|
+
# gem.add_development_dependency 'ffi-gen'
|
30
|
+
|
31
|
+
gem.files = `git ls-files`.split("\n")
|
32
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
33
|
+
|
34
|
+
if File.exist? 'ext/libcouchbase.dll'
|
35
|
+
gem.files += ['ext/libcouchbase.dll', 'ext/libcouchbase_libuv.dll']
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add the submodule to the gem
|
39
|
+
relative_path = File.expand_path("../", __FILE__) + '/'
|
40
|
+
`git submodule --quiet foreach pwd`.split($\).each do |submodule_path|
|
41
|
+
|
42
|
+
if (ENV['OS'] == 'Windows_NT') && submodule_path[0] == '/'
|
43
|
+
# Detect if cygwin path is being used by git
|
44
|
+
submodule_path = submodule_path[1..-1]
|
45
|
+
submodule_path.insert(1, ':')
|
46
|
+
end
|
47
|
+
|
48
|
+
# for each submodule, change working directory to that submodule
|
49
|
+
Dir.chdir(submodule_path) do
|
50
|
+
# Make the submodule path relative
|
51
|
+
submodule_path = submodule_path.gsub(/#{relative_path}/i, '')
|
52
|
+
|
53
|
+
# issue git ls-files in submodule's directory
|
54
|
+
submodule_files = `git ls-files`.split($\)
|
55
|
+
|
56
|
+
# prepend the submodule path to create relative file paths
|
57
|
+
submodule_files_paths = submodule_files.map do |filename|
|
58
|
+
File.join(submodule_path, filename)
|
59
|
+
end
|
60
|
+
|
61
|
+
# add relative paths to gem.files
|
62
|
+
gem.files += submodule_files_paths
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Remove sym link (blows up on windows)
|
67
|
+
gem.files.delete('ext/libcouchbase/configure.pl')
|
68
|
+
end
|
data/spec/bucket_spec.rb
ADDED
@@ -0,0 +1,290 @@
|
|
1
|
+
# frozen_string_literal: true, encoding: ASCII-8BIT
|
2
|
+
|
3
|
+
require 'libcouchbase'
|
4
|
+
Libcouchbase::Defaults.username = 'tester'
|
5
|
+
Libcouchbase::Defaults.password = 'password123'
|
6
|
+
|
7
|
+
describe Libcouchbase::Bucket do
|
8
|
+
before :each do
|
9
|
+
# This will load the couchbase connection on a different thread
|
10
|
+
@bucket = Libcouchbase::Bucket.new
|
11
|
+
@reactor = ::Libuv::Reactor.default
|
12
|
+
@log = []
|
13
|
+
end
|
14
|
+
|
15
|
+
after :each do
|
16
|
+
@bucket = nil
|
17
|
+
@reactor = nil
|
18
|
+
@log = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'reactor loop' do
|
22
|
+
it "should set a value" do
|
23
|
+
@reactor.run { |reactor|
|
24
|
+
result = @bucket.set('somekey', 'woop woop')
|
25
|
+
@log << result.key
|
26
|
+
@log << result.value
|
27
|
+
@log << @bucket.set('somekey2', 'woop woop2').value
|
28
|
+
}
|
29
|
+
|
30
|
+
expect(@log).to eq(['somekey', 'woop woop', 'woop woop2'])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should get a value" do
|
34
|
+
@reactor.run { |reactor|
|
35
|
+
@log << @bucket.get('somekey')
|
36
|
+
@log << @bucket.get('somekey', extended: true).value
|
37
|
+
}
|
38
|
+
expect(@log).to eq(['woop woop', 'woop woop'])
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should get a value quietly" do
|
42
|
+
@reactor.run { |reactor|
|
43
|
+
@log << @bucket.get('somekey-noexist', quiet: true)
|
44
|
+
@log << @bucket[:noexist2]
|
45
|
+
}
|
46
|
+
expect(@log).to eq([nil, nil])
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should get multiple values" do
|
50
|
+
@reactor.run { |reactor|
|
51
|
+
@log << @bucket.get('somekey', 'somekey2')
|
52
|
+
@log << @bucket.get('somekey', 'somekey2', 'no-exist-sgs', quiet: true)
|
53
|
+
}
|
54
|
+
expect(@log).to eq([['woop woop', 'woop woop2'], ['woop woop', 'woop woop2', nil]])
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should get multiple values as a hash" do
|
58
|
+
@reactor.run { |reactor|
|
59
|
+
@log << @bucket.get('somekey', 'somekey2', assemble_hash: true)
|
60
|
+
@log << @bucket.get('somekey', 'somekey2', 'no-exist-sgs', quiet: true, assemble_hash: true)
|
61
|
+
@log << @bucket.get('somekey', assemble_hash: true)
|
62
|
+
@log << @bucket.get('no-exist-sgs', quiet: true, assemble_hash: true)
|
63
|
+
}
|
64
|
+
expect(@log).to eq([
|
65
|
+
{'somekey' => 'woop woop', 'somekey2' => 'woop woop2'},
|
66
|
+
{'somekey' => 'woop woop', 'somekey2' => 'woop woop2', 'no-exist-sgs' => nil},
|
67
|
+
{'somekey' => 'woop woop'},
|
68
|
+
{'no-exist-sgs' => nil}
|
69
|
+
])
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should compare and swap a value" do
|
73
|
+
@reactor.run { |reactor|
|
74
|
+
@bucket.set('somekey', 'woop woop')
|
75
|
+
result = @bucket.cas('somekey') do |current|
|
76
|
+
@log << current
|
77
|
+
"current #{current}"
|
78
|
+
end
|
79
|
+
@log << result.value
|
80
|
+
}
|
81
|
+
expect(@log).to eq(['woop woop', 'current woop woop'])
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should fetch a value" do
|
85
|
+
@reactor.run { |reactor|
|
86
|
+
@bucket.delete('randomunknown')
|
87
|
+
@log << @bucket.fetch('randomunknown', 'woop woop')
|
88
|
+
@log << @bucket.fetch('randomunknown') { 'testing' }
|
89
|
+
|
90
|
+
@bucket.delete('otherunknown')
|
91
|
+
@log << @bucket.fetch('otherunknown') { 'testing' }
|
92
|
+
@log << @bucket.fetch('otherunknown', 'woop woop')
|
93
|
+
}
|
94
|
+
expect(@log).to eq(['woop woop', 'woop woop', 'testing', 'testing'])
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should retry when performing a CAS operation" do
|
98
|
+
@reactor.run { |reactor|
|
99
|
+
begin
|
100
|
+
@bucket.set('somekey', 'woop woop')
|
101
|
+
result = @bucket.cas('somekey', retry: 2) do |current|
|
102
|
+
@log << current
|
103
|
+
# This ensures the operation fails
|
104
|
+
@bucket.set('somekey', 'woop woop1')
|
105
|
+
"current #{current}"
|
106
|
+
end
|
107
|
+
@log << result.value
|
108
|
+
rescue Libcouchbase::Error::KeyExists
|
109
|
+
@log << :error
|
110
|
+
end
|
111
|
+
}
|
112
|
+
expect(@log).to eq(['woop woop', 'woop woop1', 'woop woop1', :error])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'native ruby' do
|
117
|
+
it "should set a value" do
|
118
|
+
result = @bucket.set('somekey', 'woop woop')
|
119
|
+
@log << result.key
|
120
|
+
@log << result.value
|
121
|
+
@log << @bucket.set('somekey2', 'woop woop2').value
|
122
|
+
|
123
|
+
expect(@log).to eq(['somekey', 'woop woop', 'woop woop2'])
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should get a value" do
|
127
|
+
@log << @bucket.get('somekey')
|
128
|
+
@log << @bucket.get('somekey', extended: true).value
|
129
|
+
|
130
|
+
expect(@log).to eq(['woop woop', 'woop woop'])
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should get a value quietly" do
|
134
|
+
@log << @bucket.get('somekey-noexist', quiet: true)
|
135
|
+
@log << @bucket[:noexist2]
|
136
|
+
|
137
|
+
expect(@log).to eq([nil, nil])
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should get multiple values" do
|
141
|
+
@log << @bucket.get('somekey', 'somekey2')
|
142
|
+
@log << @bucket.get('somekey', 'somekey2', 'no-exist-sgs', quiet: true)
|
143
|
+
|
144
|
+
expect(@log).to eq([['woop woop', 'woop woop2'], ['woop woop', 'woop woop2', nil]])
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should get multiple values as a hash" do
|
148
|
+
@log << @bucket.get('somekey', 'somekey2', assemble_hash: true)
|
149
|
+
@log << @bucket.get('somekey', 'somekey2', 'no-exist-sgs', quiet: true, assemble_hash: true)
|
150
|
+
@log << @bucket.get('somekey', assemble_hash: true)
|
151
|
+
@log << @bucket.get('no-exist-sgs', quiet: true, assemble_hash: true)
|
152
|
+
|
153
|
+
expect(@log).to eq([
|
154
|
+
{'somekey' => 'woop woop', 'somekey2' => 'woop woop2'},
|
155
|
+
{'somekey' => 'woop woop', 'somekey2' => 'woop woop2', 'no-exist-sgs' => nil},
|
156
|
+
{'somekey' => 'woop woop'},
|
157
|
+
{'no-exist-sgs' => nil}
|
158
|
+
])
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should get multiple results asynchronously and then wait for the results" do
|
162
|
+
results = []
|
163
|
+
results << @bucket.get('somekey', async: true)
|
164
|
+
results << @bucket.get('somekey2', async: true)
|
165
|
+
|
166
|
+
@log = @bucket.wait_results results
|
167
|
+
|
168
|
+
expect(@log).to eq(['woop woop', 'woop woop2'])
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should compare and swap a value" do
|
172
|
+
@bucket.set('somekey', 'woop woop')
|
173
|
+
result = @bucket.cas('somekey') do |current|
|
174
|
+
@log << current
|
175
|
+
"current #{current}"
|
176
|
+
end
|
177
|
+
@log << result.value
|
178
|
+
|
179
|
+
expect(@log).to eq(['woop woop', 'current woop woop'])
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should retry when performing a CAS operation" do
|
183
|
+
begin
|
184
|
+
@bucket.set('somekey', 'woop woop')
|
185
|
+
result = @bucket.cas('somekey', retry: 2) do |current|
|
186
|
+
@log << current
|
187
|
+
# This ensures the operation fails
|
188
|
+
@bucket.set('somekey', 'woop woop1')
|
189
|
+
"current #{current}"
|
190
|
+
end
|
191
|
+
@log << result.value
|
192
|
+
rescue Libcouchbase::Error::KeyExists
|
193
|
+
@log << :error
|
194
|
+
end
|
195
|
+
|
196
|
+
expect(@log).to eq(['woop woop', 'woop woop1', 'woop woop1', :error])
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe 'eventmachine loop' do
|
201
|
+
require 'em-synchrony'
|
202
|
+
|
203
|
+
it "should set a value" do
|
204
|
+
EM.synchrony {
|
205
|
+
result = @bucket.set('somekey', 'woop woop')
|
206
|
+
@log << result.key
|
207
|
+
@log << result.value
|
208
|
+
@log << @bucket.set('somekey2', 'woop woop2').value
|
209
|
+
EM.stop
|
210
|
+
}
|
211
|
+
|
212
|
+
expect(@log).to eq(['somekey', 'woop woop', 'woop woop2'])
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should get a value" do
|
216
|
+
EM.synchrony {
|
217
|
+
@log << @bucket.get('somekey')
|
218
|
+
@log << @bucket.get('somekey', extended: true).value
|
219
|
+
EM.stop
|
220
|
+
}
|
221
|
+
expect(@log).to eq(['woop woop', 'woop woop'])
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should get a value quietly" do
|
225
|
+
EM.synchrony {
|
226
|
+
@log << @bucket.get('somekey-noexist', quiet: true)
|
227
|
+
@log << @bucket[:noexist2]
|
228
|
+
EM.stop
|
229
|
+
}
|
230
|
+
expect(@log).to eq([nil, nil])
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should get multiple values" do
|
234
|
+
EM.synchrony {
|
235
|
+
@log << @bucket.get('somekey', 'somekey2')
|
236
|
+
@log << @bucket.get('somekey', 'somekey2', 'no-exist-sgs', quiet: true)
|
237
|
+
EM.stop
|
238
|
+
}
|
239
|
+
expect(@log).to eq([['woop woop', 'woop woop2'], ['woop woop', 'woop woop2', nil]])
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should get multiple values as a hash" do
|
243
|
+
EM.synchrony {
|
244
|
+
@log << @bucket.get('somekey', 'somekey2', assemble_hash: true)
|
245
|
+
@log << @bucket.get('somekey', 'somekey2', 'no-exist-sgs', quiet: true, assemble_hash: true)
|
246
|
+
@log << @bucket.get('somekey', assemble_hash: true)
|
247
|
+
@log << @bucket.get('no-exist-sgs', quiet: true, assemble_hash: true)
|
248
|
+
EM.stop
|
249
|
+
}
|
250
|
+
expect(@log).to eq([
|
251
|
+
{'somekey' => 'woop woop', 'somekey2' => 'woop woop2'},
|
252
|
+
{'somekey' => 'woop woop', 'somekey2' => 'woop woop2', 'no-exist-sgs' => nil},
|
253
|
+
{'somekey' => 'woop woop'},
|
254
|
+
{'no-exist-sgs' => nil}
|
255
|
+
])
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should compare and swap a value" do
|
259
|
+
EM.synchrony {
|
260
|
+
@bucket.set('somekey', 'woop woop')
|
261
|
+
result = @bucket.cas('somekey') do |current|
|
262
|
+
@log << current
|
263
|
+
"current #{current}"
|
264
|
+
end
|
265
|
+
@log << result.value
|
266
|
+
EM.stop
|
267
|
+
}
|
268
|
+
expect(@log).to eq(['woop woop', 'current woop woop'])
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should retry when performing a CAS operation" do
|
272
|
+
EM.synchrony {
|
273
|
+
begin
|
274
|
+
@bucket.set('somekey', 'woop woop')
|
275
|
+
result = @bucket.cas('somekey', retry: 2) do |current|
|
276
|
+
@log << current
|
277
|
+
# This ensures the operation fails
|
278
|
+
@bucket.set('somekey', 'woop woop1')
|
279
|
+
"current #{current}"
|
280
|
+
end
|
281
|
+
@log << result.value
|
282
|
+
rescue Libcouchbase::Error::KeyExists
|
283
|
+
@log << :error
|
284
|
+
end
|
285
|
+
EM.stop
|
286
|
+
}
|
287
|
+
expect(@log).to eq(['woop woop', 'woop woop1', 'woop woop1', :error])
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|