About
Its ruby client for Tarantool Key-Value Storage.
Install
gem install tarantool
Usage
require 'tarantool'
To be able to send requests to the server, you must initialize Tarantool and Tarantool space:
DB = Tarantool.new host: 'locahost', port: 33013
space = DB.space 0
The driver internals can work in two modes: block via TCPSocket and non block via EventMachine and fibers. By default it uses block mode.
space.insert 'prepor', 'Andrew', '[email protected]'
res = space.select 'prepor'
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
space.delete 'prepor'
Notice Tarantool
instances (connections actually) are not threadsafe. So, you should create Tarantool
instance per thread.
To use EventMachine pass type: em in options:
require 'em-synchrony'
DB = Tarantool.new host: 'locahost', port: 33013
space = DB.space 0
EM.synchrony do
Fiber.new do
space.insert 'prepor', 'Andrew', '[email protected]'
res = space.select 'prepor'
puts "Name: #{res.tuple[1].to_s}; Email: #{res.tuple[2].to_s}"
space.delete 'prepor'
end.resume
end
The driver itself provides ActiveModel API: Callbacks, Validations, Serialization, Dirty. Type casting is automatic, based on the index type chosen to process the query. For example:
require 'tarantool/record'
require 'tarantool/serializers/bson'
class User < Tarantool::Record
field :login, :string
field :name, :string
field :email, :string
field :apples_count, :integer, default: 0
field :info, :bson
index :name, :email
validates_length_of(:login, minimum: 3)
after_create do
# after work!
end
end
# Now attribute positions are not important.
User.create login: 'prepor', email: '[email protected]', name: 'Andrew'
User.create login: 'ruden', name: 'Andrew', email: '[email protected]'
# find by primary key login
User.find 'prepor'
# first 2 users with name Andrew
User.where(name: 'Andrew').limit(2).all
# second user with name Andrew
User.where(name: 'Andrew').offset(1).limit(1).all
# user with name Andrew and email [email protected]
User.where(name: 'Andrew', email: '[email protected]').first
# raise exception, becouse we can't select query started from not first part of index
begin
User.where(email: '[email protected]')
rescue Tarantool::ArgumentError => e
end
# increment field apples_count by one. Its atomic operation via native Tarantool interface
User.find('prepor').increment :apples_count
# update only dirty attributes
user = User.find('prepor')
user.name = "Petr"
user.save
# field serialization to bson
user.info = { 'bio' => "hi!", 'age' => 23, 'hobbies' => ['mufa', 'tuka'] }
user.save
User.find('prepor').info['bio'] # => 'hi!'
# delete record
user.destroy
When definining a record, field order is important: this is the order of fields in the tuple stored by Tarantool. By default, the primary key is field 0.
index
method just mapping to your Tarantool schema, client doesn't modify schema for you.
TODO
#first
,#all
without keys, batches requests via box.select_range#where
chains- admin-socket protocol
- safe to add fields to exist model
- Hash, Array and lambdas as default values
- timers to response, reconnect strategies