neography 1.4.1 → 1.5.0

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.
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