riak-client 2.4.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.document +5 -5
  3. data/.gitignore +3 -0
  4. data/Gemfile +17 -17
  5. data/Guardfile +20 -20
  6. data/LICENSE.md +16 -16
  7. data/RELNOTES.md +4 -0
  8. data/Rakefile +6 -1
  9. data/lib/riak/client/beefcake/crdt/counter_loader.rb +18 -18
  10. data/lib/riak/client/beefcake/crdt/hyper_log_log_loader.rb +18 -0
  11. data/lib/riak/client/beefcake/crdt/map_loader.rb +64 -64
  12. data/lib/riak/client/beefcake/crdt_loader.rb +4 -1
  13. data/lib/riak/client/beefcake/crdt_operator.rb +13 -0
  14. data/lib/riak/client/beefcake/footer +4 -4
  15. data/lib/riak/client/beefcake/header +6 -6
  16. data/lib/riak/client/beefcake/messages.rb +67 -10
  17. data/lib/riak/client/decaying.rb +36 -36
  18. data/lib/riak/client/feature_detection.rb +120 -120
  19. data/lib/riak/client/instrumentation.rb +19 -19
  20. data/lib/riak/client/node.rb +49 -49
  21. data/lib/riak/client/search.rb +27 -27
  22. data/lib/riak/conflict.rb +13 -13
  23. data/lib/riak/core_ext.rb +7 -7
  24. data/lib/riak/core_ext/blank.rb +53 -53
  25. data/lib/riak/core_ext/extract_options.rb +7 -7
  26. data/lib/riak/core_ext/json.rb +15 -15
  27. data/lib/riak/core_ext/slice.rb +18 -18
  28. data/lib/riak/core_ext/stringify_keys.rb +10 -10
  29. data/lib/riak/core_ext/symbolize_keys.rb +10 -10
  30. data/lib/riak/core_ext/to_param.rb +31 -31
  31. data/lib/riak/crdt.rb +23 -21
  32. data/lib/riak/crdt/base.rb +1 -1
  33. data/lib/riak/crdt/hyper_log_log.rb +97 -0
  34. data/lib/riak/crdt/operation.rb +19 -19
  35. data/lib/riak/encoding.rb +6 -6
  36. data/lib/riak/errors/backend_creation.rb +9 -9
  37. data/lib/riak/errors/connection_error.rb +50 -50
  38. data/lib/riak/errors/protobuffs_error.rb +11 -11
  39. data/lib/riak/i18n.rb +7 -7
  40. data/lib/riak/instrumentation.rb +6 -6
  41. data/lib/riak/json.rb +52 -52
  42. data/lib/riak/list_buckets.rb +28 -28
  43. data/lib/riak/locale/en.yml +1 -0
  44. data/lib/riak/locale/fr.yml +51 -51
  45. data/lib/riak/map_reduce/results.rb +49 -49
  46. data/lib/riak/map_reduce_error.rb +7 -7
  47. data/lib/riak/multiget.rb +122 -122
  48. data/lib/riak/robject.rb +17 -1
  49. data/lib/riak/search/result_document.rb +9 -0
  50. data/lib/riak/stamp.rb +77 -77
  51. data/lib/riak/tombstone.rb +13 -0
  52. data/lib/riak/util/tcp_socket_extensions.rb +58 -58
  53. data/lib/riak/version.rb +1 -1
  54. data/spec/failover/failover.rb +59 -59
  55. data/spec/fixtures/bitcask.txt +25 -25
  56. data/spec/fixtures/multipart-basic-conflict.txt +15 -15
  57. data/spec/fixtures/multipart-blank.txt +7 -7
  58. data/spec/fixtures/multipart-mapreduce.txt +10 -10
  59. data/spec/fixtures/multipart-with-body.txt +16 -16
  60. data/spec/fixtures/multipart-with-marked-tombstones.txt +17 -17
  61. data/spec/fixtures/multipart-with-unmarked-tombstone.txt +16 -16
  62. data/spec/fixtures/server.cert.crt +15 -15
  63. data/spec/fixtures/server.cert.key +15 -15
  64. data/spec/fixtures/test.pem +1 -1
  65. data/spec/integration/riak/bucket_types_spec.rb +38 -0
  66. data/spec/integration/riak/crdt/configuration_spec.rb +4 -3
  67. data/spec/integration/riak/crdt_spec.rb +70 -0
  68. data/spec/integration/riak/encodings/crdt_spec.rb +29 -3
  69. data/spec/integration/riak/encodings/yz_spec.rb +2 -1
  70. data/spec/integration/riak/preflist_spec.rb +15 -3
  71. data/spec/integration/riak/protobuffs/timeouts_spec.rb +1 -1
  72. data/spec/integration/riak/security_spec.rb +11 -6
  73. data/spec/integration/riak/threading_spec.rb +154 -150
  74. data/spec/integration/yokozuna/index_spec.rb +61 -61
  75. data/spec/integration/yokozuna/queries_spec.rb +1 -1
  76. data/spec/integration/yokozuna/schema_spec.rb +49 -49
  77. data/spec/riak/beefcake_protobuffs_backend/crdt_operator_spec.rb +22 -0
  78. data/spec/riak/core_ext/to_param_spec.rb +15 -15
  79. data/spec/riak/crdt/hyper_log_log_spec.rb +56 -0
  80. data/spec/riak/crdt/inner_counter_spec.rb +21 -21
  81. data/spec/riak/crdt/inner_set_spec.rb +33 -33
  82. data/spec/riak/crdt/set_spec.rb +61 -61
  83. data/spec/riak/crdt/shared_examples.rb +14 -0
  84. data/spec/riak/escape_spec.rb +72 -72
  85. data/spec/riak/feature_detection_spec.rb +77 -77
  86. data/spec/riak/index_collection_spec.rb +53 -53
  87. data/spec/riak/instrumentation_spec.rb +124 -124
  88. data/spec/riak/link_spec.rb +85 -85
  89. data/spec/riak/list_buckets_spec.rb +41 -41
  90. data/spec/riak/node_spec.rb +26 -26
  91. data/spec/riak/robject_spec.rb +45 -0
  92. data/spec/support/certs/README.md +12 -12
  93. data/spec/support/certs/ca.crt +21 -21
  94. data/spec/support/certs/client.crl +13 -13
  95. data/spec/support/certs/client.crt +94 -94
  96. data/spec/support/certs/client.csr +18 -18
  97. data/spec/support/certs/client.key +27 -27
  98. data/spec/support/certs/empty_ca.crt +21 -21
  99. data/spec/support/certs/server.crl +13 -13
  100. data/spec/support/certs/server.crt +94 -94
  101. data/spec/support/certs/server.key +27 -27
  102. data/spec/support/crdt_search_fixtures.rb +1 -1
  103. data/spec/support/integration_setup.rb +10 -10
  104. data/spec/support/test_client.rb +1 -1
  105. data/spec/support/test_client.yml.example +10 -10
  106. metadata +10 -3
@@ -1,6 +1,7 @@
1
1
  # coding: utf-8
2
2
  require 'spec_helper'
3
3
  require 'riak'
4
+ require 'riak/util/string'
4
5
 
5
6
  describe 'Encoding and Riak Search', integration: true, search_config: true do
6
7
  let(:bucket_type){ test_client.bucket_type 'yokozuna' }
@@ -72,7 +73,7 @@ EOD
72
73
  expect(results).to_not be_empty
73
74
  expect(results.docs.first.bucket_type).to eq robj.bucket.type
74
75
  expect(results.docs.first.bucket).to eq robj.bucket
75
- expect(results.docs.first.key.bytes).to eq robj.key.bytes
76
+ expect(Riak::Util::String.equal_bytes?(results.docs.first.key, robj.key)).to be
76
77
  end
77
78
  end
78
79
 
@@ -18,14 +18,26 @@ describe 'Preflist', integration: true, test_client: true do
18
18
  end
19
19
 
20
20
  it 'is available from RObjects' do
21
- expect(robject.preflist).to be_a_preflist
21
+ begin
22
+ expect(robject.preflist).to be_a_preflist
23
+ rescue Riak::ProtobuffsErrorResponse
24
+ skip('preflists are not supported')
25
+ end
22
26
  end
23
27
 
24
28
  it 'is available from Buckets' do
25
- expect(bucket.get_preflist robject.key).to be_a_preflist
29
+ begin
30
+ expect(bucket.get_preflist robject.key).to be_a_preflist
31
+ rescue Riak::ProtobuffsErrorResponse
32
+ skip('preflists are not supported')
33
+ end
26
34
  end
27
35
 
28
36
  it 'is available from the Client' do
29
- expect(test_client.get_preflist bucket.name, robject.key).to be_a_preflist
37
+ begin
38
+ expect(test_client.get_preflist bucket.name, robject.key).to be_a_preflist
39
+ rescue Riak::ProtobuffsErrorResponse
40
+ skip('preflists are not supported')
41
+ end
30
42
  end
31
43
  end
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  require 'riak/client/beefcake/messages'
5
5
  require 'riak/client/beefcake/protocol'
6
6
 
7
- describe 'Protocol Buffers', test_client: true, integration: true do
7
+ describe 'Protocol Buffers', test_client: true, integration: true, slow: true do
8
8
  if RUBY_VERSION >= '2.0.0'
9
9
  describe 'timeouts' do
10
10
  it 'raises error on connect timeout' do
@@ -51,9 +51,14 @@ describe 'Secure Protobuffs', test_client: true, integration: true do
51
51
 
52
52
  bugged_crypto_client = Riak::Client.new broken_auth_config
53
53
 
54
- expect{ bugged_crypto_client.ping }.
55
- to(raise_error(OpenSSL::SSL::SSLError,
56
- /certificate verify failed/i))
54
+ if RUBY_PLATFORM == 'java'
55
+ expect{ bugged_crypto_client.ping }.
56
+ to(raise_error(OpenSSL::SSL::SSLError))
57
+ else
58
+ expect{ bugged_crypto_client.ping }.
59
+ to(raise_error(OpenSSL::SSL::SSLError,
60
+ /certificate verify failed/i))
61
+ end
57
62
  end
58
63
 
59
64
  it "refuses to connect if the server cert is revoked" do
@@ -86,10 +91,10 @@ describe 'Secure Protobuffs', test_client: true, integration: true do
86
91
 
87
92
  client_cert_config[:authentication][:client_ca] = client_cert_config[:authentication]['ca_file']
88
93
 
89
- client_cert_config[:authentication][:cert] = 'spec/support/certs/client.crt'
90
- client_cert_config[:authentication][:key] = 'spec/support/certs/client.key'
94
+ client_cert_config[:authentication][:cert] = 'tools/test-ca/certs/riakuser-client-cert.pem'
95
+ client_cert_config[:authentication][:key] = 'tools/test-ca/private/riakuser-client-cert-key.pem'
91
96
 
92
- client_cert_config[:authentication][:user] = 'certuser'
97
+ client_cert_config[:authentication][:user] = 'riakuser'
93
98
  client_cert_config[:authentication][:password] = ''
94
99
 
95
100
  cert_client = Riak::Client.new client_cert_config
@@ -1,150 +1,154 @@
1
- require 'spec_helper'
2
-
3
- describe "Multithreaded client", :test_client => true do
4
- class Synchronizer
5
- def initialize(n)
6
- @mutex = Mutex.new
7
- @n = n
8
- @waiting = Set.new
9
- end
10
-
11
- def sync
12
- stop = false
13
- @mutex.synchronize do
14
- @waiting << Thread.current
15
-
16
- if @waiting.size >= @n
17
- # All threads are waiting.
18
- @waiting.each do |t|
19
- t.run
20
- end
21
- else
22
- stop = true
23
- end
24
- end
25
-
26
- if stop
27
- Thread.stop
28
- end
29
- end
30
- end
31
-
32
- def threads(n, opts = {})
33
- if opts[:synchronize]
34
- s1 = Synchronizer.new n
35
- s2 = Synchronizer.new n
36
- end
37
-
38
- threads = (0...n).map do |i|
39
- Thread.new do
40
- if opts[:synchronize]
41
- s1.sync
42
- end
43
-
44
- yield i
45
-
46
- if opts[:synchronize]
47
- s2.sync
48
- end
49
- end
50
- end
51
-
52
- threads.each do |t|
53
- t.join
54
- end
55
- end
56
-
57
- [
58
- {:protobuffs_backend => :Beefcake}
59
- ].each do |opts|
60
- describe opts.inspect do
61
- before do
62
- @bucket = random_bucket 'threading'
63
- end
64
-
65
- it 'gets in parallel' do
66
- data = "the gun is good"
67
- ro = @bucket.new('test')
68
- ro.content_type = "application/json"
69
- ro.data = [data]
70
- ro.store
71
-
72
- threads 10, :synchronize => true do
73
- x = @bucket['test']
74
- expect(x.content_type).to eq("application/json")
75
- expect(x.data).to eq([data])
76
- end
77
- end
78
-
79
- it 'puts in parallel' do
80
- data = "the tabernacle is indestructible and everlasting"
81
-
82
- n = 10
83
- threads n, :synchronize => true do |i|
84
- x = @bucket.new("test-#{i}")
85
- x.content_type = "application/json"
86
- x.data = ["#{data}-#{i}"]
87
- x.store
88
- end
89
-
90
- (0...n).each do |i|
91
- read = @bucket["test-#{i}"]
92
- expect(read.content_type).to eq("application/json")
93
- expect(read.data).to eq(["#{data}-#{i}"])
94
- end
95
- end
96
-
97
- # This is a 1.0+ spec because putting with the same client ID
98
- # will not create siblings on 0.14 in the same way. This will
99
- # also likely fail for nodes with vnode_vclocks = false.
100
- it 'puts conflicts in parallel' do
101
- @bucket.allow_mult = true
102
- expect(@bucket.allow_mult).to eq(true)
103
-
104
- init = @bucket.new('test')
105
- init.content_type = "application/json"
106
- init.data = ''
107
- init.store
108
-
109
- # Create conflicting writes
110
- n = 10
111
- s = Synchronizer.new n
112
- threads n, :synchronize => true do |i|
113
- x = @bucket["test"]
114
- s.sync
115
- x.data = [i]
116
- x.store
117
- end
118
-
119
- read = @bucket["test"]
120
- expect(read.conflict?).to eq(true)
121
- expect(read.siblings.map do |sibling|
122
- sibling.data.first
123
- end.to_set).to eq((0...n).to_set)
124
- end
125
-
126
- it 'lists-keys and gets in parallel', :slow => true do
127
- count = 100
128
- threads = 2
129
-
130
- # Create items
131
- count.times do |i|
132
- o = @bucket.new("#{i}")
133
- o.content_type = 'application/json'
134
- o.data = [i]
135
- o.store
136
- end
137
-
138
- threads(threads) do
139
- set = Set.new
140
- @bucket.keys do |stream|
141
- stream.each do |key|
142
- set.merge @bucket[key].data
143
- end
144
- end
145
- expect(set).to eq((0...count).to_set)
146
- end
147
- end
148
- end
149
- end
150
- end
1
+ require 'spec_helper'
2
+
3
+ describe "Multithreaded client", :test_client => true do
4
+ if ENV['TRAVIS'] == 'true' && RUBY_PLATFORM == 'java'
5
+ skip 'multithreaded client tests time out on Travis CI'
6
+ break
7
+ end
8
+ class Synchronizer
9
+ def initialize(n)
10
+ @mutex = Mutex.new
11
+ @n = n
12
+ @waiting = Set.new
13
+ end
14
+
15
+ def sync
16
+ stop = false
17
+ @mutex.synchronize do
18
+ @waiting << Thread.current
19
+
20
+ if @waiting.size >= @n
21
+ # All threads are waiting.
22
+ @waiting.each do |t|
23
+ t.run
24
+ end
25
+ else
26
+ stop = true
27
+ end
28
+ end
29
+
30
+ if stop
31
+ Thread.stop
32
+ end
33
+ end
34
+ end
35
+
36
+ def threads(n, opts = {})
37
+ if opts[:synchronize]
38
+ s1 = Synchronizer.new n
39
+ s2 = Synchronizer.new n
40
+ end
41
+
42
+ threads = (0...n).map do |i|
43
+ Thread.new do
44
+ if opts[:synchronize]
45
+ s1.sync
46
+ end
47
+
48
+ yield i
49
+
50
+ if opts[:synchronize]
51
+ s2.sync
52
+ end
53
+ end
54
+ end
55
+
56
+ threads.each do |t|
57
+ t.join
58
+ end
59
+ end
60
+
61
+ [
62
+ {:protobuffs_backend => :Beefcake}
63
+ ].each do |opts|
64
+ describe opts.inspect do
65
+ before do
66
+ @bucket = random_bucket 'threading'
67
+ end
68
+
69
+ it 'gets in parallel' do
70
+ data = "the gun is good"
71
+ ro = @bucket.new('test')
72
+ ro.content_type = "application/json"
73
+ ro.data = [data]
74
+ ro.store
75
+
76
+ threads 10, :synchronize => true do
77
+ x = @bucket['test']
78
+ expect(x.content_type).to eq("application/json")
79
+ expect(x.data).to eq([data])
80
+ end
81
+ end
82
+
83
+ it 'puts in parallel' do
84
+ data = "the tabernacle is indestructible and everlasting"
85
+
86
+ n = 10
87
+ threads n, :synchronize => true do |i|
88
+ x = @bucket.new("test-#{i}")
89
+ x.content_type = "application/json"
90
+ x.data = ["#{data}-#{i}"]
91
+ x.store
92
+ end
93
+
94
+ (0...n).each do |i|
95
+ read = @bucket["test-#{i}"]
96
+ expect(read.content_type).to eq("application/json")
97
+ expect(read.data).to eq(["#{data}-#{i}"])
98
+ end
99
+ end
100
+
101
+ # This is a 1.0+ spec because putting with the same client ID
102
+ # will not create siblings on 0.14 in the same way. This will
103
+ # also likely fail for nodes with vnode_vclocks = false.
104
+ it 'puts conflicts in parallel' do
105
+ @bucket.allow_mult = true
106
+ expect(@bucket.allow_mult).to eq(true)
107
+
108
+ init = @bucket.new('test')
109
+ init.content_type = "application/json"
110
+ init.data = ''
111
+ init.store
112
+
113
+ # Create conflicting writes
114
+ n = 10
115
+ s = Synchronizer.new n
116
+ threads n, :synchronize => true do |i|
117
+ x = @bucket["test"]
118
+ s.sync
119
+ x.data = [i]
120
+ x.store
121
+ end
122
+
123
+ read = @bucket["test"]
124
+ expect(read.conflict?).to eq(true)
125
+ expect(read.siblings.map do |sibling|
126
+ sibling.data.first
127
+ end.to_set).to eq((0...n).to_set)
128
+ end
129
+
130
+ it 'lists-keys and gets in parallel', :slow => true do
131
+ count = 100
132
+ threads = 2
133
+
134
+ # Create items
135
+ count.times do |i|
136
+ o = @bucket.new("#{i}")
137
+ o.content_type = 'application/json'
138
+ o.data = [i]
139
+ o.store
140
+ end
141
+
142
+ threads(threads) do
143
+ set = Set.new
144
+ @bucket.keys do |stream|
145
+ stream.each do |key|
146
+ set.merge @bucket[key].data
147
+ end
148
+ end
149
+ expect(set).to eq((0...count).to_set)
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -1,61 +1,61 @@
1
- require 'spec_helper'
2
- require 'riak'
3
-
4
- describe "Yokozuna", test_client: true, integration: true do
5
- before(:all) do
6
- @client = test_client
7
-
8
- @index = 'yz_spec-' + random_key
9
- @schema = 'yz_spec-' + random_key
10
- end
11
-
12
- context "without any indexes" do
13
- it "allows index creation" do
14
- expect(@client.create_search_index(@index, "_yz_default", 3)).to eq(true)
15
- end
16
- end
17
-
18
- context "with an index" do
19
- before :all do
20
- expect(@client.create_search_index(@index)).to eq(true)
21
- wait_until{ !@client.get_search_index(@index).nil? }
22
- end
23
-
24
- it "allows index inspection" do
25
- expect(@client.get_search_index(@index).name).to eq(@index)
26
- expect{ @client.get_search_index("herp_derp") }.to raise_error(Riak::ProtobuffsFailedRequest)
27
- end
28
-
29
- it "has an index list" do
30
- expect(@client.list_search_indexes.size).to be >= 1
31
- end
32
-
33
- it "associates a bucket with an index" do
34
- @bucket = Riak::Bucket.new(@client, @index)
35
- @bucket.props = {'search_index' => @index}
36
- @bucket = @client.bucket(@index)
37
- expect(@bucket.props).to include('search_index' => @index)
38
- end
39
-
40
- context "associated with a bucket" do
41
- before :all do
42
- @bucket = Riak::Bucket.new(@client, @index)
43
- @bucket.props = {'search_index' => @index}
44
- @bucket = @client.bucket(@index)
45
- expect(@bucket.props).to include('search_index' => @index)
46
- end
47
-
48
- it "indexes on object writes" do
49
- object = @bucket.get_or_new("cat")
50
- object.raw_data = {"cat_s"=>"Lela"}.to_json
51
- object.content_type = 'application/json'
52
- object.store
53
- sleep 1.1 # pause for index commit to trigger
54
-
55
- resp = @client.search(@index, "cat_s:Lela")
56
- expect(resp).to include('docs')
57
- expect(resp['docs'].size).to eq(1)
58
- end
59
- end
60
- end
61
- end
1
+ require 'spec_helper'
2
+ require 'riak'
3
+
4
+ describe "Yokozuna", test_client: true, integration: true do
5
+ before(:all) do
6
+ @client = test_client
7
+
8
+ @index = 'yz_spec-' + random_key
9
+ @schema = 'yz_spec-' + random_key
10
+ end
11
+
12
+ context "without any indexes" do
13
+ it "allows index creation" do
14
+ expect(@client.create_search_index(@index, "_yz_default", 3)).to eq(true)
15
+ end
16
+ end
17
+
18
+ context "with an index" do
19
+ before :all do
20
+ expect(@client.create_search_index(@index)).to eq(true)
21
+ wait_until{ !@client.get_search_index(@index).nil? }
22
+ end
23
+
24
+ it "allows index inspection" do
25
+ expect(@client.get_search_index(@index).name).to eq(@index)
26
+ expect{ @client.get_search_index("herp_derp") }.to raise_error(Riak::ProtobuffsFailedRequest)
27
+ end
28
+
29
+ it "has an index list" do
30
+ expect(@client.list_search_indexes.size).to be >= 1
31
+ end
32
+
33
+ it "associates a bucket with an index" do
34
+ @bucket = Riak::Bucket.new(@client, @index)
35
+ @bucket.props = {'search_index' => @index}
36
+ @bucket = @client.bucket(@index)
37
+ expect(@bucket.props).to include('search_index' => @index)
38
+ end
39
+
40
+ context "associated with a bucket" do
41
+ before :all do
42
+ @bucket = Riak::Bucket.new(@client, @index)
43
+ @bucket.props = {'search_index' => @index}
44
+ @bucket = @client.bucket(@index)
45
+ expect(@bucket.props).to include('search_index' => @index)
46
+ end
47
+
48
+ it "indexes on object writes" do
49
+ object = @bucket.get_or_new("cat")
50
+ object.raw_data = {"cat_s"=>"Lela"}.to_json
51
+ object.content_type = 'application/json'
52
+ object.store
53
+ sleep 2.1 # pause for index commit to trigger
54
+
55
+ resp = @client.search(@index, "cat_s:Lela")
56
+ expect(resp).to include('docs')
57
+ expect(resp['docs'].size).to eq(1)
58
+ end
59
+ end
60
+ end
61
+ end