orientdb4r 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/changelog.txt CHANGED
@@ -1,3 +1,7 @@
1
+ 0.3.1 2012-08-27
2
+ - Timeout for reuse of dirty (already failed) nodes in load balancing
3
+ - Bug Fix #14, #15
4
+
1
5
  0.3.0 2012-08-01
2
6
  - introduced support for cluster of distributed servers
3
7
  - initial strategies for load balancing: sequence, round robin
@@ -20,7 +20,7 @@ class FlatClassPerf < FStudy::Case
20
20
  client.command 'DELETE FROM User'
21
21
  end
22
22
  def data
23
- 1.upto(10000) do |i|
23
+ 1.upto(100000) do |i|
24
24
  Orientdb4r::logger.info "...done: #{i}" if 0 == (i % 1000)
25
25
  first_name = dg.word
26
26
  surname = dg.word
@@ -9,10 +9,23 @@ module Orientdb4r
9
9
  # # Regexp to validate format of providet version.
10
10
  SERVER_VERSION_PATTERN = /^\d+\.\d+\.\d+/
11
11
 
12
+ # connection parameters
12
13
  attr_reader :user, :password, :database
14
+ # version loaded from server
13
15
  attr_reader :server_version
14
- attr_reader :nodes, :connection_library
15
- attr_reader :load_balancing, :lb_strategy
16
+ # type of connection library [:restclient, :excon]
17
+ attr_reader :connection_library
18
+ # type of load balancing [:sequence, :round_robin]
19
+ attr_reader :load_balancing
20
+ # proxy for remote communication
21
+ attr_reader :proxy
22
+
23
+ # intern structures
24
+
25
+ # nodes responsible for communication with a server
26
+ attr_reader :nodes
27
+ # object implementing a LB strategy
28
+ attr_reader :lb_strategy
16
29
 
17
30
  ###
18
31
  # Constructor.
@@ -282,6 +295,7 @@ module Orientdb4r
282
295
 
283
296
  rescue NodeError => e
284
297
  Orientdb4r::logger.error "node error, index=#{idx}, msg=#{e.message}, #{node}"
298
+ node.cleanup
285
299
  lb_strategy.bad_one idx
286
300
  idx = lb_strategy.node_index
287
301
  end
@@ -4,7 +4,7 @@ module Orientdb4r
4
4
  # Base class for implementation of load balancing strategy.
5
5
  class LBStrategy
6
6
 
7
- # If occures a new try to communicate from node can be tested.
7
+ # If occures a new try to communicate from node can be tested [s].
8
8
  RECOVERY_TIMEOUT = 30
9
9
 
10
10
  attr_reader :nodes_count, :bad_nodes
@@ -39,17 +39,39 @@ module Orientdb4r
39
39
 
40
40
  protected
41
41
 
42
+ ###
43
+ # Tries to find a new node if the given failed.
44
+ # Returns <i>nil</i> if no one found
42
45
  def search_next_good(bad_idx)
43
46
  Orientdb4r::logger.warn "identified bad node, idx=#{bad_idx}, age=#{Time.now - @bad_nodes[bad_idx]} [s]"
47
+
48
+ # alternative nodes of not found a good one
49
+ timeout_candidate = nil
50
+
51
+ # first round - try to find a first good one
44
52
  1.upto(nodes_count) do |i|
45
53
  candidate = (i + bad_idx) % nodes_count
46
- unless @bad_nodes.include? candidate
54
+
55
+ if @bad_nodes.include? candidate
56
+ failure_time = @bad_nodes[candidate]
57
+ now = Time.now
58
+ # timeout candidate
59
+ if (now - failure_time) > RECOVERY_TIMEOUT
60
+ timeout_candidate = candidate
61
+ Orientdb4r::logger.debug "node timeout recovery, idx=#{candidate}"
62
+ good_one(candidate)
63
+ end
64
+ else
47
65
  Orientdb4r::logger.debug "found good node, idx=#{candidate}"
48
66
  return candidate
49
67
  end
50
68
  end
51
69
 
52
- # TODO implement search based on LRU for next round
70
+ # no good index found -> try timeouted one
71
+ unless timeout_candidate.nil?
72
+ Orientdb4r::logger.debug "good node not found, delivering timeouted one, idx=#{timeout_candidate}"
73
+ return timeout_candidate
74
+ end
53
75
 
54
76
  Orientdb4r::logger.error 'no nodes more, all invalid'
55
77
  nil
@@ -12,18 +12,22 @@ module Orientdb4r
12
12
 
13
13
  def initialize(options) #:nodoc:
14
14
  super()
15
- options_pattern = { :host => 'localhost', :port => 2480, :ssl => false,
16
- :nodes => :optional, :load_balancing => :sequence,
17
- :connection_library => Orientdb4r::connection_library}
15
+ options_pattern = {
16
+ :host => 'localhost', :port => 2480, :ssl => false,
17
+ :nodes => :optional,
18
+ :connection_library => :restclient,
19
+ :load_balancing => :sequence,
20
+ :proxy => :optional
21
+ }
18
22
  verify_and_sanitize_options(options, options_pattern)
19
23
 
20
24
  # fake nodes for single server
21
25
  if options[:nodes].nil?
22
26
  options[:nodes] = [{:host => options[:host], :port => options[:port], :ssl => options[:ssl]}]
23
27
  end
24
- raise ArgumentError, 'nodes has to be arrray' unless options[:nodes].is_a? Array
28
+ raise ArgumentError, 'nodes has to be array' unless options[:nodes].is_a? Array
25
29
 
26
- # instantiate nodes accroding to HTTP library
30
+ # instantiate nodes according to HTTP library
27
31
  @connection_library = options[:connection_library]
28
32
  node_clazz = case connection_library
29
33
  when :restclient then Orientdb4r::RestClientNode
@@ -45,6 +49,14 @@ module Orientdb4r
45
49
  else raise ArgumentError, "unknow load balancing type: #{load_balancing}"
46
50
  end
47
51
 
52
+ # proxy
53
+ @proxy = options[:proxy]
54
+ unless proxy.nil?
55
+ case connection_library
56
+ when :restclient then ::RestClient.proxy = proxy
57
+ when :excon then nodes.each { |node| node.proxy = proxy }
58
+ end
59
+ end
48
60
 
49
61
  Orientdb4r::logger.info "client initialized with #{@nodes.size} node(s) "
50
62
  Orientdb4r::logger.info "connection_library=#{options[:connection_library]}, load_balancing=#{load_balancing}"
@@ -7,6 +7,8 @@ module Orientdb4r
7
7
  # accessible view REST API and 'excon' library on the client side.
8
8
  class ExconNode < RestNode
9
9
 
10
+ attr_accessor :proxy
11
+
10
12
  def request(options) #:nodoc:
11
13
  verify_options(options, {:user => :mandatory, :password => :mandatory, \
12
14
  :uri => :mandatory, :method => :mandatory, :content_type => :optional, :data => :optional})
@@ -77,10 +79,15 @@ module Orientdb4r
77
79
  ###
78
80
  # Gets Excon connection.
79
81
  def connection
80
- @connection ||= Excon::Connection.new(url)
81
- #:read_timeout => self.class.read_timeout,
82
- #:write_timeout => self.class.write_timeout,
83
- #:connect_timeout => self.class.connect_timeout
82
+ return @connection unless @connection.nil?
83
+
84
+ options = {}
85
+ options[:proxy] = proxy unless proxy.nil?
86
+
87
+ @connection ||= Excon::Connection.new(url, options)
88
+ #:read_timeout => self.class.read_timeout,
89
+ #:write_timeout => self.class.write_timeout,
90
+ #:connect_timeout => self.class.connect_timeout
84
91
  end
85
92
 
86
93
  ###
@@ -2,6 +2,7 @@ module Orientdb4r
2
2
 
3
3
  # Version history.
4
4
  VERSION_HISTORY = [
5
+ ['0.3.1', '2012-08-27', "Timeout for reuse of dirty nodes in load balancing; BF #14, BF #15"],
5
6
  ['0.3.0', '2012-08-01', "Added support for cluster of distributed servers + load balancing"],
6
7
  ['0.2.10', '2012-07-21', "Experimental support for Excon HTTP library with Keep-Alive connection"],
7
8
  ['0.2.9', '2012-07-18', "Added feature Client#delete_database, New class Rid"],
data/lib/orientdb4r.rb CHANGED
@@ -40,21 +40,10 @@ module Orientdb4r
40
40
  }
41
41
  end
42
42
 
43
- ###
44
- # All calls to REST API will use the proxy specified here.
45
- def rest_proxy(url)
46
- RestClient.proxy = url
47
- end
48
-
49
43
  ###
50
44
  # Logger used for logging output
51
45
  attr_accessor :logger
52
46
 
53
- ###
54
- # Predefined connection library.
55
- # Can be overriden by option in client initialization.
56
- attr_accessor :connection_library
57
-
58
47
  end
59
48
 
60
49
 
@@ -99,10 +88,6 @@ end
99
88
  Orientdb4r::logger = Logger.new(STDOUT)
100
89
  Orientdb4r::logger.level = Logger::INFO
101
90
 
102
- # Default connection library
103
- Orientdb4r::connection_library = :restclient
104
- #Orientdb4r::connection_library = :excon
105
-
106
91
  Orientdb4r::logger.info \
107
92
  "Orientdb4r #{Orientdb4r::VERSION}, running on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
108
93
 
@@ -0,0 +1,86 @@
1
+ require 'test/unit'
2
+ require 'orientdb4r'
3
+
4
+ ###
5
+ # This class tests communication with OrientDB cluster and load balancing.
6
+ class TestClient < Test::Unit::TestCase
7
+
8
+ Orientdb4r::logger.level = Logger::DEBUG
9
+
10
+ PROXY_URL = 'http://bad.domain.com'
11
+
12
+
13
+ ###
14
+ # Test inintialization of single node.
15
+ def test_one_node_initialization
16
+ client = Orientdb4r.client :instance => :new
17
+ assert_not_nil client.nodes
18
+ assert_instance_of Array, client.nodes
19
+ assert_equal 1, client.nodes.size
20
+ assert_equal 2480, client.nodes[0].port
21
+ assert_equal false, client.nodes[0].ssl
22
+ end
23
+
24
+ ###
25
+ # Test inintialization of more nodes.
26
+ def test_nodes_initialization
27
+ client = Orientdb4r.client :nodes => [{}, {:port => 2481}], :instance => :new
28
+ assert_not_nil client.nodes
29
+ assert_instance_of Array, client.nodes
30
+ assert_equal 2, client.nodes.size
31
+ assert_equal 2480, client.nodes[0].port
32
+ assert_equal 2481, client.nodes[1].port
33
+ assert_equal false, client.nodes[0].ssl
34
+ assert_equal false, client.nodes[1].ssl
35
+
36
+ client = Orientdb4r.client :nodes => [{}, {:port => 2481}, {:port => 2482}], :instance => :new
37
+ assert_equal 3, client.nodes.size
38
+ end
39
+
40
+ ###
41
+ # Tests initialization of connection library.
42
+ def test_connection_library
43
+ # restclient
44
+ client = Orientdb4r.client :instance => :new
45
+ assert_equal :restclient, client.connection_library
46
+ assert_instance_of Orientdb4r::RestClientNode, client.nodes[0]
47
+
48
+ # excon
49
+ client = Orientdb4r.client :connection_library => :excon, :instance => :new
50
+ assert_equal :excon, client.connection_library
51
+ assert_instance_of Orientdb4r::ExconNode, client.nodes[0]
52
+ end
53
+
54
+ ###
55
+ # Tests initialization of proxy.
56
+ def test_proxy
57
+ # no proxy - resclient
58
+ client = Orientdb4r.client :instance => :new
59
+ assert_nil client.proxy
60
+ assert_nil RestClient.proxy
61
+
62
+ # proxy - restclient
63
+ client = Orientdb4r.client :proxy => PROXY_URL, :instance => :new
64
+ assert_equal PROXY_URL, client.proxy
65
+ assert_equal PROXY_URL, RestClient.proxy
66
+ assert_raise Orientdb4r::ConnectionError do
67
+ client.connect :database => 'temp', :user => 'admin', :password => 'admin'
68
+ end
69
+ RestClient.proxy = nil # restore no setting
70
+
71
+ # no proxy - excon
72
+ client = Orientdb4r.client :connection_library => :excon, :instance => :new
73
+ assert_nil client.proxy
74
+ assert_nil client.nodes[0].proxy
75
+
76
+ # proxy - restclient
77
+ client = Orientdb4r.client :connection_library => :excon, :proxy => PROXY_URL, :instance => :new
78
+ assert_equal PROXY_URL, client.proxy
79
+ assert_equal PROXY_URL, client.nodes[0].proxy
80
+ assert_raise Orientdb4r::ConnectionError do
81
+ client.connect :database => 'temp', :user => 'admin', :password => 'admin'
82
+ end
83
+ end
84
+
85
+
86
+ end
@@ -3,39 +3,16 @@ require 'orientdb4r'
3
3
 
4
4
  ###
5
5
  # This class tests communication with OrientDB cluster and load balancing.
6
- class TestDatabase < Test::Unit::TestCase
6
+ class TestLoadBalancing < Test::Unit::TestCase
7
7
 
8
8
  Orientdb4r::logger.level = Logger::DEBUG
9
9
 
10
10
 
11
- ###
12
- # Test inintialization of single node.
13
- def test_one_node_initialization
14
- client = Orientdb4r.client :instance => :new
15
- assert_not_nil client.nodes
16
- assert_instance_of Array, client.nodes
17
- assert_equal 1, client.nodes.size
18
- assert_equal 2480, client.nodes[0].port
19
- assert_equal false, client.nodes[0].ssl
20
- end
21
-
22
- ###
23
- # Test inintialization of more nodes.
24
- def test_nodes_initialization
25
- client = Orientdb4r.client :nodes => [{}, {:port => 2481}], :instance => :new
26
- assert_not_nil client.nodes
27
- assert_instance_of Array, client.nodes
28
- assert_equal 2, client.nodes.size
29
- assert_equal 2480, client.nodes[0].port
30
- assert_equal 2481, client.nodes[1].port
31
- assert_equal false, client.nodes[0].ssl
32
- assert_equal false, client.nodes[1].ssl
33
- end
34
-
35
11
  ###
36
12
  # Test default Sequence strategy.
37
13
  def test_sequence_loadbalancing
38
14
  client = Orientdb4r.client :nodes => [{}, {:port => 2481}], :instance => :new
15
+ assert_equal :sequence, client.load_balancing
39
16
  lb_strategy = client.lb_strategy
40
17
  assert_not_nil lb_strategy
41
18
  assert_instance_of Orientdb4r::Sequence, lb_strategy
@@ -49,6 +26,7 @@ class TestDatabase < Test::Unit::TestCase
49
26
  # Test RoundRobin strategy.
50
27
  def test_roundrobin_loadbalancing
51
28
  client = Orientdb4r.client :nodes => [{}, {:port => 2481}], :load_balancing => :round_robin, :instance => :new
29
+ assert_equal :round_robin, client.load_balancing
52
30
  lb_strategy = client.lb_strategy
53
31
  assert_not_nil lb_strategy
54
32
  assert_instance_of Orientdb4r::RoundRobin, lb_strategy
@@ -60,6 +38,8 @@ class TestDatabase < Test::Unit::TestCase
60
38
  assert_equal client.nodes[1], client.nodes[client.lb_strategy.node_index]
61
39
  end
62
40
 
41
+ ###
42
+ # Tests variant reasons for LB failure.
63
43
  def test_load_balancing_in_problems
64
44
  # invalid port
65
45
  client = Orientdb4r.client :port => 9999, :instance => :new
data/test/test_utils.rb CHANGED
@@ -3,7 +3,7 @@ require 'orientdb4r'
3
3
 
4
4
  ###
5
5
  # This class tests Utils methods.
6
- class TestDmo < Test::Unit::TestCase
6
+ class TestUtils < Test::Unit::TestCase
7
7
  include Orientdb4r::Utils
8
8
 
9
9
  def test_verify_options
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orientdb4r
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-01 00:00:00.000000000 Z
12
+ date: 2012-08-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -65,11 +65,12 @@ files:
65
65
  - lib/orientdb4r/version.rb
66
66
  - orientdb4r.gemspec
67
67
  - test/readme_sample.rb
68
+ - test/test_client.rb
68
69
  - test/test_database.rb
69
70
  - test/test_ddo.rb
70
- - test/test_distributed.rb
71
71
  - test/test_dmo.rb
72
72
  - test/test_document_crud.rb
73
+ - test/test_loadbalancing.rb
73
74
  - test/test_utils.rb
74
75
  homepage: http://github.com/veny/orientdb4r
75
76
  licenses: []
@@ -92,15 +93,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
93
  version: 1.3.1
93
94
  requirements: []
94
95
  rubyforge_project:
95
- rubygems_version: 1.8.19
96
+ rubygems_version: 1.8.23
96
97
  signing_key:
97
98
  specification_version: 3
98
99
  summary: Ruby binding for Orient DB.
99
100
  test_files:
100
101
  - test/readme_sample.rb
102
+ - test/test_client.rb
101
103
  - test/test_database.rb
102
104
  - test/test_ddo.rb
103
- - test/test_distributed.rb
104
105
  - test/test_dmo.rb
105
106
  - test/test_document_crud.rb
107
+ - test/test_loadbalancing.rb
106
108
  - test/test_utils.rb