tarantool 0.2.5 → 0.3.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/Gemfile +14 -12
  2. data/LICENSE +4 -4
  3. data/README.md +15 -9
  4. data/Rakefile +5 -129
  5. data/lib/tarantool/base_record.rb +288 -0
  6. data/lib/tarantool/block_db.rb +135 -0
  7. data/lib/tarantool/callback_db.rb +47 -0
  8. data/lib/tarantool/core-ext.rb +12 -0
  9. data/lib/tarantool/em_db.rb +37 -0
  10. data/lib/tarantool/exceptions.rb +52 -7
  11. data/lib/tarantool/fiber_db.rb +152 -0
  12. data/lib/tarantool/light_record.rb +68 -0
  13. data/lib/tarantool/query.rb +127 -0
  14. data/lib/tarantool/record/select.rb +59 -0
  15. data/lib/tarantool/record.rb +93 -282
  16. data/lib/tarantool/request.rb +351 -52
  17. data/lib/tarantool/response.rb +108 -45
  18. data/lib/tarantool/serializers/bson.rb +2 -2
  19. data/lib/tarantool/serializers.rb +32 -4
  20. data/lib/tarantool/space_array.rb +153 -0
  21. data/lib/tarantool/space_hash.rb +262 -0
  22. data/lib/tarantool/util.rb +182 -0
  23. data/lib/tarantool/version.rb +3 -0
  24. data/lib/tarantool.rb +79 -29
  25. data/test/box.pid +1 -0
  26. data/test/helper.rb +164 -0
  27. data/test/run_all.rb +3 -0
  28. data/test/shared_query.rb +73 -0
  29. data/test/shared_record.rb +474 -0
  30. data/test/shared_space_array.rb +284 -0
  31. data/test/shared_space_hash.rb +239 -0
  32. data/test/tarant/init.lua +22 -0
  33. data/test/tarantool.cfg +62 -0
  34. data/test/tarantool.log +6 -0
  35. data/{spec/tarantool.cfg → test/tarantool_repl.cfg} +11 -5
  36. data/test/test_light_record.rb +48 -0
  37. data/test/test_query_block.rb +6 -0
  38. data/test/test_query_fiber.rb +7 -0
  39. data/test/test_record.rb +88 -0
  40. data/{spec/tarantool/composite_primary_key_spec.rb → test/test_record_composite_pk.rb} +5 -7
  41. data/test/test_space_array_block.rb +6 -0
  42. data/test/test_space_array_callback.rb +255 -0
  43. data/test/test_space_array_callback_nodef.rb +190 -0
  44. data/test/test_space_array_fiber.rb +7 -0
  45. data/test/test_space_hash_block.rb +6 -0
  46. data/test/test_space_hash_fiber.rb +7 -0
  47. metadata +78 -55
  48. data/Gemfile.lock +0 -54
  49. data/examples/em_simple.rb +0 -16
  50. data/examples/record.rb +0 -68
  51. data/examples/simple.rb +0 -13
  52. data/lib/tarantool/requests/call.rb +0 -20
  53. data/lib/tarantool/requests/delete.rb +0 -18
  54. data/lib/tarantool/requests/insert.rb +0 -19
  55. data/lib/tarantool/requests/ping.rb +0 -16
  56. data/lib/tarantool/requests/select.rb +0 -22
  57. data/lib/tarantool/requests/update.rb +0 -35
  58. data/lib/tarantool/requests.rb +0 -19
  59. data/lib/tarantool/serializers/integer.rb +0 -14
  60. data/lib/tarantool/serializers/string.rb +0 -14
  61. data/lib/tarantool/space.rb +0 -39
  62. data/spec/helpers/let.rb +0 -11
  63. data/spec/helpers/truncate.rb +0 -12
  64. data/spec/spec_helper.rb +0 -21
  65. data/spec/tarantool/em_spec.rb +0 -22
  66. data/spec/tarantool/record_spec.rb +0 -316
  67. data/spec/tarantool/request_spec.rb +0 -103
  68. data/tarantool.gemspec +0 -69
@@ -1,316 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'spec_helper'
3
- require 'tarantool/record'
4
- require 'yajl'
5
- require 'tarantool/serializers/bson'
6
- describe Tarantool::Record do
7
- include Helpers::Truncate
8
-
9
- def space
10
- @space ||= DB.space 0
11
- end
12
-
13
- let(:user_class) do
14
- Class.new(Tarantool::Record) do
15
- set_tarantool DB
16
- set_space_no 0
17
-
18
- def self.name # For naming
19
- "User"
20
- end
21
-
22
- field :login, :string
23
- field :name, :string
24
- field :email, :string
25
- field :apples_count, :integer, default: 0
26
- index :name, :email
27
- end
28
- end
29
-
30
- let(:user) { user_class.new }
31
- it "should set and get attributes" do
32
- user.name = 'Andrew'
33
- user.name.must_equal 'Andrew'
34
- end
35
-
36
- describe "inheritance" do
37
- let(:author_class) do
38
- Class.new(user_class) do
39
- field :best_book, Integer
40
- end
41
- end
42
- let(:artist_class) do
43
- Class.new(user_class) do
44
- field :imdb_id, Integer
45
- end
46
- end
47
-
48
- describe "Artist from User" do
49
- it "should has only itself field" do
50
- artist_class.fields.keys.must_equal [:login, :name, :email, :apples_count, :imdb_id]
51
- end
52
- end
53
-
54
- it "should has same space no as parent" do
55
- user_class.space_no = 1
56
- artist_class.space_no.must_equal 1
57
- end
58
-
59
- it "should has different space no to parent if setted" do
60
- artist_class.space_no = 1
61
- user_class.space_no.must_equal 0
62
- artist_class.space_no.must_equal 1
63
- end
64
- end
65
-
66
- describe "detect_index_no" do
67
- let(:select) { user_class.select }
68
- it "should return 0 for :login" do
69
- select.detect_index_no([:login]).must_equal 0
70
- end
71
- it "should return 1 for :name" do
72
- select.detect_index_no([:name]).must_equal 1
73
- end
74
- it "should return 1 for :name, :email" do
75
- select.detect_index_no([:name, :email]).must_equal 1
76
- end
77
- it "should return nil for :email" do
78
- select.detect_index_no([:email]).must_be_nil
79
- end
80
- it "should return nil for :login, :name" do
81
- select.detect_index_no([:login, :name]).must_be_nil
82
- end
83
- end
84
-
85
- describe "save" do
86
- it "should save and select record" do
87
- u = user_class.new login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru'
88
- u.save
89
- u = user_class.find 'prepor'
90
- u.id.must_equal 'prepor'
91
- u.email.must_equal 'ceo@prepor.ru'
92
- u.name.must_equal 'Andrew'
93
- u.apples_count.must_equal 0
94
- end
95
-
96
- it "should update dirty attributes" do
97
- u = user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru'
98
- u.name = 'Petr'
99
- u.save
100
- u = user_class.find 'prepor'
101
- u.email.must_equal 'ceo@prepor.ru'
102
- u.name.must_equal 'Petr'
103
- end
104
-
105
- describe "with nils" do
106
- before do
107
- user_class.field :info, :bson
108
- end
109
- it "should work properly with nils values" do
110
- u = user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru', apples_count: nil
111
- u.info.must_be_nil
112
- u.apples_count.must_be_nil
113
- u.reload
114
- u.info.must_be_nil
115
- u.apples_count.must_be_nil
116
- u.info = {'bio' => 'hi!'}
117
- u.apples_count = 1
118
- u.save
119
- u.reload
120
- u.info.must_equal({ 'bio' => 'hi!' })
121
- u.apples_count.must_equal 1
122
- end
123
- end
124
- end
125
-
126
- describe "reload" do
127
- it "should reload current record" do
128
- u = user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru'
129
- u.name = 'Petr'
130
- u.reload.name.must_equal 'Andrew'
131
- end
132
- end
133
-
134
- describe "increment" do
135
- before { @truncate_fields = 2 }
136
- let(:user) { user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru' }
137
- it "should increment apples count by 1" do
138
- user.increment :apples_count
139
- user.reload.apples_count.must_equal 1
140
- end
141
-
142
- it "should increment apples count by 3" do
143
- user.increment :apples_count, 3
144
- user.reload.apples_count.must_equal 3
145
- end
146
- end
147
-
148
- describe "destroy" do
149
- it "should destroy record" do
150
- u = user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru'
151
- u.destroy
152
- u.reload.must_equal false
153
- end
154
- end
155
-
156
- describe "validations" do
157
- describe "with validator on login size" do
158
- before do
159
- user_class.validates_length_of(:login, minimum: 3)
160
- end
161
- it "should invalidate all records with login less then 3 chars" do
162
- u = user_class.new login: 'pr', name: 'Andrew', email: 'ceo@prepor.ru'
163
- u.save.must_equal false
164
- u.valid?.must_equal false
165
- u.errors.size.must_equal 1
166
- u.login = 'prepor'
167
- u.save.must_equal true
168
- u.valid?.must_equal true
169
- u.errors.size.must_equal 0
170
- end
171
- end
172
- end
173
-
174
- describe "callbacks" do
175
- let(:u) { user_class.new login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru '}
176
- it "should run before / after create callbackss in right places" do
177
- user_class.before_create :action_before_create
178
- user_class.after_create :action_after_create
179
- mock(u).action_before_create { u.new_record?.must_equal true }
180
- mock(u).action_after_create { u.new_record?.must_equal false }
181
- u.save
182
- end
183
-
184
- describe "initialize" do
185
- it "should run after_initialize after any initialization" do
186
- user_class.after_initialize :action_after_initialize
187
- any_instance_of(user_class) do |u|
188
- mock(u).action_after_initialize.twice
189
- end
190
- u.save
191
- user_class.find u.login
192
- end
193
-
194
- it "should not run after_initialize after reload" do
195
- user_class.after_initialize :action_after_initialize
196
- any_instance_of(user_class) do |u|
197
- mock(u).action_after_initialize.once
198
- end
199
- u.save
200
- u.reload
201
- end
202
-
203
- it "should properly save record inside after_initialize" do
204
- user_class.after_initialize do |u|
205
- u.save
206
- end
207
- u
208
- user_class.find u.login
209
- end
210
- end
211
- end
212
-
213
- describe "serialization" do
214
- it "should support AM serialization API" do
215
- h = { login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru' }
216
- u = user_class.create h
217
- u.as_json.must_equal({ 'user' => h.merge(apples_count: 0) })
218
- end
219
-
220
- describe "fields serilizers" do
221
- before do
222
- user_class.field :info, :bson
223
- end
224
-
225
- it "should serialise and deserialize info field" do
226
- info = { 'bio' => "hi!", 'age' => 23, 'hobbies' => ['mufa', 'tuka'] }
227
- u = user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru', info: info
228
- u.info['hobbies'].must_equal ['mufa', 'tuka']
229
- u.reload
230
- u.info['hobbies'].must_equal ['mufa', 'tuka']
231
- u = user_class.find u.login
232
- u.info['hobbies'].must_equal ['mufa', 'tuka']
233
- end
234
- end
235
- end
236
-
237
- describe "select" do
238
- describe "by name Andrew" do
239
- let(:select) { user_class.where(name: 'Andrew') }
240
- before do
241
- user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru'
242
- user_class.create login: 'petro', name: 'Petr', email: 'petro@gmail.com'
243
- user_class.create login: 'ruden', name: 'Andrew', email: 'rudenkoco@gmail.com'
244
- end
245
- it "should select all records with name == 'Andrew'" do
246
- select.all.map(&:login).must_equal ['prepor', 'ruden']
247
- end
248
-
249
- it "should select first record with name == 'Andrew'" do
250
- select.first.login.must_equal 'prepor'
251
- end
252
-
253
- it "should select 1 record by name and email" do
254
- user_class.where(name: 'Andrew', email: 'rudenkoco@gmail.com').map(&:login).must_equal ['ruden']
255
- end
256
-
257
- it "should select 2 record by name and email" do
258
- user_class.where(name: ['Andrew', 'Andrew'], email: ['ceo@prepor.ru', 'rudenkoco@gmail.com']).map(&:login).must_equal ['prepor', 'ruden']
259
- end
260
-
261
- it "should select 3 record by names" do
262
- user_class.where(name: ['Andrew', 'Petr']).map(&:login).must_equal ['prepor', 'ruden', 'petro']
263
- end
264
-
265
- describe "with limit 1" do
266
- let(:select) { super().limit(1) }
267
- it "should select first record with name == 'Andrew'" do
268
- select.map(&:login).must_equal ['prepor']
269
- end
270
-
271
- describe "with offset 1" do
272
- let(:select) { super().offset(1) }
273
- it "should select last record with name == 'Andrew'" do
274
- select.map(&:login).must_equal ['ruden']
275
- end
276
- end
277
- end
278
- end
279
-
280
- describe "==" do
281
-
282
- before do
283
- user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru'
284
- user_class.create login: 'petro', name: 'Petr', email: 'petro@gmail.com'
285
- end
286
-
287
- it "should return equality as true" do
288
- u1 = user_class.where(login: "prepor").first
289
- u2 = user_class.where(login: "prepor").first
290
- (u1 == u2).must_equal true
291
- end
292
-
293
- it "should not return equality as true" do
294
- u1 = user_class.where(login: "prepor")
295
- u2 = user_class.where(login: "petro")
296
- (u1 == u2).must_equal false
297
- end
298
- end
299
-
300
-
301
- describe "call" do
302
- let(:res) { user.class.select.call('box.select_range', 0, 0, 2)}
303
- before do
304
- user_class.create login: 'prepor', name: 'Andrew', email: 'ceo@prepor.ru'
305
- user_class.create login: 'petro', name: 'Petr', email: 'petro@gmail.com'
306
- user_class.create login: 'ruden', name: 'Andrew', email: 'rudenkoco@gmail.com'
307
- end
308
-
309
- it "should select 2 records and return UserClass instances" do
310
- res.size.must_equal 2
311
- res.any? { |v| v.is_a? user_class }
312
- end
313
- end
314
- end
315
-
316
- end
@@ -1,103 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'spec_helper'
3
-
4
- describe Tarantool::Request do
5
- def space
6
- @space ||= DB.space 1
7
- end
8
-
9
- describe "pack method" do
10
- describe "for field" do
11
- it "should pack integer as 32 bit integer" do
12
- size, value = Tarantool::Request.pack_field(5).unpack('wL')
13
- value.must_equal 5
14
- end
15
-
16
- it "should pack string as arbitrary binary string" do
17
- size, value = Tarantool::Request.pack_field("привет").unpack('wa*')
18
- value.force_encoding('utf-8').must_equal 'привет'
19
- end
20
-
21
- it "should raise ArgumentError for other types" do
22
- lambda { Tarantool::Request.pack_field(:foo) }.must_raise Tarantool::ArgumentError
23
- end
24
- end
25
-
26
- describe "for tuple" do
27
- it "should pack to fields with fields count" do
28
- field1, field2 = 1, "привет"
29
- expect = [2, 4, field1, field2.bytesize, field2].pack('LwLwa*')
30
- Tarantool::Request.pack_tuple(field1, field2).must_equal expect
31
- end
32
- end
33
- end
34
-
35
- describe "requests" do
36
- include Helpers::Truncate
37
- describe "insert and select" do
38
- it "should insert tuple and return it" do
39
- space.insert 100, 'привет', return_tuple: true
40
- res = space.select 100
41
- int, string = res.tuple
42
- int.to_i.must_equal 100
43
- string.to_s.must_equal 'привет'
44
- end
45
-
46
- describe "with equal ids" do
47
- it "should raise error" do
48
- space.insert 100, 'lala'
49
- lambda { space.insert 100, 'yo' }.must_raise(Tarantool::BadReturnCode)
50
- end
51
- end
52
- end
53
-
54
- describe "select" do
55
- it "should select multiple tuples" do
56
- space.insert 100, 'привет'
57
- space.insert 101, 'hi'
58
- res = space.select 100, 101
59
- res.tuples.map { |v| v.last.to_s }.must_equal ['привет', 'hi']
60
- end
61
- end
62
-
63
- describe "call" do
64
- it "should call lua proc" do
65
- res = space.call 'box.pack', 'i', '100', return_tuple: true
66
- res.tuple[0].to_i.must_equal 100
67
- end
68
-
69
- it "should return batches via select_range" do
70
- space.insert 100, 'привет'
71
- space.insert 101, 'hi'
72
- res = space.call 'box.select_range', '1', '0', '100', return_tuple: true
73
- res.tuples.size.must_equal 2
74
- end
75
- end
76
-
77
- describe "update" do
78
- it "should update tuple" do
79
- space.insert 100, 'привет'
80
- space.update 100, ops: [[1, :set, 'yo!']]
81
- res = space.select 100
82
- int, string = res.tuple
83
- string.to_s.must_equal 'yo!'
84
- end
85
- end
86
-
87
- describe "delete" do
88
- it "should delete record" do
89
- inserted = space.insert 100, 'привет', return_tuple: true
90
- space.delete inserted.tuple[0], return_tuple: true
91
- res = space.select 100
92
- res.tuple.must_be_nil
93
- end
94
- end
95
-
96
- describe "ping" do
97
- it "should ping without exceptions" do
98
- res = space.ping
99
- res.must_be_kind_of Numeric
100
- end
101
- end
102
- end
103
- end
data/tarantool.gemspec DELETED
@@ -1,69 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.specification_version = 2 if s.respond_to? :specification_version=
3
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
- s.rubygems_version = '1.3.5'
5
-
6
- s.name = 'tarantool'
7
- s.version = '0.2.5'
8
- s.date = '2012-06-02'
9
- s.rubyforge_project = 'tarantool'
10
-
11
- s.summary = "Tarantool KV-storage client."
12
- s.description = "Tarantool KV-storage client."
13
-
14
- s.authors = ["Andrew Rudenko"]
15
- s.email = 'ceo@prepor.ru'
16
- s.homepage = 'http://github.com/mailru/tarantool-ruby'
17
-
18
- s.require_paths = %w[lib]
19
-
20
- s.rdoc_options = ["--charset=UTF-8"]
21
- s.extra_rdoc_files = %w[README.md LICENSE]
22
-
23
- s.add_dependency('iproto', [">= 0.2"])
24
- s.add_dependency('activemodel', [">= 3.1", "< 4.0"])
25
-
26
-
27
- # = MANIFEST =
28
- s.files = %w[
29
- Gemfile
30
- Gemfile.lock
31
- LICENSE
32
- README.md
33
- Rakefile
34
- examples/em_simple.rb
35
- examples/record.rb
36
- examples/simple.rb
37
- lib/tarantool.rb
38
- lib/tarantool/exceptions.rb
39
- lib/tarantool/record.rb
40
- lib/tarantool/request.rb
41
- lib/tarantool/requests.rb
42
- lib/tarantool/requests/call.rb
43
- lib/tarantool/requests/delete.rb
44
- lib/tarantool/requests/insert.rb
45
- lib/tarantool/requests/ping.rb
46
- lib/tarantool/requests/select.rb
47
- lib/tarantool/requests/update.rb
48
- lib/tarantool/response.rb
49
- lib/tarantool/serializers.rb
50
- lib/tarantool/serializers/bson.rb
51
- lib/tarantool/serializers/integer.rb
52
- lib/tarantool/serializers/string.rb
53
- lib/tarantool/space.rb
54
- spec/helpers/let.rb
55
- spec/helpers/truncate.rb
56
- spec/spec_helper.rb
57
- spec/tarantool.cfg
58
- spec/tarantool/composite_primary_key_spec.rb
59
- spec/tarantool/em_spec.rb
60
- spec/tarantool/record_spec.rb
61
- spec/tarantool/request_spec.rb
62
- tarantool.gemspec
63
- ]
64
- # = MANIFEST =
65
-
66
- ## Test files will be grabbed from the file list. Make sure the path glob
67
- ## matches what you actually use.
68
- s.test_files = s.files.select { |path| path =~ /^spec\/.*_spec\.rb/ }
69
- end