tarantool 0.1.1 → 0.2
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 +2 -2
- data/Gemfile.lock +3 -4
- data/README.md +25 -27
- data/Rakefile +1 -1
- data/examples/em_simple.rb +10 -13
- data/examples/record.rb +41 -36
- data/examples/simple.rb +13 -0
- data/lib/tarantool.rb +17 -31
- data/lib/tarantool/exceptions.rb +1 -3
- data/lib/tarantool/record.rb +13 -7
- data/lib/tarantool/request.rb +5 -12
- data/lib/tarantool/requests.rb +1 -1
- data/lib/tarantool/requests/call.rb +1 -1
- data/lib/tarantool/requests/delete.rb +1 -1
- data/lib/tarantool/requests/insert.rb +1 -1
- data/lib/tarantool/requests/ping.rb +2 -2
- data/lib/tarantool/requests/select.rb +1 -1
- data/lib/tarantool/requests/update.rb +1 -1
- data/lib/tarantool/response.rb +1 -1
- data/lib/tarantool/serializers.rb +1 -1
- data/lib/tarantool/serializers/bson.rb +1 -1
- data/lib/tarantool/serializers/integer.rb +1 -1
- data/lib/tarantool/serializers/string.rb +1 -1
- data/lib/tarantool/space.rb +1 -1
- data/spec/helpers/truncate.rb +2 -2
- data/spec/spec_helper.rb +5 -12
- data/spec/tarantool/em_spec.rb +24 -0
- data/spec/tarantool/record_spec.rb +7 -2
- data/spec/tarantool/request_spec.rb +21 -21
- data/tarantool.gemspec +6 -8
- metadata +11 -29
- data/examples/synchrony_simple.rb +0 -13
- data/lib/em/protocols/fixed_header_and_body.rb +0 -67
- data/lib/tarantool/connection.rb +0 -54
- data/lib/tarantool/synchrony.rb +0 -13
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tarantool (0.1)
|
4
|
+
tarantool (0.1.1)
|
5
5
|
activemodel (>= 3.1, < 4.0)
|
6
|
-
|
7
|
-
eventmachine (>= 1.0.0.beta.4, < 2.0.0)
|
6
|
+
iproto (>= 0.1)
|
8
7
|
|
9
8
|
GEM
|
10
9
|
remote: http://rubygems.org/
|
@@ -24,6 +23,7 @@ GEM
|
|
24
23
|
eventmachine (>= 1.0.0.beta.1)
|
25
24
|
eventmachine (1.0.0.beta.4)
|
26
25
|
i18n (0.6.0)
|
26
|
+
iproto (0.1)
|
27
27
|
linecache19 (0.5.12)
|
28
28
|
ruby_core_source (>= 0.1.4)
|
29
29
|
multi_json (1.0.3)
|
@@ -48,7 +48,6 @@ DEPENDENCIES
|
|
48
48
|
bson
|
49
49
|
bson_ext
|
50
50
|
em-synchrony
|
51
|
-
eventmachine
|
52
51
|
rr
|
53
52
|
ruby-debug19
|
54
53
|
tarantool!
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# About
|
2
2
|
|
3
|
-
Its
|
3
|
+
Its ruby client for [Tarantool Key-Value Storage](http://github.com/mailru/tarantool).
|
4
4
|
|
5
5
|
# Install
|
6
6
|
|
@@ -8,48 +8,46 @@ Its asynchronyous EventMachine ruby client for [Tarantool Key-Value Storage](htt
|
|
8
8
|
gem install tarantool
|
9
9
|
```
|
10
10
|
|
11
|
+
# Usage
|
12
|
+
|
11
13
|
```ruby
|
12
14
|
require 'tarantool'
|
13
|
-
# or
|
14
|
-
require 'tarantool/synchrony'
|
15
|
-
# or
|
16
|
-
require 'tarantool/record'
|
17
15
|
```
|
18
16
|
|
19
|
-
# Usage
|
20
|
-
|
21
17
|
To be able to send requests to the server, you must
|
22
|
-
|
18
|
+
initialize Tarantool and Tarantool space:
|
23
19
|
|
24
20
|
```ruby
|
25
|
-
Tarantool.
|
21
|
+
DB = Tarantool.new host: 'locahost', port: 33013
|
22
|
+
space = DB.space 0
|
26
23
|
```
|
27
24
|
|
28
|
-
The driver internals can work in two modes:
|
25
|
+
The driver internals can work in two modes: block via TCPSocket and non block via EventMachine and fibers. By default it uses block mode.
|
29
26
|
|
30
|
-
EM deferrables:
|
31
27
|
|
32
28
|
```ruby
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
req.errback do |err|
|
41
|
-
puts "Error while insert: #{err}"
|
42
|
-
end
|
29
|
+
space.insert 'prepor', 'Andrew', 'ceo@prepor.ru'
|
30
|
+
res = space.select 'prepor'
|
31
|
+
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
|
32
|
+
space.delete 'prepor'
|
43
33
|
```
|
44
34
|
|
45
|
-
|
35
|
+
**Notice** `Tarantool` instances (connections actually) are not threadsafe. So, you should create `Tarantool` instance per thread.
|
46
36
|
|
47
|
-
|
48
|
-
require 'tarantool/synchrony'
|
37
|
+
To use EventMachine pass type: em in options:
|
49
38
|
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
```ruby
|
40
|
+
require 'em-synchrony'
|
41
|
+
DB = Tarantool.new host: 'locahost', port: 33013
|
42
|
+
space = DB.space 0
|
43
|
+
EM.synchrony do
|
44
|
+
Fiber.new do
|
45
|
+
space.insert 'prepor', 'Andrew', 'ceo@prepor.ru'
|
46
|
+
res = space.select 'prepor'
|
47
|
+
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
|
48
|
+
space.delete 'prepor'
|
49
|
+
end.resume
|
50
|
+
end
|
53
51
|
```
|
54
52
|
|
55
53
|
The driver itself provides ActiveModel API: Callbacks, Validations, Serialization, Dirty.
|
data/Rakefile
CHANGED
@@ -78,7 +78,7 @@ task :release => :build do
|
|
78
78
|
puts "You must be on the master branch to release!"
|
79
79
|
exit!
|
80
80
|
end
|
81
|
-
sh "git commit --allow-empty -
|
81
|
+
sh "git commit --allow-empty -m 'Release #{version}'"
|
82
82
|
sh "git tag v#{version}"
|
83
83
|
sh "git push origin master"
|
84
84
|
sh "git push origin v#{version}"
|
data/examples/em_simple.rb
CHANGED
@@ -4,18 +4,15 @@ Bundler.setup
|
|
4
4
|
|
5
5
|
require 'tarantool'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
req.errback do |err|
|
18
|
-
puts "Error while insert: #{err}"
|
7
|
+
require 'em-synchrony'
|
8
|
+
DB = Tarantool.new host: 'localhost', port: 33013
|
9
|
+
space = DB.space 0
|
10
|
+
EM.synchrony do
|
11
|
+
Fiber.new do
|
12
|
+
space.insert 'prepor', 'Andrew', 'ceo@prepor.ru'
|
13
|
+
res = space.select 'prepor'
|
14
|
+
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
|
15
|
+
space.delete 'prepor'
|
19
16
|
EM.stop
|
20
|
-
end
|
17
|
+
end.resume
|
21
18
|
end
|
data/examples/record.rb
CHANGED
@@ -4,7 +4,16 @@ Bundler.setup
|
|
4
4
|
|
5
5
|
require 'tarantool/record'
|
6
6
|
require 'tarantool/serializers/bson'
|
7
|
-
|
7
|
+
|
8
|
+
DB = Tarantool.new host: 'localhost', port: 33013
|
9
|
+
|
10
|
+
class MyTarantool < Tarantool::Record
|
11
|
+
set_tarantool DB
|
12
|
+
end
|
13
|
+
|
14
|
+
class User < MyTarantool
|
15
|
+
set_space_no 0
|
16
|
+
|
8
17
|
field :login, :string
|
9
18
|
field :name, :string
|
10
19
|
field :email, :string
|
@@ -19,38 +28,34 @@ class User < Tarantool::Record
|
|
19
28
|
end
|
20
29
|
end
|
21
30
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
user.destroy
|
54
|
-
puts "Ok!"
|
55
|
-
EM.stop
|
56
|
-
end
|
31
|
+
# Now attribute positions are not important.
|
32
|
+
User.create login: 'prepor', email: 'ceo@prepor.ru', name: 'Andrew'
|
33
|
+
User.create login: 'ruden', name: 'Andrew', email: 'rudenkoco@gmail.com'
|
34
|
+
|
35
|
+
# find by primary key login
|
36
|
+
User.find 'prepor'
|
37
|
+
# first 2 users with name Andrew
|
38
|
+
User.where(name: 'Andrew').limit(2).all
|
39
|
+
# second user with name Andrew
|
40
|
+
User.where(name: 'Andrew').offset(1).limit(1).all
|
41
|
+
# user with name Andrew and email ceo@prepor.ru
|
42
|
+
User.where(name: 'Andrew', email: 'ceo@prepor.ru').first
|
43
|
+
# raise exception, becouse we can't select from not first part of index
|
44
|
+
begin
|
45
|
+
User.where(email: 'ceo@prepor.ru')
|
46
|
+
rescue Tarantool::ArgumentError => e
|
47
|
+
end
|
48
|
+
# increment field apples_count by one. Its atomic operation vie native Tarantool interface
|
49
|
+
User.find('prepor').increment :apples_count
|
50
|
+
|
51
|
+
# update only dirty attributes
|
52
|
+
user = User.find('prepor')
|
53
|
+
user.name = "Petr"
|
54
|
+
user.save
|
55
|
+
|
56
|
+
# field serialization to bson
|
57
|
+
user.info = { 'bio' => "hi!", 'age' => 23, 'hobbies' => ['mufa', 'tuka'] }
|
58
|
+
user.save
|
59
|
+
User.find('prepor').info['bio'] # => 'hi!'
|
60
|
+
user.destroy
|
61
|
+
puts "Ok!"
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
|
3
|
+
Bundler.setup
|
4
|
+
|
5
|
+
require 'tarantool'
|
6
|
+
|
7
|
+
DB = Tarantool.new host: 'localhost', port: 33013
|
8
|
+
space = DB.space 0
|
9
|
+
|
10
|
+
space.insert 'prepor', 'Andrew', 'ceo@prepor.ru'
|
11
|
+
res = space.select 'prepor'
|
12
|
+
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
|
13
|
+
space.delete 'prepor'
|
data/lib/tarantool.rb
CHANGED
@@ -1,50 +1,36 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
require '
|
3
|
-
require 'em-synchrony'
|
2
|
+
require 'iproto'
|
4
3
|
|
5
|
-
|
6
|
-
VERSION = '0.
|
7
|
-
|
4
|
+
class Tarantool
|
5
|
+
VERSION = '0.2'
|
6
|
+
|
8
7
|
require 'tarantool/space'
|
9
|
-
require 'tarantool/connection'
|
10
8
|
require 'tarantool/requests'
|
11
9
|
require 'tarantool/response'
|
12
10
|
require 'tarantool/exceptions'
|
13
11
|
require 'tarantool/serializers'
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def connection
|
20
|
-
@connection ||= begin
|
21
|
-
raise "Tarantool.configure before connect" unless @config
|
22
|
-
EM.connect @config[:host], @config[:port], Tarantool::Connection
|
23
|
-
end
|
13
|
+
attr_reader :config
|
14
|
+
def initialize(config = {})
|
15
|
+
@config = config
|
24
16
|
end
|
25
17
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
@singleton_space = nil
|
18
|
+
def configure(config)
|
19
|
+
@config.merge! config
|
29
20
|
end
|
30
21
|
|
31
|
-
def
|
32
|
-
|
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
|
26
|
+
end
|
33
27
|
end
|
34
28
|
|
35
|
-
def
|
36
|
-
|
37
|
-
@config = config
|
29
|
+
def space(no, conn = connection)
|
30
|
+
Space.new conn, no
|
38
31
|
end
|
39
32
|
|
40
|
-
def hexdump(string)
|
33
|
+
def self.hexdump(string)
|
41
34
|
string.unpack('C*').map{ |c| "%02x" % c }.join(' ')
|
42
35
|
end
|
43
|
-
|
44
|
-
[:select, :update, :insert, :delete, :call, :ping].each do |v|
|
45
|
-
define_method v do |*params|
|
46
|
-
singleton_space.send v, *params
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
36
|
end
|
data/lib/tarantool/exceptions.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
|
1
|
+
class Tarantool
|
2
2
|
class TarantoolError < StandardError; end
|
3
3
|
class UndefinedRequestType < TarantoolError; end
|
4
|
-
class CouldNotConnect < TarantoolError; end
|
5
4
|
class BadReturnCode < TarantoolError; end
|
6
5
|
class StringTooLong < TarantoolError; end
|
7
6
|
class ArgumentError < TarantoolError; end
|
8
|
-
class UnexpectedResponse < TarantoolError; end
|
9
7
|
class UndefinedSpace < TarantoolError; end
|
10
8
|
class ValueError < TarantoolError; end
|
11
9
|
end
|
data/lib/tarantool/record.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_model'
|
2
|
-
require 'tarantool
|
3
|
-
|
2
|
+
require 'tarantool'
|
3
|
+
class Tarantool
|
4
4
|
class Select
|
5
5
|
include Enumerable
|
6
6
|
attr_reader :record
|
@@ -13,7 +13,7 @@ module Tarantool
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def each(&blk)
|
16
|
-
res =
|
16
|
+
res = record.space.select(*@tuples, index_no: @index_no, limit: @limit, offset: @offset).tuples
|
17
17
|
res.each do |tuple|
|
18
18
|
blk.call record.from_server(tuple)
|
19
19
|
end
|
@@ -114,10 +114,16 @@ module Tarantool
|
|
114
114
|
self.indexes = []
|
115
115
|
|
116
116
|
class_attribute :space_no
|
117
|
-
|
118
|
-
original_space_no || 0
|
119
|
-
end
|
117
|
+
class_attribute :tarantool
|
120
118
|
class << self
|
119
|
+
def set_space_no(val)
|
120
|
+
self.space_no = val
|
121
|
+
end
|
122
|
+
|
123
|
+
def set_tarantool(val)
|
124
|
+
self.tarantool = val
|
125
|
+
end
|
126
|
+
|
121
127
|
def field(name, type, params = {})
|
122
128
|
define_attribute_method name
|
123
129
|
self.fields = fields.merge name => { type: type, field_no: fields.size, params: params }
|
@@ -173,7 +179,7 @@ module Tarantool
|
|
173
179
|
end
|
174
180
|
|
175
181
|
def space
|
176
|
-
@space ||=
|
182
|
+
@space ||= tarantool.space(space_no)
|
177
183
|
end
|
178
184
|
|
179
185
|
def tuple_to_hash(tuple)
|
data/lib/tarantool/request.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
1
|
+
class Tarantool
|
2
2
|
class Request
|
3
|
-
include EM::Deferrable
|
4
3
|
|
5
4
|
class << self
|
6
5
|
def request_type(name = nil)
|
@@ -48,8 +47,8 @@ module Tarantool
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def perform
|
51
|
-
send_packet
|
52
|
-
|
50
|
+
data = connection.send_packet request_id, make_packet(make_body)
|
51
|
+
make_response data
|
53
52
|
end
|
54
53
|
|
55
54
|
def parse_args
|
@@ -65,19 +64,13 @@ module Tarantool
|
|
65
64
|
body
|
66
65
|
end
|
67
66
|
|
68
|
-
def send_packet(packet)
|
69
|
-
connection.send_packet request_id, packet do |data|
|
70
|
-
make_response data
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
67
|
def make_response(data)
|
75
68
|
return_code, = data[0,4].unpack('L')
|
76
69
|
if return_code == 0
|
77
|
-
|
70
|
+
Response.new(data[4, data.size], response_params)
|
78
71
|
else
|
79
72
|
msg = data[4, data.size].unpack('A*')
|
80
|
-
|
73
|
+
raise BadReturnCode.new("Error code #{return_code}: #{msg}")
|
81
74
|
end
|
82
75
|
end
|
83
76
|
|
data/lib/tarantool/requests.rb
CHANGED
data/lib/tarantool/response.rb
CHANGED
data/lib/tarantool/space.rb
CHANGED
data/spec/helpers/truncate.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Helpers
|
2
2
|
module Truncate
|
3
3
|
def teardown
|
4
|
-
while (res =
|
4
|
+
while (res = space.call(proc_name: 'box.select_range', args: [space.space_no.to_s, '0', '100'], return_tuple: true)) && res.tuples.size > 0
|
5
5
|
res.tuples.each do |k, *_|
|
6
|
-
|
6
|
+
space.delete key: k
|
7
7
|
end
|
8
8
|
end
|
9
9
|
super
|
data/spec/spec_helper.rb
CHANGED
@@ -3,26 +3,19 @@ ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
|
|
3
3
|
Bundler.setup
|
4
4
|
|
5
5
|
require 'minitest/spec'
|
6
|
+
require 'minitest/autorun'
|
6
7
|
|
7
8
|
require 'helpers/let'
|
8
9
|
require 'helpers/truncate'
|
9
10
|
require 'rr'
|
10
11
|
|
11
|
-
require 'tarantool
|
12
|
+
require 'tarantool'
|
12
13
|
|
13
|
-
|
14
|
+
TARANTOOL_CONFIG = { host: '127.0.0.1', port: 33013, type: :block }
|
14
15
|
|
15
|
-
Tarantool.
|
16
|
+
DB = Tarantool.new TARANTOOL_CONFIG
|
16
17
|
|
17
18
|
class MiniTest::Unit::TestCase
|
18
19
|
extend Helpers::Let
|
19
20
|
include RR::Adapters::MiniTest
|
20
|
-
end
|
21
|
-
|
22
|
-
at_exit {
|
23
|
-
EM.synchrony do
|
24
|
-
exit_code = MiniTest::Unit.new.run(ARGV)
|
25
|
-
EM.stop
|
26
|
-
exit_code
|
27
|
-
end
|
28
|
-
}
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require "em-synchrony"
|
4
|
+
describe "Tarantool with EM" do
|
5
|
+
def space
|
6
|
+
@space ||= Tarantool.new(TARANTOOL_CONFIG.merge(type: :em)).space 1
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "insert, select and delete" do
|
10
|
+
it "should insert tuple and return it" do
|
11
|
+
EM.synchrony do
|
12
|
+
Fiber.new do
|
13
|
+
space.insert 100, 'привет', return_tuple: true
|
14
|
+
res = space.select 100
|
15
|
+
int, string = res.tuple
|
16
|
+
int.to_i.must_equal 100
|
17
|
+
string.to_s.must_equal 'привет'
|
18
|
+
space.delete 100
|
19
|
+
EM.stop
|
20
|
+
end.resume
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -5,11 +5,16 @@ require 'yajl'
|
|
5
5
|
require 'tarantool/serializers/bson'
|
6
6
|
describe Tarantool::Record do
|
7
7
|
include Helpers::Truncate
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
def space
|
10
|
+
@space ||= DB.space 0
|
10
11
|
end
|
12
|
+
|
11
13
|
let(:user_class) do
|
12
14
|
Class.new(Tarantool::Record) do
|
15
|
+
set_tarantool DB
|
16
|
+
set_space_no 0
|
17
|
+
|
13
18
|
def self.name # For naming
|
14
19
|
"User"
|
15
20
|
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe Tarantool::Request do
|
5
|
-
|
6
|
-
|
5
|
+
def space
|
6
|
+
@space ||= DB.space 1
|
7
7
|
end
|
8
8
|
describe "pack method" do
|
9
9
|
describe "for field" do
|
@@ -32,7 +32,7 @@ describe Tarantool::Request do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
describe "instance" do
|
35
|
-
let(:request) { Tarantool::Requests::Insert.new
|
35
|
+
let(:request) { Tarantool::Requests::Insert.new space }
|
36
36
|
|
37
37
|
it "should make packet with right request type, body size and next request id + body" do
|
38
38
|
body = 'hi'
|
@@ -46,8 +46,8 @@ describe Tarantool::Request do
|
|
46
46
|
include Helpers::Truncate
|
47
47
|
describe "insert and select" do
|
48
48
|
it "should insert tuple and return it" do
|
49
|
-
|
50
|
-
res =
|
49
|
+
space.insert 100, 'привет', return_tuple: true
|
50
|
+
res = space.select 100
|
51
51
|
int, string = res.tuple
|
52
52
|
int.to_i.must_equal 100
|
53
53
|
string.to_s.must_equal 'привет'
|
@@ -55,40 +55,40 @@ describe Tarantool::Request do
|
|
55
55
|
|
56
56
|
describe "with equal ids" do
|
57
57
|
it "should raise error" do
|
58
|
-
|
59
|
-
lambda {
|
58
|
+
space.insert 100, 'lala'
|
59
|
+
lambda { space.insert 100, 'yo' }.must_raise(Tarantool::BadReturnCode)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
describe "select" do
|
65
65
|
it "should select multiple tuples" do
|
66
|
-
|
67
|
-
|
68
|
-
res =
|
66
|
+
space.insert 100, 'привет'
|
67
|
+
space.insert 101, 'hi'
|
68
|
+
res = space.select 100, 101
|
69
69
|
res.tuples.map { |v| v.last.to_s }.must_equal ['привет', 'hi']
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
73
|
describe "call" do
|
74
74
|
it "should call lua proc" do
|
75
|
-
res =
|
75
|
+
res = space.call proc_name: 'box.pack', args: ['i', '100'], return_tuple: true
|
76
76
|
res.tuple[0].to_i.must_equal 100
|
77
77
|
end
|
78
78
|
|
79
79
|
it "should return batches via select_range" do
|
80
|
-
|
81
|
-
|
82
|
-
res =
|
80
|
+
space.insert 100, 'привет'
|
81
|
+
space.insert 101, 'hi'
|
82
|
+
res = space.call proc_name: 'box.select_range', args: ['1', '0', '100'], return_tuple: true
|
83
83
|
res.tuples.size.must_equal 2
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
describe "update" do
|
88
88
|
it "should update tuple" do
|
89
|
-
|
90
|
-
|
91
|
-
res =
|
89
|
+
space.insert 100, 'привет'
|
90
|
+
space.update 100, ops: [[1, :set, 'yo!']]
|
91
|
+
res = space.select 100
|
92
92
|
int, string = res.tuple
|
93
93
|
string.to_s.must_equal 'yo!'
|
94
94
|
end
|
@@ -96,16 +96,16 @@ describe Tarantool::Request do
|
|
96
96
|
|
97
97
|
describe "delete" do
|
98
98
|
it "should delete record" do
|
99
|
-
inserted =
|
100
|
-
|
101
|
-
res =
|
99
|
+
inserted = space.insert 100, 'привет', return_tuple: true
|
100
|
+
space.delete inserted.tuple[0], return_tuple: true
|
101
|
+
res = space.select 100
|
102
102
|
res.tuple.must_be_nil
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
106
|
describe "ping" do
|
107
107
|
it "should ping without exceptions" do
|
108
|
-
res =
|
108
|
+
res = space.ping
|
109
109
|
res.must_be_kind_of Numeric
|
110
110
|
end
|
111
111
|
end
|
data/tarantool.gemspec
CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
|
|
4
4
|
s.rubygems_version = '1.3.5'
|
5
5
|
|
6
6
|
s.name = 'tarantool'
|
7
|
-
s.version = '0.
|
8
|
-
s.date = '
|
7
|
+
s.version = '0.2'
|
8
|
+
s.date = '2012-01-23'
|
9
9
|
s.rubyforge_project = 'tarantool'
|
10
10
|
|
11
11
|
s.summary = "Tarantool KV-storage client."
|
@@ -20,9 +20,9 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.rdoc_options = ["--charset=UTF-8"]
|
21
21
|
s.extra_rdoc_files = %w[README.md LICENSE]
|
22
22
|
|
23
|
-
s.add_dependency('
|
23
|
+
s.add_dependency('iproto', [">= 0.1"])
|
24
24
|
s.add_dependency('activemodel', [">= 3.1", "< 4.0"])
|
25
|
-
|
25
|
+
|
26
26
|
|
27
27
|
# = MANIFEST =
|
28
28
|
s.files = %w[
|
@@ -33,10 +33,8 @@ Gem::Specification.new do |s|
|
|
33
33
|
Rakefile
|
34
34
|
examples/em_simple.rb
|
35
35
|
examples/record.rb
|
36
|
-
examples/
|
37
|
-
lib/em/protocols/fixed_header_and_body.rb
|
36
|
+
examples/simple.rb
|
38
37
|
lib/tarantool.rb
|
39
|
-
lib/tarantool/connection.rb
|
40
38
|
lib/tarantool/exceptions.rb
|
41
39
|
lib/tarantool/record.rb
|
42
40
|
lib/tarantool/request.rb
|
@@ -53,11 +51,11 @@ Gem::Specification.new do |s|
|
|
53
51
|
lib/tarantool/serializers/integer.rb
|
54
52
|
lib/tarantool/serializers/string.rb
|
55
53
|
lib/tarantool/space.rb
|
56
|
-
lib/tarantool/synchrony.rb
|
57
54
|
spec/helpers/let.rb
|
58
55
|
spec/helpers/truncate.rb
|
59
56
|
spec/spec_helper.rb
|
60
57
|
spec/tarantool.cfg
|
58
|
+
spec/tarantool/em_spec.rb
|
61
59
|
spec/tarantool/record_spec.rb
|
62
60
|
spec/tarantool/request_spec.rb
|
63
61
|
tarantool.gemspec
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tarantool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,25 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-23 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement: &
|
15
|
+
name: iproto
|
16
|
+
requirement: &70163621772280 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
22
|
-
- - <
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: 2.0.0
|
21
|
+
version: '0.1'
|
25
22
|
type: :runtime
|
26
23
|
prerelease: false
|
27
|
-
version_requirements: *
|
24
|
+
version_requirements: *70163621772280
|
28
25
|
- !ruby/object:Gem::Dependency
|
29
26
|
name: activemodel
|
30
|
-
requirement: &
|
27
|
+
requirement: &70163613525100 !ruby/object:Gem::Requirement
|
31
28
|
none: false
|
32
29
|
requirements:
|
33
30
|
- - ! '>='
|
@@ -38,21 +35,7 @@ dependencies:
|
|
38
35
|
version: '4.0'
|
39
36
|
type: :runtime
|
40
37
|
prerelease: false
|
41
|
-
version_requirements: *
|
42
|
-
- !ruby/object:Gem::Dependency
|
43
|
-
name: em-synchrony
|
44
|
-
requirement: &70194702021400 !ruby/object:Gem::Requirement
|
45
|
-
none: false
|
46
|
-
requirements:
|
47
|
-
- - ! '>='
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: 1.0.0
|
50
|
-
- - <
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '2.0'
|
53
|
-
type: :runtime
|
54
|
-
prerelease: false
|
55
|
-
version_requirements: *70194702021400
|
38
|
+
version_requirements: *70163613525100
|
56
39
|
description: Tarantool KV-storage client.
|
57
40
|
email: ceo@prepor.ru
|
58
41
|
executables: []
|
@@ -68,10 +51,8 @@ files:
|
|
68
51
|
- Rakefile
|
69
52
|
- examples/em_simple.rb
|
70
53
|
- examples/record.rb
|
71
|
-
- examples/
|
72
|
-
- lib/em/protocols/fixed_header_and_body.rb
|
54
|
+
- examples/simple.rb
|
73
55
|
- lib/tarantool.rb
|
74
|
-
- lib/tarantool/connection.rb
|
75
56
|
- lib/tarantool/exceptions.rb
|
76
57
|
- lib/tarantool/record.rb
|
77
58
|
- lib/tarantool/request.rb
|
@@ -88,11 +69,11 @@ files:
|
|
88
69
|
- lib/tarantool/serializers/integer.rb
|
89
70
|
- lib/tarantool/serializers/string.rb
|
90
71
|
- lib/tarantool/space.rb
|
91
|
-
- lib/tarantool/synchrony.rb
|
92
72
|
- spec/helpers/let.rb
|
93
73
|
- spec/helpers/truncate.rb
|
94
74
|
- spec/spec_helper.rb
|
95
75
|
- spec/tarantool.cfg
|
76
|
+
- spec/tarantool/em_spec.rb
|
96
77
|
- spec/tarantool/record_spec.rb
|
97
78
|
- spec/tarantool/request_spec.rb
|
98
79
|
- tarantool.gemspec
|
@@ -122,5 +103,6 @@ signing_key:
|
|
122
103
|
specification_version: 2
|
123
104
|
summary: Tarantool KV-storage client.
|
124
105
|
test_files:
|
106
|
+
- spec/tarantool/em_spec.rb
|
125
107
|
- spec/tarantool/record_spec.rb
|
126
108
|
- spec/tarantool/request_spec.rb
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
|
3
|
-
Bundler.setup
|
4
|
-
|
5
|
-
require 'tarantool/synchrony'
|
6
|
-
|
7
|
-
EM.synchrony do
|
8
|
-
Tarantool.configure host: 'localhost', port: 33013, space_no: 0
|
9
|
-
Tarantool.insert 'prepor', 'Andrew', 'ceo@prepor.ru'
|
10
|
-
res = Tarantool.select 'prepor'
|
11
|
-
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
|
12
|
-
EM.stop
|
13
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
module EventMachine
|
2
|
-
module Protocols
|
3
|
-
module FixedHeaderAndBody
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
base.extend ClassMethods
|
7
|
-
end
|
8
|
-
|
9
|
-
module ClassMethods
|
10
|
-
def header_size(size = nil)
|
11
|
-
if size
|
12
|
-
@_header_size = size
|
13
|
-
else
|
14
|
-
@_header_size
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
attr_accessor :header, :body
|
20
|
-
|
21
|
-
def receive_data(data)
|
22
|
-
@buffer ||= ''
|
23
|
-
offset = 0
|
24
|
-
while (chunk = data[offset, _needed_size - @buffer.size]).size > 0 || _needed_size == 0
|
25
|
-
@buffer += chunk
|
26
|
-
offset += chunk.size
|
27
|
-
if @buffer.size == _needed_size
|
28
|
-
case _state
|
29
|
-
when :receive_header
|
30
|
-
@_state = :receive_body
|
31
|
-
receive_header @buffer
|
32
|
-
when :receive_body
|
33
|
-
@_state = :receive_header
|
34
|
-
receive_body @buffer
|
35
|
-
end
|
36
|
-
@buffer = ''
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def receive_header(header)
|
42
|
-
# for override
|
43
|
-
end
|
44
|
-
|
45
|
-
def body_size
|
46
|
-
# for override
|
47
|
-
end
|
48
|
-
|
49
|
-
def receive_body(body)
|
50
|
-
# for override
|
51
|
-
end
|
52
|
-
|
53
|
-
def _needed_size
|
54
|
-
case _state
|
55
|
-
when :receive_header
|
56
|
-
self.class.header_size
|
57
|
-
when :receive_body
|
58
|
-
body_size
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def _state
|
63
|
-
@_state ||= :receive_header
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/lib/tarantool/connection.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'em/protocols/fixed_header_and_body'
|
2
|
-
module Tarantool
|
3
|
-
class Connection < EM::Connection
|
4
|
-
include EM::Protocols::FixedHeaderAndBody
|
5
|
-
|
6
|
-
header_size 12
|
7
|
-
|
8
|
-
def next_request_id
|
9
|
-
@next_request_id ||= 0
|
10
|
-
@next_request_id += 1
|
11
|
-
if @next_request_id > 0xffffffff
|
12
|
-
@next_request_id = 0
|
13
|
-
end
|
14
|
-
@next_request_id
|
15
|
-
end
|
16
|
-
|
17
|
-
def connection_completed
|
18
|
-
@connected = true
|
19
|
-
end
|
20
|
-
|
21
|
-
# begin FixedHeaderAndBody API
|
22
|
-
def body_size
|
23
|
-
@body_size
|
24
|
-
end
|
25
|
-
|
26
|
-
def receive_header(header)
|
27
|
-
@type, @body_size, @request_id = header.unpack('L3')
|
28
|
-
end
|
29
|
-
|
30
|
-
def receive_body(data)
|
31
|
-
clb = waiting_requests.delete @request_id
|
32
|
-
raise UnexpectedResponse.new("For request id #{@request_id}") unless clb
|
33
|
-
clb.call data
|
34
|
-
end
|
35
|
-
# end FixedHeaderAndBody API
|
36
|
-
|
37
|
-
def waiting_requests
|
38
|
-
@waiting_requests ||= {}
|
39
|
-
end
|
40
|
-
|
41
|
-
def send_packet(request_id, data, &clb)
|
42
|
-
send_data data
|
43
|
-
waiting_requests[request_id] = clb
|
44
|
-
end
|
45
|
-
|
46
|
-
def close_connection(*args)
|
47
|
-
super(*args)
|
48
|
-
end
|
49
|
-
|
50
|
-
def unbind
|
51
|
-
raise CouldNotConnect.new unless @connected
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
data/lib/tarantool/synchrony.rb
DELETED