tarantool 0.2.5 → 0.3.0.7

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.
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
data/lib/tarantool.rb CHANGED
@@ -1,36 +1,86 @@
1
- # -*- coding: utf-8 -*-
2
- require 'iproto'
3
-
4
- class Tarantool
5
- VERSION = '0.2.5'
6
-
7
- require 'tarantool/space'
8
- require 'tarantool/requests'
9
- require 'tarantool/response'
10
- require 'tarantool/exceptions'
11
- require 'tarantool/serializers'
12
-
13
- attr_reader :config
14
- def initialize(config = {})
15
- @config = config
16
- end
1
+ require 'eventmachine'
2
+ require "iproto"
3
+ require "tarantool/version"
4
+ require "tarantool/request"
5
+ require "tarantool/response"
6
+ require "tarantool/space_array.rb"
7
+ require "tarantool/space_hash.rb"
8
+ require "tarantool/query.rb"
9
+ require "tarantool/serializers.rb"
17
10
 
18
- def configure(config)
19
- @config.merge! config
20
- end
11
+ module Tarantool
12
+ #autoload :Record, 'tarantool/record'
13
+ #autoload :LightRecord, 'tarantool/light_record'
21
14
 
22
- def connection(c = config)
23
- @connection ||= begin
24
- raise "Tarantool.configure before connect" unless c
25
- IProto.get_connection c[:host], c[:port], c[:type] || :block
15
+ class << self
16
+ def new(conf)
17
+ case conf[:type] || :block
18
+ when :em, :em_fiber
19
+ require 'tarantool/fiber_db'
20
+ FiberDB.new(conf[:host], conf[:port])
21
+ when :em_cb, :em_callback
22
+ require 'tarantool/callback_db'
23
+ CallbackDB.new(conf[:host], conf[:port])
24
+ when :block
25
+ require 'tarantool/block_db'
26
+ BlockDB.new(conf[:host], conf[:port])
27
+ end
26
28
  end
27
29
  end
28
30
 
29
- def space(no, conn = connection)
30
- Space.new conn, no
31
- end
31
+ class DB
32
+ attr_reader :closed, :connection
33
+ alias closed? closed
34
+ def initialize(host, port)
35
+ @host = host
36
+ @port = port
37
+ @closed = false
38
+ establish_connection
39
+ end
40
+
41
+ # returns regular space, where fields are named by position
42
+ #
43
+ # tarantool.space_block(0, [:int, :str, :int, :str], keys: [[0], [1,2]])
44
+ def space_array(space_no, field_types = [], opts = {})
45
+ indexes = opts[:keys] || opts[:indexes]
46
+ self.class::SpaceArray.new(self, space_no, field_types, indexes)
47
+ end
48
+ # alias space_array to space for backward compatibility
49
+ alias space space_array
50
+
51
+ def space_hash(space_no, fields, opts = {})
52
+ indexes = opts[:keys] || opts[:indexes]
53
+ self.class::SpaceHash.new(self, space_no, fields, indexes)
54
+ end
55
+
56
+ def query
57
+ @query ||= self.class::Query.new(self)
58
+ end
59
+
60
+ def method_missing(name, *args)
61
+ if query.respond_to?(name)
62
+ query.send(name, *args)
63
+ else
64
+ super
65
+ end
66
+ end
67
+
68
+ def close
69
+ @closed = true
70
+ close_connection
71
+ end
72
+
73
+ def establish_connection
74
+ raise NoMethodError, "#establish_connection should be redefined"
75
+ end
76
+
77
+ def close_connection
78
+ raise NoMethodError, "#close_connection should be redefined"
79
+ end
80
+
81
+ def _send_request(request_type, body, cb)
82
+ raise NoMethodError, "#_send_request should be redefined"
83
+ end
32
84
 
33
- def self.hexdump(string)
34
- string.unpack('C*').map{ |c| "%02x" % c }.join(' ')
35
85
  end
36
- end
86
+ end
data/test/box.pid ADDED
@@ -0,0 +1 @@
1
+ 2887
data/test/helper.rb ADDED
@@ -0,0 +1,164 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'rr'
4
+
5
+ require 'tarantool'
6
+
7
+ class ArrayPackSerializer
8
+ def encode(arr)
9
+ arr.pack("N*")
10
+ end
11
+
12
+ def decode(str)
13
+ str.unpack("N*")
14
+ end
15
+ end
16
+
17
+ TCONFIG = { host: '127.0.0.1', port: 33013, admin: 33015 }
18
+
19
+ SPACE0 = {
20
+ types: [:str, :str, :str, :int],
21
+ keys: [0, [1,2], 3]
22
+ }
23
+ SPACE1 = {
24
+ types: [:int, :str, :int, 2],
25
+ keys: 0
26
+ }
27
+ SPACE2 = {
28
+ types: [:str, :str, :int],
29
+ keys: [[0,1], 2]
30
+ }
31
+ SPACE3 = {
32
+ types: [:int, ArrayPackSerializer.new],
33
+ keys: [0, 1]
34
+ }
35
+
36
+ HSPACE0 = {
37
+ fields: {name: :str, surname: :str, email: :str, score: :int},
38
+ keys: [:name, %w{surname email}, 'score']
39
+ }
40
+ HSPACE1 = {
41
+ fields: {id: :int, _tail: [:str, :int]},
42
+ keys: :id
43
+ }
44
+ HSPACE2 = {
45
+ fields: {first: :str, second: :str, third: :int},
46
+ keys: [%w{first second}, :third]
47
+ }
48
+ HSPACE3 = {
49
+ fields: {id: :int, scores: ArrayPackSerializer.new},
50
+ keys: [:id, :scores]
51
+ }
52
+
53
+ module Helper
54
+ def tarantool_pipe
55
+ $tarantool_pipe ||= begin
56
+ cnf = TCONFIG
57
+ tarant = %W{tarantool -p #{cnf[:port]} -m #{cnf[:admin]}}
58
+ tarant = [{}, *tarant, :err => [:child, :out]]
59
+ IO.popen(tarant, 'w+').tap{|p| p.sync = true}
60
+ end
61
+ end
62
+
63
+ def exec_tarantool(cmd, lines_to_read)
64
+ cmd = cmd.gsub(/^\s+/, '')
65
+ tarantool_pipe.puts(cmd)
66
+ tarantool_pipe.flush
67
+ lines_to_read.times do
68
+ tarantool_pipe.gets
69
+ end
70
+ end
71
+
72
+ def truncate
73
+ exec_tarantool "
74
+ lua truncate(0)
75
+ lua truncate(1)
76
+ lua truncate(2)
77
+ lua truncate(3)
78
+ ", 12
79
+ end
80
+
81
+ def seed
82
+ exec_tarantool "
83
+ insert into t0 values ('vasya', 'petrov', 'eb@lo.com', 5)
84
+ insert into t0 values ('ilya', 'zimov', 'il@zi.bot', 13)
85
+ insert into t0 values ('fedor', 'kuklin', 'ku@kl.in', 13)
86
+ insert into t1 values (1, 'common', 4)
87
+ insert into t1 values (2, 'medium', 6, 'common', 7)
88
+ insert into t2 values ('hi zo', 'ho zo', 1)
89
+ insert into t2 values ('hi zo', 'pidas', 1, 3, 5)
90
+ insert into t2 values ('coma', 'peredoma', 2)
91
+ ", 16
92
+ end
93
+
94
+ def clear_db
95
+ truncate
96
+ seed
97
+ end
98
+
99
+ def emrun(semaphore = 1)
100
+ @semaphore = semaphore
101
+ EM.run {
102
+ @timeout_timer = EM.add_timer(1) {
103
+ EM.stop
104
+ assert false, "timeout encounted"
105
+ }
106
+ yield
107
+ }
108
+ end
109
+
110
+ def emstop
111
+ @semaphore -= 1
112
+ if @semaphore == 0
113
+ EM.cancel_timer @timeout_timer
114
+ EM.next_tick{ EM.stop }
115
+ end
116
+ end
117
+
118
+ def fibrun
119
+ res = nil
120
+ EM.run {
121
+ f = Fiber.new{
122
+ begin
123
+ res = yield
124
+ ensure
125
+ EM.next_tick{ EM.stop }
126
+ end
127
+ }
128
+ EM.next_tick{ f.resume }
129
+ }
130
+ res
131
+ end
132
+
133
+ def blockrun
134
+ yield
135
+ end
136
+
137
+ def mock(u, meth, &block)
138
+ u.define_singleton_method(meth, &block)
139
+ end
140
+ end
141
+
142
+ class MiniTest::Unit::TestCase
143
+ include ::Helper
144
+ include RR::Adapters::MiniTest
145
+ end
146
+
147
+ class << MiniTest::Spec
148
+ def shared_examples
149
+ @shared_examples ||= {}
150
+ end
151
+ end
152
+
153
+ module MiniTest::Spec::SharedExamples
154
+ def shared_examples_for(desc, &block)
155
+ MiniTest::Spec.shared_examples[desc] = block
156
+ end
157
+
158
+ def it_behaves_like(desc)
159
+ class_eval &MiniTest::Spec.shared_examples.fetch(desc)
160
+ end
161
+ end
162
+
163
+ Object.class_eval { include(MiniTest::Spec::SharedExamples) }
164
+
data/test/run_all.rb ADDED
@@ -0,0 +1,3 @@
1
+ Dir.glob(File.expand_path('../test_*.rb', __FILE__)) do |f|
2
+ require f
3
+ end
@@ -0,0 +1,73 @@
1
+ require File.expand_path('../helper.rb', __FILE__)
2
+
3
+ shared_examples_for :blocking_query do
4
+ before { clear_db }
5
+
6
+ let(:vasya){ ['vasya', 'petrov', 'eb@lo.com', 5] }
7
+ let(:ilya) { ['ilya', 'zimov', 'il@zi.bot', 13] }
8
+ let(:fedor){ ['fedor', 'kuklin', 'ku@kl.in', 13] }
9
+ let(:vasya_h) { {name: 'vasya', surname: 'petrov', email: 'eb@lo.com', score: 5} }
10
+ let(:ilya_h) { {name: 'ilya', surname: 'zimov', email: 'il@zi.bot', score: 13} }
11
+ let(:fedor_h) { {name: 'fedor', surname: 'kuklin', email: 'ku@kl.in', score: 13} }
12
+
13
+ it "should be able to select" do
14
+ results = blockrun {[
15
+ tarantool.select(0, 0, 'vasya', 0, -1),
16
+ tarantool.all(0, 1, ['zimov', 'il@zi.bot'], returns: [:str, :str, :str, :int]),
17
+ tarantool.first(0, 2, 13, returns: {name: :str, surname: :str, email: :str, score: :int}),
18
+ tarantool.all(1, 0, 2, returns: [:int, :str, :int, 2]),
19
+ tarantool.all(1, 0, 2, returns: {id: :int, _tail: [:str, :int]})
20
+ ]}
21
+ vasya_s = vasya.dup
22
+ vasya_s[3] = "\x05\x00\x00\x00"
23
+ results[0].must_equal [vasya_s]
24
+ results[1].must_equal [ilya]
25
+ [ilya_h, fedor_h].must_include results[2]
26
+ results[3].must_equal [[2, 'medium', 6, 'common', 7]]
27
+ results[4].must_equal [{id: 2, _tail: [['medium', 6], ['common', 7]]}]
28
+ end
29
+
30
+ it "should insert" do
31
+ results = blockrun {[
32
+ tarantool.insert(0, ['asdf','qwer','zxcv',10], return_tuple: true),
33
+ tarantool.insert(0, ['wert','sdfg','xcvb',1200], types: [:str, :str, :str, :str], return_tuple: true),
34
+ tarantool.insert(1, [3, 'a', 5, 'b', 6], types: [:int, :str, :int, 2], return_tuple: true),
35
+ tarantool.replace(1, [2, 'e', 1]),
36
+ tarantool.first(1, 0, 2, returns: [:int, :str, :int, 2]),
37
+ ]}
38
+ results[0].must_equal ['asdf','qwer','zxcv',10]
39
+ results[1].must_equal ['wert','sdfg','xcvb',"1200"]
40
+ results[2].must_equal [3, 'a', 5, 'b', 6]
41
+ results[3].must_equal 1
42
+ results[4].must_equal [2, 'e', 1]
43
+ end
44
+
45
+ it "should update" do
46
+ results = blockrun {[
47
+ tarantool.update(1, 2, [["+2", 4]], returns: [:int, :str, :int, 2], return_tuple: true)
48
+ ]}
49
+ results[0].must_equal [2, 'medium', 10, 'common', 7]
50
+ end
51
+
52
+ it "should delete" do
53
+ results = blockrun {[
54
+ tarantool.delete(1, 1, returns: [:int, :str, :int, 2], return_tuple: true),
55
+ tarantool.delete(1, 2, returns: {id: :int, _tail: [:str, :int]}, return_tuple: true)
56
+ ]}
57
+ results[0].must_equal [1, 'common', 4]
58
+ results[1].must_equal({id: 2, _tail: [['medium', 6], ['common', 7]]})
59
+ end
60
+
61
+ it "should call" do
62
+ results = blockrun {[
63
+ tarantool.call('func3', ['hello', '2']),
64
+ tarantool.call('func3', ['hello', 2]),
65
+ tarantool.call('func3', [234, 432], returns: [:str, :int]),
66
+ tarantool.call('func3', [234, 432], returns: {type: :str, val: :int}),
67
+ ]}
68
+ results[0].must_equal [['string', 'hello'], ['string', '2']]
69
+ results[1].must_equal [['string', 'hello'], ['string', "\x02\x00\x00\x00"]]
70
+ results[2].must_equal [['string', 234], ['string', 432]]
71
+ results[3].must_equal [{type:'string', val:234}, {type:'string', val:432}]
72
+ end
73
+ end