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
@@ -0,0 +1,47 @@
1
+ require 'tarantool/em_db'
2
+
3
+ module Tarantool
4
+ class CallbackDB < EMDB
5
+ class SpaceArray < ::Tarantool::SpaceArray
6
+ alias by_pk by_pk_blk
7
+ alias all_by_key all_by_key_blk
8
+ alias first_by_key first_by_key_blk
9
+ alias all_by_keys all_by_keys_blk
10
+ alias select select_blk
11
+ alias insert insert_blk
12
+ alias replace replace_blk
13
+ alias update update_blk
14
+ alias delete delete_blk
15
+ alias invoke invoke_blk
16
+ alias call call_blk
17
+ alias ping ping_blk
18
+ end
19
+
20
+ class SpaceHash < ::Tarantool::SpaceHash
21
+ alias by_pk by_pk_blk
22
+ alias all all_blk
23
+ alias first first_blk
24
+ alias select select_blk
25
+ alias insert insert_blk
26
+ alias replace replace_blk
27
+ alias update update_blk
28
+ alias delete delete_blk
29
+ alias invoke invoke_blk
30
+ alias call call_blk
31
+ alias ping ping_blk
32
+ end
33
+
34
+ class Query < ::Tarantool::Query
35
+ alias select select_blk
36
+ alias all all_blk
37
+ alias first first_blk
38
+ alias insert insert_blk
39
+ alias replace replace_blk
40
+ alias update update_blk
41
+ alias delete delete_blk
42
+ alias invoke invoke_blk
43
+ alias call call_blk
44
+ alias ping ping_blk
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ require 'fiber'
2
+
3
+ class Fiber
4
+ alias call resume
5
+ end
6
+
7
+ module Kernel
8
+ def fiber_yield
9
+ Fiber.yield
10
+ end
11
+ alias fyield fiber_yield
12
+ end
@@ -0,0 +1,37 @@
1
+ module Tarantool
2
+ class EMDB < DB
3
+ def establish_connection
4
+ @connection_waiters = []
5
+ EM.schedule do
6
+ unless @closed
7
+ @connection = IProto.get_connection(@host, @port, :em_callback)
8
+ while waiter = @connection_waiters.shift
9
+ _send_request(*waiter)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ def close_connection
16
+ EM.schedule do
17
+ if @connection
18
+ @connection.close
19
+ @connection = nil
20
+ end
21
+ unless @connection_waiters.empty?
22
+ while waiter = @connection_waiters.shift
23
+ waiter.last.call(::IProto::Disconnected)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def _send_request(request_type, body, cb)
30
+ if @connection
31
+ @connection.send_request(request_type, body, cb)
32
+ else
33
+ @connection_waiters << [request_type, body, cb]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,9 +1,54 @@
1
- class Tarantool
1
+ module Tarantool
2
+ class ArgumentError < ::ArgumentError; end
3
+ class StringTooLong < ArgumentError; end
4
+
2
5
  class TarantoolError < StandardError; end
3
- class UndefinedRequestType < TarantoolError; end
4
- class BadReturnCode < TarantoolError; end
5
- class StringTooLong < TarantoolError; end
6
- class ArgumentError < TarantoolError; end
7
- class UndefinedSpace < TarantoolError; end
8
6
  class ValueError < TarantoolError; end
9
- end
7
+ class StatusCode < TarantoolError
8
+ attr_reader :code
9
+ def initialize(code, msg)
10
+ super(msg)
11
+ @code = code
12
+ end
13
+ def to_s
14
+ "#{super} [#{code}]"
15
+ end
16
+ end
17
+ # try again return codes
18
+ class TryAgain < StatusCode; end
19
+ class TupleReadOnly < TryAgain; end
20
+ class TupleIsLocked < TryAgain; end
21
+ class MemoryIssue < TryAgain; end
22
+ # general error return codes
23
+ class BadReturnCode < StatusCode; end
24
+ class NonMaster < BadReturnCode; end
25
+ class IllegalParams < BadReturnCode; end
26
+ class UnsupportedCommand < BadReturnCode; end
27
+ class WrongField < BadReturnCode; end
28
+ class WrongNumber < BadReturnCode; end
29
+ class Duplicate < BadReturnCode; end # it is rather useful
30
+ class WrongVersion < BadReturnCode; end
31
+ class WalIO < BadReturnCode; end
32
+ class LuaError < BadReturnCode; end
33
+ class StoredProcedureNotDefined < BadReturnCode; end
34
+ class TupleExists < BadReturnCode; end
35
+ class TupleDoesntExists < BadReturnCode; end
36
+ CODE_TO_EXCEPTION = {
37
+ 0x0401 => TupleReadOnly,
38
+ 0x0601 => TupleIsLocked,
39
+ 0x0701 => MemoryIssue,
40
+ 0x0102 => NonMaster,
41
+ 0x0202 => IllegalParams,
42
+ 0x0a02 => UnsupportedCommand,
43
+ 0x1e02 => WrongField,
44
+ 0x1f02 => WrongNumber,
45
+ 0x2002 => Duplicate,
46
+ 0x2602 => WrongVersion,
47
+ 0x2702 => WalIO,
48
+ 0x3102 => TupleDoesntExists,
49
+ 0x3202 => StoredProcedureNotDefined,
50
+ 0x3302 => LuaError,
51
+ 0x3702 => TupleExists,
52
+ }
53
+ CODE_TO_EXCEPTION.default = BadReturnCode
54
+ end
@@ -0,0 +1,152 @@
1
+ require 'iproto/core-ext'
2
+ require 'tarantool/em_db'
3
+
4
+ module Tarantool
5
+ class FiberDB < EMDB
6
+ module CommonSpaceFiberMethods
7
+ def all_by_pks(pks, opts={})
8
+ all_by_pks_cb(pks, ::Fiber.current, opts)
9
+ _raise_or_return ::Fiber.yield
10
+ end
11
+
12
+ def by_pk(pk)
13
+ by_pk_cb(pk, ::Fiber.current)
14
+ _raise_or_return ::Fiber.yield
15
+ end
16
+
17
+ def insert(tuple, opts={})
18
+ insert_cb(tuple, ::Fiber.current, opts)
19
+ _raise_or_return ::Fiber.yield
20
+ end
21
+
22
+ def replace(tuple, opts={})
23
+ replace_cb(tuple, ::Fiber.current, opts)
24
+ _raise_or_return ::Fiber.yield
25
+ end
26
+
27
+ def update(pk, operations, opts={})
28
+ update_cb(pk, operations, ::Fiber.current, opts)
29
+ _raise_or_return ::Fiber.yield
30
+ end
31
+
32
+ def delete(pk, opts={})
33
+ delete_cb(pk, ::Fiber.current, opts)
34
+ _raise_or_return ::Fiber.yield
35
+ end
36
+
37
+ def invoke(func_name, values = [], opts = {})
38
+ invoke_cb(func_name, values, ::Fiber.current, opts)
39
+ _raise_or_return ::Fiber.yield
40
+ end
41
+
42
+ def call(func_name, values = [], opts = {})
43
+ call_cb(func_name, values, ::Fiber.current, opts)
44
+ _raise_or_return ::Fiber.yield
45
+ end
46
+
47
+ def ping
48
+ ping_cb(::Fiber.current)
49
+ _raise_or_return ::Fiber.yield
50
+ end
51
+ end
52
+
53
+ class SpaceArray < ::Tarantool::SpaceArray
54
+ include CommonSpaceFiberMethods
55
+ def all_by_key(index_no, key, opts={})
56
+ all_by_key_cb(index_no, key, ::Fiber.current, opts)
57
+ _raise_or_return ::Fiber.yield
58
+ end
59
+
60
+ def first_by_key(index_no, key)
61
+ first_by_key_cb(index_no, key, ::Fiber.current)
62
+ _raise_or_return ::Fiber.yield
63
+ end
64
+
65
+ def all_by_keys(index_no, key, opts={})
66
+ all_by_keys_cb(index_no, key, ::Fiber.current, opts)
67
+ _raise_or_return ::Fiber.yield
68
+ end
69
+
70
+ def select(index_no, keys, offset=0, limit=-1)
71
+ select_cb(index_no, keys, offset, limit, ::Fiber.current)
72
+ _raise_or_return ::Fiber.yield
73
+ end
74
+ end
75
+
76
+ class SpaceHash < ::Tarantool::SpaceHash
77
+ include CommonSpaceFiberMethods
78
+
79
+ def by_pk(key_array)
80
+ by_pk_cb(key_array, ::Fiber.current)
81
+ _raise_or_return ::Fiber.yield
82
+ end
83
+
84
+ def all(keys, opts = {})
85
+ all_cb(keys, ::Fiber.current, opts)
86
+ _raise_or_return ::Fiber.yield
87
+ end
88
+
89
+ def first(key)
90
+ first_cb(key, ::Fiber.current)
91
+ _raise_or_return ::Fiber.yield
92
+ end
93
+
94
+ def select(keys, offset=0, limit=-1)
95
+ select_cb(keys, offset, limit, ::Fiber.current)
96
+ _raise_or_return ::Fiber.yield
97
+ end
98
+ end
99
+
100
+ class Query < ::Tarantool::Query
101
+ def select(space_no, index_no, keys, offset, limit, opts={})
102
+ select_cb(space_no, index_no, keys, offset, limit, ::Fiber.current, opts)
103
+ _raise_or_return ::Fiber.yield
104
+ end
105
+
106
+ def all(space_no, index_no, keys, opts={})
107
+ all_cb(space_no, index_no, keys, ::Fiber.current, opts)
108
+ _raise_or_return ::Fiber.yield
109
+ end
110
+
111
+ def first(space_no, index_no, key, opts={})
112
+ first_cb(space_no, index_no, key, ::Fiber.current, opts)
113
+ _raise_or_return ::Fiber.yield
114
+ end
115
+
116
+ def insert(space_no, tuple, opts={})
117
+ insert_cb(space_no, tuple, ::Fiber.current, opts)
118
+ _raise_or_return ::Fiber.yield
119
+ end
120
+
121
+ def replace(space_no, tuple, opts={})
122
+ replace_cb(space_no, tuple, ::Fiber.current, opts)
123
+ _raise_or_return ::Fiber.yield
124
+ end
125
+
126
+ def update(space_no, pk, operation, opts={})
127
+ update_cb(space_no, pk, operation, ::Fiber.current, opts)
128
+ _raise_or_return ::Fiber.yield
129
+ end
130
+
131
+ def delete(space_no, pk, opts={})
132
+ delete_cb(space_no, pk, ::Fiber.current, opts)
133
+ _raise_or_return ::Fiber.yield
134
+ end
135
+
136
+ def invoke(func_name, values, opts={})
137
+ invoke_cb(func_name, values, ::Fiber.current, opts)
138
+ _raise_or_return ::Fiber.yield
139
+ end
140
+
141
+ def call(func_name, values, opts={})
142
+ call_cb(func_name, values, ::Fiber.current, opts)
143
+ _raise_or_return ::Fiber.yield
144
+ end
145
+
146
+ def ping
147
+ ping_cb(::Fiber.current)
148
+ _raise_or_return ::Fiber.yield
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,68 @@
1
+ require 'tarantool/base_record'
2
+
3
+ module Tarantool
4
+ class LightRecord < BaseRecord
5
+ def initialize(attributes = nil)
6
+ @__new_record = true
7
+ @attributes = self.class.default_values.dup
8
+ set_attributes(attributes) if attributes
9
+ after_init
10
+ end
11
+
12
+ def __fetched(attributes)
13
+ @__new_record = false
14
+ @attributes = attributes
15
+ after_init
16
+ self
17
+ end
18
+
19
+ # callback which runs both after initialization and after
20
+ # fetching from database
21
+ def after_init
22
+ end
23
+
24
+ def save
25
+ if @__new_record
26
+ self.class.insert(@attributes)
27
+ @__new_record = false
28
+ else
29
+ self.class.replace(@attributes)
30
+ end
31
+ self
32
+ end
33
+
34
+ def destroy
35
+ self.class.delete id
36
+ true
37
+ end
38
+
39
+ class << self
40
+ def generated_attribute_methods
41
+ @generated_attribute_methods ||= begin
42
+ include (mod = Module.new)
43
+ mod
44
+ end
45
+ end
46
+
47
+ def define_field_accessor(name, type)
48
+ generated_attribute_methods.class_eval <<-"EOF", __FILE__, __LINE__ - 1
49
+ def #{name}
50
+ @attributes[:"#{name}"]
51
+ end
52
+
53
+ def #{name}=(v)
54
+ @attributes[:"#{name}"] = v
55
+ end
56
+ EOF
57
+ end
58
+
59
+ def create(attrs)
60
+ new(attrs).save
61
+ end
62
+
63
+ def from_fetched(attributes)
64
+ attributes && allocate.__fetched(attributes)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,127 @@
1
+ require 'tarantool/request'
2
+ require 'tarantool/response'
3
+
4
+ module Tarantool
5
+ class Query
6
+ include Request
7
+ def initialize(tarantool)
8
+ @tarantool = tarantool
9
+ end
10
+
11
+ def _send_request(type, body, cb)
12
+ @tarantool._send_request(type, body, cb)
13
+ end
14
+
15
+ def select_cb(space_no, index_no, keys, offset, limit, cb, opts={})
16
+ keys = [*keys]
17
+ types = opts[:types] || _detect_types(keys)
18
+ returns = opts[:returns] || TYPES_AUTO
19
+ if Hash === returns
20
+ returns, *translators = _parse_hash_definition(returns)
21
+ end
22
+ _select(space_no, index_no, offset, limit, keys, cb, returns,
23
+ types, translators)
24
+ end
25
+
26
+ def all_cb(space_no, index_no, keys, cb, opts={})
27
+ select_cb(space_no, index_no, keys,
28
+ opts[:offset] || 0, opts[:limit] || -1,
29
+ cb, opts)
30
+ end
31
+
32
+ def first_cb(space_no, index_no, key, cb, opts={})
33
+ select_cb(space_no, index_no, [key], 0, :first, cb, opts)
34
+ end
35
+
36
+ def insert_cb(space_no, tuple, cb, opts={})
37
+ types = opts[:types] || _detect_types(tuple)
38
+ _insert(space_no, BOX_ADD, tuple, types, cb, opts[:return_tuple])
39
+ end
40
+
41
+ def replace_cb(space_no, tuple, cb, opts={})
42
+ types = opts[:types] || _detect_types(tuple)
43
+ _insert(space_no, BOX_REPLACE, tuple, types, cb, opts[:return_tuple])
44
+ end
45
+
46
+ def update_cb(space_no, pk, operations, cb, opts={})
47
+ pk = [*pk]
48
+ pk_types = opts[:pk_types] || _detect_types(pk)
49
+ returns = opts[:returns] || TYPES_AUTO
50
+ if Hash === returns && opts[:return_tuple]
51
+ returns, *translators = _parse_hash_definition(returns)
52
+ end
53
+ _update(space_no, pk, operations, returns, pk_types, cb,
54
+ opts[:return_tuple], translators)
55
+ end
56
+
57
+ def delete_cb(space_no, pk, cb, opts={})
58
+ pk = [*pk]
59
+ pk_types = opts[:pk_types] || _detect_types(pk)
60
+ returns = opts[:returns] || TYPES_AUTO
61
+ if Hash === returns && opts[:return_tuple]
62
+ returns, *translators = _parse_hash_definition(returns)
63
+ end
64
+ _delete(space_no, pk, returns, pk_types, cb,
65
+ opts[:return_tuple], translators)
66
+ end
67
+
68
+ def invoke_cb(func_name, values, cb, opts={})
69
+ opts = opts.dup
70
+ values = [*values]
71
+ opts[:types] ||= _detect_types(values)
72
+ _call(func_name, values, cb, opts)
73
+ end
74
+
75
+ def call_cb(func_name, values, cb, opts={})
76
+ opts = opts.dup
77
+ values = [*values]
78
+ opts[:return_tuple] = true if opts[:return_tuple].nil?
79
+ opts[:types] ||= _detect_types(values)
80
+ opts[:returns] ||= TYPES_AUTO
81
+ if Hash === opts[:returns] && opts[:return_tuple]
82
+ opts[:returns], *opts[:translators] = _parse_hash_definition(opts[:returns])
83
+ end
84
+ _call(func_name, values, cb, opts)
85
+ end
86
+
87
+ def select_blk(space_no, index_no, keys, offset, limit, opts={}, &block)
88
+ select_cb(space_no, index_no, keys, offset, limit, block, opts)
89
+ end
90
+
91
+ def all_blk(space_no, index_no, keys, opts={}, &block)
92
+ all_cb(space_no, index_no, keys, block, opts)
93
+ end
94
+
95
+ def first_blk(space_no, index_no, key, opts={}, &block)
96
+ first_cb(space_no, index_no, key, block, opts)
97
+ end
98
+
99
+ def insert_blk(space_no, tuple, opts={}, &block)
100
+ insert_cb(space_no, tuple, block, opts)
101
+ end
102
+
103
+ def replace_blk(space_no, tuple, opts={}, &block)
104
+ replace_cb(space_no, tuple, block, opts)
105
+ end
106
+
107
+ def update_blk(space_no, pk, operation, opts={}, &block)
108
+ update_cb(space_no, pk, operation, block, opts={})
109
+ end
110
+
111
+ def delete_blk(space_no, pk, opts={}, &block)
112
+ delete_cb(space_no, pk, block, opts)
113
+ end
114
+
115
+ def invoke_blk(func_name, values, opts={}, &block)
116
+ invoke_cb(func_name, values, block, opts)
117
+ end
118
+
119
+ def call_blk(func_name, values, opts={}, &block)
120
+ call_cb(func_name, values, block, opts)
121
+ end
122
+
123
+ def ping_blk(&block)
124
+ ping_cb(block)
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,59 @@
1
+ module Tarantool
2
+ class BaseRecord
3
+ class Select
4
+ include Enumerable
5
+
6
+ attr_reader :record, :params
7
+ def initialize(record, params={})
8
+ @record = record
9
+ @params = params
10
+ end
11
+
12
+ def space_no
13
+ @record.space_no
14
+ end
15
+
16
+ def results
17
+ @results ||= begin
18
+ raise "Condition is not set" unless @params[:where]
19
+ @record.auto_space.select(
20
+ @params[:where],
21
+ @params[:offset] || 0,
22
+ @params[:limit] || -1
23
+ )
24
+ end
25
+ end
26
+
27
+ def each
28
+ return to_enum unless block_given?
29
+ results.each{|a| yield a}
30
+ end
31
+
32
+ def call(*args)
33
+ @record.call(*args)
34
+ end
35
+
36
+ def limit(limit)
37
+ self.class.new(@record, @params.merge(limit: limit))
38
+ end
39
+
40
+ def offset(offset)
41
+ self.class.new(@record, @params.merge(offset: offset))
42
+ end
43
+
44
+ def where(params)
45
+ self.class.new(@record, @params.merge(where: params))
46
+ end
47
+
48
+ def all
49
+ results.dup
50
+ end
51
+
52
+ def first
53
+ @record.auto_space.
54
+ select(@params[:where], @params[:offset] || 0, 1).
55
+ first
56
+ end
57
+ end
58
+ end
59
+ end