libcouchbase-mapo 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|