neography 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 019b250080905755da04979dfb0073f6fa7a5794
4
- data.tar.gz: 5eae513cb7e9ca6dcfebfda920219217e436b587
3
+ metadata.gz: ae76679128738baf8ce0f7e770abda5aab5f5391
4
+ data.tar.gz: e1da52e3ce0cf1f8182cdb5dc109b70ffb084487
5
5
  SHA512:
6
- metadata.gz: 1a1add73720dec8732b633a70901e2eb9ee68aa3b7bd47d5560d897a87df04b1c1a92c9206067626892db7684c33aefc991c2bb38386c4e56b5da16b3e2f411e
7
- data.tar.gz: 1adb3519a08080d05ea3ff43329b46673667df8d840cd98974aec1cbd75e6a3cbbbd81a7aa89c90d19dc6b3a27110ba5fed34811c2aa9c39373c227cd1388d59
6
+ metadata.gz: 94a8a3375f463c3cf7d036f8d06f82e15971dfc3723cff255701d135d634d42ad31128c3839d58b09defa92723e0563898925f16298ee8fd548abfa19589a3f5
7
+ data.tar.gz: ca5a8a40e7fca44bd8c478eb3e6f1a6e4254dbdd55737156224a85aad6dd3c712c5a53ca27495d352aacbc1182f0cfb37649abee31048d6f36473fca7d721a6f
data/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ v1.4.2
2
+ =======
3
+ ee25406 Bump to 1.4.2
4
+ c56574f Add batch_no_streaming method
5
+
1
6
  v1.3.11
2
7
  =======
3
8
  49e310d Bump to 1.3.11
data/lib/neography.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'cgi'
2
- require 'httpclient'
2
+ require 'excon'
3
3
  require 'json'
4
4
  require 'multi_json'
5
5
  require 'logger'
@@ -7,7 +7,7 @@ module Neography
7
7
  :max_threads,
8
8
  :authentication, :username, :password,
9
9
  :parser, :max_execution_time,
10
- :proxy
10
+ :proxy, :http_send_timeout, :http_receive_timeout
11
11
 
12
12
  def initialize
13
13
  set_defaults
@@ -15,45 +15,49 @@ module Neography
15
15
 
16
16
  def to_hash
17
17
  {
18
- :protocol => @protocol,
19
- :server => @server,
20
- :port => @port,
21
- :directory => @directory,
22
- :cypher_path => @cypher_path,
23
- :gremlin_path => @gremlin_path,
24
- :log_file => @log_file,
25
- :log_enabled => @log_enabled,
26
- :logger => @logger,
27
- :slow_log_threshold => @slow_log_threshold,
28
- :max_threads => @max_threads,
29
- :authentication => @authentication,
30
- :username => @username,
31
- :password => @password,
32
- :parser => @parser,
33
- :max_execution_time => @max_execution_time,
34
- :proxy => @proxy
18
+ :protocol => @protocol,
19
+ :server => @server,
20
+ :port => @port,
21
+ :directory => @directory,
22
+ :cypher_path => @cypher_path,
23
+ :gremlin_path => @gremlin_path,
24
+ :log_file => @log_file,
25
+ :log_enabled => @log_enabled,
26
+ :logger => @logger,
27
+ :slow_log_threshold => @slow_log_threshold,
28
+ :max_threads => @max_threads,
29
+ :authentication => @authentication,
30
+ :username => @username,
31
+ :password => @password,
32
+ :parser => @parser,
33
+ :max_execution_time => @max_execution_time,
34
+ :proxy => @proxy,
35
+ :http_send_timeout => @http_send_timeout,
36
+ :http_receive_timeout => @http_receive_timeout
35
37
  }
36
38
  end
37
39
 
38
40
  private
39
41
 
40
42
  def set_defaults
41
- @protocol = "http://"
42
- @server = "localhost"
43
- @port = 7474
44
- @directory = ""
45
- @cypher_path = "/cypher"
46
- @gremlin_path = "/ext/GremlinPlugin/graphdb/execute_script"
47
- @log_file = "neography.log"
48
- @log_enabled = false
49
- @slow_log_threshold = 0
50
- @max_threads = 20
51
- @authentication = nil
52
- @username = nil
53
- @password = nil
54
- @parser = MultiJsonParser
55
- @max_execution_time = 6000
56
- @proxy = nil
43
+ @protocol = "http://"
44
+ @server = "localhost"
45
+ @port = 7474
46
+ @directory = ""
47
+ @cypher_path = "/cypher"
48
+ @gremlin_path = "/ext/GremlinPlugin/graphdb/execute_script"
49
+ @log_file = "neography.log"
50
+ @log_enabled = false
51
+ @slow_log_threshold = 0
52
+ @max_threads = 20
53
+ @authentication = nil
54
+ @username = nil
55
+ @password = nil
56
+ @parser = MultiJsonParser
57
+ @max_execution_time = 6000
58
+ @proxy = nil
59
+ @http_send_timeout = 1200
60
+ @http_receive_timeout = 1200
57
61
  end
58
62
 
59
63
  end
@@ -4,22 +4,25 @@ module Neography
4
4
  class Connection
5
5
  USER_AGENT = "Neography/#{Neography::VERSION}"
6
6
  ACTIONS = ["get", "post", "put", "delete"]
7
-
8
- attr_accessor :protocol, :server, :port, :directory,
7
+
8
+ attr_reader :protocol, :server, :port, :directory,
9
9
  :cypher_path, :gremlin_path,
10
10
  :log_file, :log_enabled, :logger, :slow_log_threshold,
11
11
  :max_threads,
12
12
  :authentication, :username, :password,
13
13
  :parser, :client,
14
- :proxy
14
+ :proxy, :http_send_timeout, :http_receive_timeout
15
15
 
16
16
  def initialize(options = ENV['NEO4J_URL'] || {})
17
17
  config = merge_configuration(options)
18
18
  save_local_configuration(config)
19
- @client ||= HTTPClient.new(config[:proxy])
20
- @client.send_timeout = 1200 # 10 minutes
21
- @client.receive_timeout = 1200
22
- authenticate
19
+ @client ||= Excon.new(config[:proxy] || "#{@protocol}#{@server}:#{@port}",
20
+ :read_timeout => config[:http_receive_timeout],
21
+ :write_timeout => config[:http_send_timeout],
22
+ :persistent => true,
23
+ :user => config[:username],
24
+ :password => config[:password])
25
+ #authenticate
23
26
  end
24
27
 
25
28
  def configure(protocol, server, port, directory)
@@ -35,23 +38,39 @@ module Neography
35
38
 
36
39
  def merge_options(options)
37
40
  merged_options = options.merge!(@authentication)
38
- merged_options[:headers].merge!(@user_agent) if merged_options[:headers]
39
- merged_options[:headers].merge!('X-Stream' => true) if merged_options[:headers]
40
- merged_options[:headers].merge!(@max_execution_time) if merged_options[:headers]
41
+ if merged_options[:headers]
42
+ merged_options[:headers].merge!(@user_agent)
43
+ merged_options[:headers].merge!('X-Stream' => true) unless merged_options[:headers].key?('X-Stream')
44
+ merged_options[:headers].merge!(@max_execution_time)
45
+ end
41
46
  merged_options
42
47
  end
43
48
 
44
49
  ACTIONS.each do |action|
45
- define_method(action) do |path, options = {}|
50
+ define_method(action) do |path, options = {}|
46
51
  # This ugly hack is required because internal Batch paths do not start with "/db/data"
47
52
  # if somebody has a cleaner solution... pull request please!
48
- path = "/db/data" + path if ["node", "relationship", "transaction", "cypher", "propertykeys", "schema", "label", "labels", "batch", "index", "ext"].include?(path.split("/")[1].split("?").first)
49
- query_path = configuration + path
50
- query_body = merge_options(options)[:body]
53
+ partial_path = path.split("/")
54
+ if partial_path.size > 0
55
+ partial_path = partial_path[1].split("?").first
56
+ end
57
+ reserved = ["node", "relationship", "transaction", "cypher", "propertykeys", "schema", "label", "labels", "batch", "index", "ext"]
58
+ path = "/db/data" + path if reserved.include?(partial_path)
59
+ query_body = options[:body]
60
+ stream = ""
61
+ headers = merge_options(options)[:headers]
51
62
  log path, query_body do
52
- evaluate_response(@client.send(action.to_sym, query_path, query_body, merge_options(options)[:headers]), path, query_body)
63
+ req_params = {:method => action.to_sym, :path => path, :body => query_body, :headers => headers}
64
+ is_streaming = headers && (headers['X-Stream'] == true)
65
+ if is_streaming
66
+ streamer = lambda { |chunk, _, _| stream += chunk }
67
+ req_params.merge!({:persistent => false, :response_block => streamer,
68
+ :read_timeout => 100000000, :write_timeout => 100000000})
69
+ end
70
+ response = @client.request(req_params)
71
+ evaluate_response(response, path, query_body, is_streaming, (partial_path == "batch"), stream)
53
72
  end
54
- end
73
+ end
55
74
  end
56
75
 
57
76
  def log(path, body)
@@ -80,7 +99,7 @@ module Neography
80
99
  @client.www_auth.basic_auth.challenge(configuration) if auth_type == 'basic_auth'
81
100
  end
82
101
  end
83
-
102
+
84
103
  private
85
104
 
86
105
  def merge_configuration(options)
@@ -127,29 +146,31 @@ module Neography
127
146
  return_result(code, result)
128
147
  end
129
148
 
130
- def evaluate_response(response, path, query_body)
131
- if response.http_header.request_uri.request_uri == "/db/data/batch"
132
- code, body, parsed = handle_batch(response)
149
+ def evaluate_response(response, path, query_body, streaming, batching, stream = nil)
150
+ code = response.status
151
+ parsed = false
152
+ if streaming && batching
153
+ code, body, parsed = handle_batch(stream)
154
+ elsif streaming
155
+ body = (stream || '').force_encoding("UTF-8")
133
156
  else
134
- code = response.code
135
157
  body = response.body.force_encoding("UTF-8")
136
- parsed = false
137
158
  end
138
159
  return_result(response, code, body, parsed, path, query_body)
139
160
  end
140
161
 
141
- def handle_batch(response)
162
+ def handle_batch(stream)
142
163
  code = 200
143
- body = @parser.json(response.body.force_encoding("UTF-8"))
164
+ body = @parser.json(stream.force_encoding("UTF-8"))
144
165
  body.each do |result|
145
166
  if result["status"] >= 400
146
- code = result["status"]
167
+ code = result["status"]
147
168
  break
148
169
  end
149
170
  end
150
171
  return code, body, true
151
172
  end
152
-
173
+
153
174
  def return_result(response, code, body, parsed, path, query_body)
154
175
  case code
155
176
  when 200
@@ -166,7 +187,7 @@ module Neography
166
187
  when 400..500
167
188
  handle_4xx_500_response(response, code, body, path, query_body)
168
189
  nil
169
- end
190
+ end
170
191
  end
171
192
 
172
193
  def handle_4xx_500_response(response, code, body, path, query_body)
@@ -184,7 +205,7 @@ module Neography
184
205
  parsed_body = result["body"] || result
185
206
  break
186
207
  end
187
- end
208
+ end
188
209
  else
189
210
  parsed_body = @parser.json(body)
190
211
  end
@@ -195,7 +216,7 @@ module Neography
195
216
  @logger.error "#{response.dump} error: #{body}" if @log_enabled
196
217
  raise_errors(code, parsed_body["exception"], message, stacktrace, request, index)
197
218
  end
198
-
219
+
199
220
  def raise_errors(code, exception, message, stacktrace, request, index)
200
221
  error = nil
201
222
  case code
@@ -215,12 +236,12 @@ module Neography
215
236
  when /RelationshipNotFoundException/ ; RelationshipNotFoundException
216
237
  when /NotFoundException/ ; NotFoundException
217
238
  when /UniquePathNotUniqueException/ ; UniquePathNotUniqueException
218
- when /DeadlockDetectedException/ ; DeadlockDetectedException
239
+ when /DeadlockDetectedException/ ; DeadlockDetectedException
219
240
  else
220
241
  NeographyError
221
242
  end
222
-
223
- raise error.new(message, code, stacktrace, request, index)
243
+
244
+ raise error.new(message, code, stacktrace, request, index)
224
245
  end
225
246
 
226
247
  def parse_string_options(options)
@@ -51,4 +51,7 @@ module Neography
51
51
  # Signals that a deadlock between two or more transactions has been detected
52
52
  class DeadlockDetectedException < NeographyError; end
53
53
 
54
+ # Unknown batch option exception detected
55
+ class UnknownBatchOptionException < NeographyError; end
56
+
54
57
  end
@@ -7,25 +7,35 @@ module Neography
7
7
  do_batch(*args)
8
8
  end
9
9
 
10
+ def batch_no_streaming(*args)
11
+ do_batch_no_streaming(*args)
12
+ end
13
+
10
14
  private
11
15
 
12
16
  def do_batch(*args)
17
+ @connection.post("/batch", compute_batch_options(*args))
18
+ end
19
+
20
+ def do_batch_no_streaming(*args)
21
+ options = compute_batch_options(*args)
22
+ options[:headers].merge!({ 'X-Stream' => false })
23
+ @connection.post("/batch", options)
24
+ end
25
+
26
+ def compute_batch_options(*args)
13
27
  batch = []
14
28
  Array(args).each_with_index do |c, i|
15
29
  batch << {:id => i }.merge(get_batch(c))
16
30
  end
17
- options = {
18
- :body => batch.to_json,
19
- :headers => json_content_type
20
- }
21
- @connection.post("/batch", options)
31
+ {:body => batch.to_json, :headers => json_content_type}
22
32
  end
23
33
 
24
34
  def get_batch(args)
25
35
  begin
26
36
  send("batch_#{args[0]}".to_sym, *args[1..-1])
27
37
  rescue
28
- raise "Unknown option #{args[0]} - #{args}"
38
+ raise UnknownBatchOptionException.new("Unknown option #{args[0]} - #{args}")
29
39
  end
30
40
  end
31
41
 
@@ -23,7 +23,7 @@ module Neography
23
23
  end
24
24
 
25
25
  def query_node_auto_index(query_expression)
26
- @connection.get("/index/auto/node/?query=%{query}" % {:query => query_expression}) || []
26
+ @connection.get("/index/auto/node/?query=%{query}" % {:query => encode(query_expression)}) || []
27
27
  end
28
28
 
29
29
  def get_node_auto_index_status
@@ -1,6 +1,6 @@
1
1
  module Neography
2
2
  class Rest
3
- module NodeIndexes
3
+ module NodeIndexes
4
4
  include Neography::Rest::Helpers
5
5
 
6
6
  def list_node_indexes
@@ -117,7 +117,21 @@ module Neography
117
117
  :headers => json_content_type
118
118
  }
119
119
  @connection.post("/index/node/%{index}?uniqueness=%{function}" % {:index => index, :function => 'get_or_create'}, options)
120
-
120
+
121
+ end
122
+
123
+ def create_or_fail_unique_node(index, key, value, properties = {})
124
+ options = {
125
+ :body => (
126
+ { :properties => properties,
127
+ :key => key,
128
+ :value => value
129
+ }
130
+ ).to_json,
131
+ :headers => json_content_type
132
+ }
133
+ @connection.post("/index/node/%{index}?uniqueness=%{function}" % {:index => index, :function => 'create_or_fail'}, options)
134
+
121
135
  end
122
136
 
123
137
  end
@@ -1,6 +1,6 @@
1
1
  module Neography
2
2
  class Rest
3
- module RelationshipIndexes
3
+ module RelationshipIndexes
4
4
  include Neography::Rest::Helpers
5
5
 
6
6
  def list_relationship_indexes
@@ -118,7 +118,21 @@ module Neography
118
118
  :headers => json_content_type
119
119
  }
120
120
  @connection.post("/index/relationship/%{index}?uniqueness=%{function}" % {:index => index, :function => 'get_or_create'}, options)
121
-
121
+
122
+ end
123
+
124
+ def create_or_fail_unique_relationship(index, key, value, properties = {})
125
+ options = {
126
+ :body => (
127
+ { :properties => properties,
128
+ :key => key,
129
+ :value => value
130
+ }
131
+ ).to_json,
132
+ :headers => json_content_type
133
+ }
134
+ @connection.post("/index/relationship/%{index}?uniqueness=%{function}" % {:index => index, :function => 'create_or_fail'}, options)
135
+
122
136
  end
123
137
 
124
138
  end
@@ -1,13 +1,12 @@
1
1
  # borrowed from architect4r
2
2
  require 'os'
3
- require 'httpclient'
4
3
  require 'zip'
5
4
  require 'net/http'
6
5
 
7
6
  namespace :neo4j do
8
7
  desc "Install Neo4j"
9
8
  task :install, :edition, :version do |t, args|
10
- args.with_defaults(:edition => "community", :version => "2.0.1")
9
+ args.with_defaults(:edition => "community", :version => "2.0.3")
11
10
  puts "Installing Neo4j-#{args[:edition]}-#{args[:version]}"
12
11
 
13
12
  if OS::Underlying.windows?
@@ -1,3 +1,3 @@
1
1
  module Neography
2
- VERSION = "1.4.1"
2
+ VERSION = "1.5.0"
3
3
  end
data/neography.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency "rspec", ">= 2.11"
24
24
  s.add_development_dependency "net-http-spy", "0.2.1"
25
25
  s.add_development_dependency "coveralls"
26
- s.add_dependency "httpclient", ">= 2.3.3"
26
+ s.add_dependency "excon", "~> 0.33.0"
27
27
  s.add_dependency "json", ">= 1.7.7"
28
28
  s.add_dependency "os", ">= 0.9.6"
29
29
  s.add_dependency "rubyzip", ">= 1.0.0"
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "no streaming" do
9
+
10
+ it "can send a 1000 item batch" do
11
+ commands = []
12
+ 1000.times do |x|
13
+ commands << [:create_node, {"name" => "Max " + x.to_s}]
14
+ end
15
+ batch_result = @neo.batch_no_streaming *commands
16
+ batch_result.first["body"]["data"]["name"].should == "Max 0"
17
+ batch_result.last["body"]["data"]["name"].should == "Max 999"
18
+ end
19
+
20
+ it "can send a 5000 item batch" do
21
+ commands = []
22
+ 5000.times do |x|
23
+ commands << [:get_node, 0]
24
+ end
25
+ batch_result = @neo.batch_no_streaming *commands
26
+ batch_result.first["body"]["self"].split('/').last.should == "0"
27
+ batch_result.last["body"]["self"].split('/').last.should == "0"
28
+ end
29
+
30
+ it "can send a 20000 item batch" do
31
+ commands = []
32
+ 20000.times do |x|
33
+ commands << [:create_node, {"name" => "Max " + x.to_s}]
34
+ end
35
+ batch_result = @neo.batch_no_streaming *commands
36
+ batch_result.first["body"]["data"]["name"].should == "Max 0"
37
+ batch_result.last["body"]["data"]["name"].should == "Max 19999"
38
+ end
39
+ end
40
+
41
+ end
@@ -566,4 +566,18 @@ describe Neography::Rest do
566
566
  end
567
567
  end
568
568
 
569
+ describe "batch unknown option" do
570
+ it "should raise Neography::UnknownBatchOptionException when bad option is passed in batch" do
571
+ batch_commands = []
572
+
573
+ batch_commands << [ :bad_option, "start person_n=node:person(ssn = '000-00-0002')
574
+ set bar1 = {foo}"]
575
+
576
+ expect {
577
+ batch_result = @neo.batch *batch_commands
578
+ }.to raise_exception Neography::UnknownBatchOptionException
579
+
580
+ end
581
+ end
582
+
569
583
  end
@@ -15,7 +15,7 @@ describe Neography::Rest do
15
15
  batch_result = @neo.batch *commands
16
16
  batch_result.first["body"]["data"]["name"].should == "Max 0"
17
17
  batch_result.last["body"]["data"]["name"].should == "Max 999"
18
- end
18
+ end
19
19
 
20
20
  it "can send a 5000 item batch" do
21
21
  commands = []
@@ -25,8 +25,27 @@ describe Neography::Rest do
25
25
  batch_result = @neo.batch *commands
26
26
  batch_result.first["body"]["self"].split('/').last.should == "0"
27
27
  batch_result.last["body"]["self"].split('/').last.should == "0"
28
- end
28
+ end
29
29
 
30
- end
30
+ it "can send a 7000 get item batch" do
31
+ commands = []
32
+ 7000.times do |x|
33
+ commands << [:get_node, 0]
34
+ end
35
+ batch_result = @neo.batch *commands
36
+ batch_result.first["body"]["self"].split('/').last.should == "0"
37
+ batch_result.last["body"]["self"].split('/').last.should == "0"
38
+ end
31
39
 
40
+ it "can send a 5000 create item batch" do
41
+ commands = []
42
+ 5000.times do |x|
43
+ commands << [:create_node, {"name" => "Max " + x.to_s}]
44
+ end
45
+ batch_result = @neo.batch *commands
46
+ batch_result.first["body"]["data"]["name"].should == "Max 0"
47
+ batch_result.last["body"]["data"]["name"].should == "Max 4999"
48
+ end
49
+
50
+ end
32
51
  end
@@ -420,7 +420,10 @@ describe Neography::Rest do
420
420
  it "can query a node from an automatic index" do
421
421
  new_node = @neo.create_node("name" => "Max")
422
422
  existing_nodes = @neo.find_node_auto_index("name:Max")
423
- existing_nodes.collect{|n| n["self"]}.include?(new_node["self"]).should be_true
423
+ existing_nodes.collect{|n| n["self"]}.include?(new_node["self"]).should be_true
424
+ # check that more complex queries are correctly handled
425
+ existing_nodes = @neo.find_node_auto_index("name:Max OR name:Max")
426
+ existing_nodes.collect{|n| n["self"]}.include?(new_node["self"]).should be_true
424
427
  end
425
428
 
426
429
  it "can get a relationship from an automatic index" do
data/spec/spec_helper.rb CHANGED
@@ -34,7 +34,7 @@ def error_response(attributes)
34
34
 
35
35
  double(
36
36
  http_header: http_header,
37
- code: attributes[:code],
37
+ status: attributes[:code],
38
38
  body: {
39
39
  message: attributes[:message],
40
40
  exception: attributes[:exception],
@@ -42,4 +42,3 @@ def error_response(attributes)
42
42
  }.reject { |k,v| v.nil? }.to_json
43
43
  )
44
44
  end
45
-
@@ -7,44 +7,49 @@ module Neography
7
7
 
8
8
  context "defaults" do
9
9
 
10
- its(:protocol) { should == 'http://' }
11
- its(:server) { should == 'localhost' }
12
- its(:port) { should == 7474 }
13
- its(:directory) { should == '' }
14
- its(:cypher_path) { should == '/cypher' }
15
- its(:gremlin_path) { should == '/ext/GremlinPlugin/graphdb/execute_script' }
16
- its(:log_file) { should == 'neography.log' }
17
- its(:log_enabled) { should == false }
18
- its(:logger) { should == nil }
19
- its(:slow_log_threshold) { should == 0 }
20
- its(:max_threads) { should == 20 }
21
- its(:authentication) { should == nil }
22
- its(:username) { should == nil }
23
- its(:password) { should == nil }
24
- its(:parser) { should == MultiJsonParser}
25
- its(:max_execution_time) { should == 6000 }
26
- its(:proxy) { should == nil }
10
+ its(:protocol) { should == 'http://' }
11
+ its(:server) { should == 'localhost' }
12
+ its(:port) { should == 7474 }
13
+ its(:directory) { should == '' }
14
+ its(:cypher_path) { should == '/cypher' }
15
+ its(:gremlin_path) { should == '/ext/GremlinPlugin/graphdb/execute_script' }
16
+ its(:log_file) { should == 'neography.log' }
17
+ its(:log_enabled) { should == false }
18
+ its(:logger) { should == nil }
19
+ its(:slow_log_threshold) { should == 0 }
20
+ its(:max_threads) { should == 20 }
21
+ its(:authentication) { should == nil }
22
+ its(:username) { should == nil }
23
+ its(:password) { should == nil }
24
+ its(:parser) { should == MultiJsonParser}
25
+ its(:max_execution_time) { should == 6000 }
26
+ its(:proxy) { should == nil }
27
+ its(:http_send_timeout) { should == 1200 }
28
+ its(:http_receive_timeout) { should == 1200 }
27
29
 
28
30
 
29
31
  it "has a hash representation" do
30
32
  expected_hash = {
31
- :protocol => 'http://',
32
- :server => 'localhost',
33
- :port => 7474,
34
- :directory => '',
35
- :cypher_path => '/cypher',
36
- :gremlin_path => '/ext/GremlinPlugin/graphdb/execute_script',
37
- :log_file => 'neography.log',
38
- :log_enabled => false,
39
- :logger => nil,
40
- :slow_log_threshold => 0,
41
- :max_threads => 20,
42
- :authentication => nil,
43
- :username => nil,
44
- :password => nil,
45
- :parser => MultiJsonParser,
46
- :max_execution_time => 6000,
47
- :proxy => nil
33
+ :protocol => 'http://',
34
+ :server => 'localhost',
35
+ :port => 7474,
36
+ :directory => '',
37
+ :cypher_path => '/cypher',
38
+ :gremlin_path => '/ext/GremlinPlugin/graphdb/execute_script',
39
+ :log_file => 'neography.log',
40
+ :log_enabled => false,
41
+ :logger => nil,
42
+ :slow_log_threshold => 0,
43
+ :max_threads => 20,
44
+ :authentication => nil,
45
+ :username => nil,
46
+ :password => nil,
47
+ :parser => MultiJsonParser,
48
+ :max_execution_time => 6000,
49
+ :proxy => nil,
50
+ :http_send_timeout => 1200,
51
+ :http_receive_timeout => 1200
52
+
48
53
  }
49
54
  config.to_hash.should == expected_hash
50
55
  end
@@ -59,8 +59,30 @@ module Neography
59
59
  }
60
60
  }
61
61
  end
62
+
63
+ context "httpclient" do
64
+ let(:httpclient) { double(:http_client) }
65
+ let(:options) do
66
+ {
67
+ :http_send_timeout => 120,
68
+ :http_receive_timeout => 100
69
+ }
70
+ end
71
+
72
+ it 'configures send/receive timeout' do
73
+ Excon.should_receive(:new).with("http://localhost:7474",
74
+ :read_timeout => 100,
75
+ :write_timeout => 120,
76
+ :persistent=>true,
77
+ :user=>nil,
78
+ :password=>nil).and_return(httpclient)
79
+ connection
80
+ end
81
+ end
62
82
  end
63
83
 
84
+
85
+
64
86
  context "string option" do
65
87
  let(:options) { "https://user:pass@somehost:8585/path" }
66
88
 
@@ -80,22 +102,22 @@ module Neography
80
102
  context "requests" do
81
103
 
82
104
  it "does a GET request" do
83
- connection.client.should_receive(:get).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
105
+ connection.client.should_receive(:request).with(:method => :get, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
84
106
  connection.get("/node/bar")
85
107
  end
86
108
 
87
109
  it "does a POST request" do
88
- connection.client.should_receive(:post).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
110
+ connection.client.should_receive(:request).with(:method => :post, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
89
111
  connection.post("/node/bar")
90
112
  end
91
113
 
92
114
  it "does a PUT request" do
93
- connection.client.should_receive(:put).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
115
+ connection.client.should_receive(:request).with(:method => :put, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
94
116
  connection.put("/node/bar")
95
117
  end
96
118
 
97
119
  it "does a DELETE request" do
98
- connection.client.should_receive(:delete).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
120
+ connection.client.should_receive(:request).with(:method => :delete, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
99
121
  connection.delete("/node/bar")
100
122
  end
101
123
 
@@ -114,19 +136,20 @@ module Neography
114
136
  "foo",
115
137
  "bar") { double.as_null_object }
116
138
 
117
- connection.client.should_receive(:get).with(
118
- "http://localhost:7474/db/data/node/bar", nil, nil
119
- ) { double.as_null_object }
139
+ connection.client.should_receive(:request).with(
140
+ :method => :get, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
120
141
 
121
142
  connection.get("/node/bar")
122
143
  end
123
144
  end
124
145
 
125
146
  it "adds the User-Agent to the headers" do
126
- connection.client.should_receive(:get).with(
127
- "http://localhost:7474/db/data/node/bar",
128
- nil, { "User-Agent" => "Neography/#{Neography::VERSION}", "X-Stream"=>true, "max-execution-time"=>6000}
129
- ) { double.as_null_object }
147
+ connection.client.should_receive(:request).with(
148
+ hash_including(
149
+ {:method => :get, :path => "/db/data/node/bar", :body => nil,
150
+ :headers => {"User-Agent" => "Neography/#{Neography::VERSION}", "X-Stream"=>true, "max-execution-time" => 6000}}
151
+ )
152
+ ) { double.as_null_object }
130
153
 
131
154
  connection.get("/node/bar", :headers => {})
132
155
  end
@@ -135,7 +158,7 @@ module Neography
135
158
 
136
159
  it "raises NodeNotFoundException" do
137
160
  response = error_response(code: 404, message: "a message", exception: "NodeNotFoundException")
138
- connection.client.stub(:get).and_return(response)
161
+ connection.client.stub(:request).and_return(response)
139
162
  expect {
140
163
  connection.get("/node/bar")
141
164
  }.to raise_error NodeNotFoundException
@@ -143,7 +166,7 @@ module Neography
143
166
 
144
167
  it "raises OperationFailureException" do
145
168
  response = error_response(code: 409, message: "a message", exception: "OperationFailureException")
146
- connection.client.stub(:get).and_return(response)
169
+ connection.client.stub(:request).and_return(response)
147
170
  expect {
148
171
  connection.get("/node/bar")
149
172
  }.to raise_error OperationFailureException
@@ -151,7 +174,7 @@ module Neography
151
174
 
152
175
  it "raises PropertyValueException" do
153
176
  response = error_response(code: 400, message: "a message", exception: "PropertyValueException")
154
- connection.client.stub(:get).and_return(response)
177
+ connection.client.stub(:request).and_return(response)
155
178
  expect {
156
179
  connection.get("/node/bar")
157
180
  }.to raise_error PropertyValueException
@@ -159,7 +182,7 @@ module Neography
159
182
 
160
183
  it "raises NoSuchPropertyException" do
161
184
  response = error_response(code: 404, message: "a message", exception: "NoSuchPropertyException")
162
- connection.client.stub(:get).and_return(response)
185
+ connection.client.stub(:request).and_return(response)
163
186
  expect {
164
187
  connection.get("/node/bar")
165
188
  }.to raise_error NoSuchPropertyException
@@ -167,7 +190,7 @@ module Neography
167
190
 
168
191
  it "raises RelationshipNotFoundException" do
169
192
  response = error_response(code: 404, message: "a message", exception: "RelationshipNotFoundException")
170
- connection.client.stub(:get).and_return(response)
193
+ connection.client.stub(:request).and_return(response)
171
194
  expect {
172
195
  connection.get("/node/bar")
173
196
  }.to raise_error RelationshipNotFoundException
@@ -175,7 +198,7 @@ module Neography
175
198
 
176
199
  it "raises BadInputException" do
177
200
  response = error_response(code: 400, message: "a message", exception: "BadInputException")
178
- connection.client.stub(:get).and_return(response)
201
+ connection.client.stub(:request).and_return(response)
179
202
  expect {
180
203
  connection.get("/node/bar")
181
204
  }.to raise_error BadInputException
@@ -183,7 +206,7 @@ module Neography
183
206
 
184
207
  it "raises UnauthorizedError" do
185
208
  response = error_response(code: 401)
186
- connection.client.stub(:get).and_return(response)
209
+ connection.client.stub(:request).and_return(response)
187
210
  expect {
188
211
  connection.get("/node/bar")
189
212
  }.to raise_error UnauthorizedError
@@ -191,7 +214,7 @@ module Neography
191
214
 
192
215
  it "raises NeographyError in all other cases" do
193
216
  response = error_response(code: 418, message: "I'm a teapot.")
194
- connection.client.stub(:get).and_return(response)
217
+ connection.client.stub(:request).and_return(response)
195
218
  expect {
196
219
  connection.get("/node/bar")
197
220
  }.to raise_error NeographyError
@@ -199,7 +222,7 @@ module Neography
199
222
 
200
223
  it "raises BadInputException" do
201
224
  response = error_response(code: 500, message: "a message", exception: "JsonParseException")
202
- connection.client.stub(:get).and_return(response)
225
+ connection.client.stub(:request).and_return(response)
203
226
  expect {
204
227
  connection.get("/node/bar")
205
228
  }.to raise_error NeographyError
@@ -208,52 +231,54 @@ module Neography
208
231
  end
209
232
 
210
233
  context "query logging" do
211
- before do
212
- @logger = Logger.new(nil)
213
- connection.logger = @logger
214
- connection.log_enabled = true
215
- end
216
234
 
217
- let(:expected_response) {"expected_response"}
235
+ subject(:connection) do
218
236
 
219
- let(:request_body) { {key1: :val1} }
237
+ Connection.new({
238
+ :logger => Logger.new(nil),
239
+ :log_enabled => true
240
+ })
241
+
242
+ let(:expected_response) {"expected_response"}
220
243
 
221
- it "should log query" do
222
- connection.should_receive(:log).with("/db/data/node/bar", request_body).once
223
- connection.get("/node/bar", {body: request_body})
224
- end
244
+ let(:request_body) { {key1: :val1} }
225
245
 
226
- it "should return original response" do
227
- connection.stub(:evaluate_response).and_return expected_response
228
- connection.get("/node/bar").should eq expected_response
229
- end
246
+ it "should log query" do
247
+ connection.should_receive(:log).with("/db/data/node/bar", request_body).once
248
+ connection.get("/node/bar", {body: request_body})
249
+ end
230
250
 
231
- describe "slow_log_threshold" do
232
- before do
251
+ it "should return original response" do
233
252
  connection.stub(:evaluate_response).and_return expected_response
253
+ connection.get("/node/bar").should eq expected_response
234
254
  end
235
255
 
236
- context "default value" do
237
- it "should have output" do
238
- @logger.should_receive(:info).once
256
+ describe "slow_log_threshold" do
257
+ before do
258
+ connection.stub(:evaluate_response).and_return expected_response
239
259
  end
240
- end
241
260
 
242
- context "high value" do
243
- before { connection.slow_log_threshold = 100_000 }
244
- it "should not have output" do
245
- @logger.should_not_receive(:info)
261
+ context "default value" do
262
+ it "should have output" do
263
+ @logger.should_receive(:info).once
264
+ end
246
265
  end
247
- end
248
266
 
249
- after do
250
- connection.get("/node/bar", {body: request_body})
267
+ context "high value" do
268
+ before { connection.slow_log_threshold = 100_000 }
269
+ it "should not have output" do
270
+ @logger.should_not_receive(:info)
271
+ end
272
+ end
273
+
274
+ after do
275
+ connection.get("/node/bar", {body: request_body})
276
+ end
251
277
  end
252
278
  end
253
-
254
279
  end
255
280
  end
256
281
  end
257
282
  end
258
283
 
259
- class Foo; end
284
+ class Foo; end
@@ -24,6 +24,10 @@ module Neography
24
24
  it "finds by query if no value passed to #find_or_query" do
25
25
  subject.connection.should_receive(:get).with("/index/auto/node/?query=some_query")
26
26
  subject.find_node_auto_index("some_query")
27
+
28
+ query = "some_query AND another_one"
29
+ subject.connection.should_receive(:get).with("/index/auto/node/?query=#{URI.encode(query)}")
30
+ subject.find_node_auto_index(query)
27
31
  end
28
32
 
29
33
  it "finds by key and value" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neography
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max De Marzi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-27 00:00:00.000000000 Z
11
+ date: 2014-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -53,19 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: httpclient
56
+ name: excon
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.3.3
61
+ version: 0.33.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.3.3
68
+ version: 0.33.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: json
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -217,6 +217,7 @@ files:
217
217
  - spec/integration/parsing_spec.rb
218
218
  - spec/integration/performance_spec.rb
219
219
  - spec/integration/relationship_spec.rb
220
+ - spec/integration/rest_batch_no_streaming_spec.rb
220
221
  - spec/integration/rest_batch_spec.rb
221
222
  - spec/integration/rest_batch_streaming_spec.rb
222
223
  - spec/integration/rest_bulk_spec.rb
@@ -303,6 +304,7 @@ test_files:
303
304
  - spec/integration/parsing_spec.rb
304
305
  - spec/integration/performance_spec.rb
305
306
  - spec/integration/relationship_spec.rb
307
+ - spec/integration/rest_batch_no_streaming_spec.rb
306
308
  - spec/integration/rest_batch_spec.rb
307
309
  - spec/integration/rest_batch_streaming_spec.rb
308
310
  - spec/integration/rest_bulk_spec.rb