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.
- data/Gemfile +14 -12
- data/LICENSE +4 -4
- data/README.md +15 -9
- data/Rakefile +5 -129
- data/lib/tarantool/base_record.rb +288 -0
- data/lib/tarantool/block_db.rb +135 -0
- data/lib/tarantool/callback_db.rb +47 -0
- data/lib/tarantool/core-ext.rb +12 -0
- data/lib/tarantool/em_db.rb +37 -0
- data/lib/tarantool/exceptions.rb +52 -7
- data/lib/tarantool/fiber_db.rb +152 -0
- data/lib/tarantool/light_record.rb +68 -0
- data/lib/tarantool/query.rb +127 -0
- data/lib/tarantool/record/select.rb +59 -0
- data/lib/tarantool/record.rb +93 -282
- data/lib/tarantool/request.rb +351 -52
- data/lib/tarantool/response.rb +108 -45
- data/lib/tarantool/serializers/bson.rb +2 -2
- data/lib/tarantool/serializers.rb +32 -4
- data/lib/tarantool/space_array.rb +153 -0
- data/lib/tarantool/space_hash.rb +262 -0
- data/lib/tarantool/util.rb +182 -0
- data/lib/tarantool/version.rb +3 -0
- data/lib/tarantool.rb +79 -29
- data/test/box.pid +1 -0
- data/test/helper.rb +164 -0
- data/test/run_all.rb +3 -0
- data/test/shared_query.rb +73 -0
- data/test/shared_record.rb +474 -0
- data/test/shared_space_array.rb +284 -0
- data/test/shared_space_hash.rb +239 -0
- data/test/tarant/init.lua +22 -0
- data/test/tarantool.cfg +62 -0
- data/test/tarantool.log +6 -0
- data/{spec/tarantool.cfg → test/tarantool_repl.cfg} +11 -5
- data/test/test_light_record.rb +48 -0
- data/test/test_query_block.rb +6 -0
- data/test/test_query_fiber.rb +7 -0
- data/test/test_record.rb +88 -0
- data/{spec/tarantool/composite_primary_key_spec.rb → test/test_record_composite_pk.rb} +5 -7
- data/test/test_space_array_block.rb +6 -0
- data/test/test_space_array_callback.rb +255 -0
- data/test/test_space_array_callback_nodef.rb +190 -0
- data/test/test_space_array_fiber.rb +7 -0
- data/test/test_space_hash_block.rb +6 -0
- data/test/test_space_hash_fiber.rb +7 -0
- metadata +78 -55
- data/Gemfile.lock +0 -54
- data/examples/em_simple.rb +0 -16
- data/examples/record.rb +0 -68
- data/examples/simple.rb +0 -13
- data/lib/tarantool/requests/call.rb +0 -20
- data/lib/tarantool/requests/delete.rb +0 -18
- data/lib/tarantool/requests/insert.rb +0 -19
- data/lib/tarantool/requests/ping.rb +0 -16
- data/lib/tarantool/requests/select.rb +0 -22
- data/lib/tarantool/requests/update.rb +0 -35
- data/lib/tarantool/requests.rb +0 -19
- data/lib/tarantool/serializers/integer.rb +0 -14
- data/lib/tarantool/serializers/string.rb +0 -14
- data/lib/tarantool/space.rb +0 -39
- data/spec/helpers/let.rb +0 -11
- data/spec/helpers/truncate.rb +0 -12
- data/spec/spec_helper.rb +0 -21
- data/spec/tarantool/em_spec.rb +0 -22
- data/spec/tarantool/record_spec.rb +0 -316
- data/spec/tarantool/request_spec.rb +0 -103
- data/tarantool.gemspec +0 -69
data/lib/tarantool.rb
CHANGED
@@ -1,36 +1,86 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
11
|
+
module Tarantool
|
12
|
+
#autoload :Record, 'tarantool/record'
|
13
|
+
#autoload :LightRecord, 'tarantool/light_record'
|
21
14
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
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,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
|