neo4j-ruby-driver 6.2.1.beta.1 → 6.2.1.beta.2

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/neo4j/driver/bolt/connection.rb +72 -35
  3. data/lib/neo4j/driver/bolt/handshake.rb +14 -10
  4. data/lib/neo4j/driver/bolt/message/failure.rb +8 -8
  5. data/lib/neo4j/driver/bolt/message/record.rb +1 -1
  6. data/lib/neo4j/driver/bolt/message.rb +1 -1
  7. data/lib/neo4j/driver/bolt/pool.rb +2 -2
  8. data/lib/neo4j/driver/bolt/protocol/v44.rb +1 -1
  9. data/lib/neo4j/driver/bolt/record_buffer.rb +15 -8
  10. data/lib/neo4j/driver/bolt/wire.rb +4 -4
  11. data/lib/neo4j/driver/direct/connection_provider.rb +5 -1
  12. data/lib/neo4j/driver/driver.rb +2 -2
  13. data/lib/neo4j/driver/exceptions/no_such_record_exception.rb +1 -1
  14. data/lib/neo4j/driver/internal/duration_normalizer.rb +4 -2
  15. data/lib/neo4j/driver/internal/validator.rb +7 -3
  16. data/lib/neo4j/driver/packstream/markers.rb +11 -11
  17. data/lib/neo4j/driver/packstream/packer.rb +5 -3
  18. data/lib/neo4j/driver/packstream/unpacker.rb +6 -4
  19. data/lib/neo4j/driver/record.rb +3 -9
  20. data/lib/neo4j/driver/result.rb +12 -12
  21. data/lib/neo4j/driver/routing/load_balancer.rb +29 -13
  22. data/lib/neo4j/driver/routing/routing_table.rb +1 -1
  23. data/lib/neo4j/driver/session.rb +72 -70
  24. data/lib/neo4j/driver/summary/database_info.rb +1 -1
  25. data/lib/neo4j/driver/summary/plan.rb +1 -1
  26. data/lib/neo4j/driver/summary/result_summary.rb +2 -0
  27. data/lib/neo4j/driver/transaction.rb +13 -10
  28. data/lib/neo4j/driver/types/duration.rb +6 -6
  29. data/lib/neo4j/driver/types/entity.rb +40 -0
  30. data/lib/neo4j/driver/types/local_date_time.rb +46 -21
  31. data/lib/neo4j/driver/types/local_time.rb +13 -5
  32. data/lib/neo4j/driver/types/node.rb +5 -14
  33. data/lib/neo4j/driver/types/offset_time.rb +16 -9
  34. data/lib/neo4j/driver/types/path.rb +2 -2
  35. data/lib/neo4j/driver/types/point.rb +4 -4
  36. data/lib/neo4j/driver/types/relationship.rb +6 -15
  37. data/lib/neo4j/driver/types/temporal_value.rb +3 -2
  38. data/lib/neo4j/driver/types/unbound_relationship.rb +5 -10
  39. data/lib/neo4j/driver/version.rb +1 -1
  40. data/lib/neo4j/driver.rb +0 -1
  41. metadata +4 -72
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17d5f6af602136557ee743576eedcfc9a26f6a2a5ca1cc2ed2893157607c3aab
4
- data.tar.gz: 744145fd8d940d40edcce5d329b654fb1ad705edfa4a142df40403840c31f93b
3
+ metadata.gz: 02167af06d7572708bb866aa09a7cf03492c3ea5ff78601db252a874e30c0f16
4
+ data.tar.gz: 5321a39b13e65469393f5485646987e178e68f2bcc9527884a087e64775096e4
5
5
  SHA512:
6
- metadata.gz: 358d78b67822c5e1db7843d24a70ad5b99b26fd8be05c3390e1da030239d12fa0fc03c9ceacd102a00e7901c9f2b71055f621a78f37a5a1a0f8d62eb9ea9dd8b
7
- data.tar.gz: 2727a0fa17d00511c1a31a72219855d5a104c6ec3394875101aef210484bfe42931fe0b8eb3c8de520a462c279133d5e162552db8974982a435aa84bbb642f64
6
+ metadata.gz: 2fb5b47bb808deadef7fcd939ab829e0e5a9b7f13ae7808a0b128a55236b874b112d9385e471f3bb098032a8185bcc039280a692d2d0e6aed213c843045cf420
7
+ data.tar.gz: 62c171b7b0a7f5efafa4905ffc6b200f1d3d59bd06a2f4d24fdedfaefcd61813239fcb784e5eb4b844d085147594f73f5731571d320dfea1c9dc2d1b3d69bca3
@@ -15,7 +15,7 @@ module Neo4j
15
15
  # everything into the shared inbox queue for fetch_response to drain.
16
16
  # (A streaming request could register a record-routing handler instead.)
17
17
  ResponseCollector = Struct.new(:inbox) do
18
- def on_record(message) = inbox.push(message)
18
+ def on_record(message) = inbox.push(message)
19
19
  def on_success(message) = inbox.push(message)
20
20
  def on_failure(message) = inbox.push(message)
21
21
  def on_ignored(message) = inbox.push(message)
@@ -96,8 +96,8 @@ module Neo4j
96
96
  # stopped on close. Drives #advance and routes via the wire.
97
97
  @reader = nil
98
98
  @reader_mutex = Mutex.new
99
- @reader_cv = ConditionVariable.new # wakes the reader: a reply is expected
100
- @quiescent_cv = ConditionVariable.new # wakes drainers: in_flight hit 0
99
+ @reader_cv = ConditionVariable.new # wakes the reader: a reply is expected
100
+ @quiescent_cv = ConditionVariable.new # wakes drainers: in_flight hit 0
101
101
  @reader_stopped = false
102
102
  @broken_error = nil # set by failure fan-out; raised to inbox poppers
103
103
  @server_version = nil
@@ -129,25 +129,23 @@ module Neo4j
129
129
  # sharing one budget) wins over this connection's own.
130
130
  @read_deadline = deadline || acquisition_deadline
131
131
  resolved_addresses.each do |host, port|
132
- begin
133
- open_socket(host, port)
134
- perform_handshake
135
- perform_hello
136
- @read_deadline = nil
137
- @created_at = current_monotonic
138
- # Connection is READY: hand steady-state reads to the dedicated
139
- # reader. (Handshake/hello above read synchronously via
140
- # fetch_response, so a failed connect never spawns a reader.)
141
- start_reader
142
- return self
143
- rescue Exceptions::AuthenticationException
144
- # Auth is the same regardless of which address we hit — fail fast.
145
- discard_socket
146
- raise
147
- rescue Exceptions::ServiceUnavailableException, IOError, SystemCallError => e
148
- last_error = e
149
- discard_socket
150
- end
132
+ open_socket(host, port)
133
+ perform_handshake
134
+ perform_hello
135
+ @read_deadline = nil
136
+ @created_at = current_monotonic
137
+ # Connection is READY: hand steady-state reads to the dedicated
138
+ # reader. (Handshake/hello above read synchronously via
139
+ # fetch_response, so a failed connect never spawns a reader.)
140
+ start_reader
141
+ return self
142
+ rescue Exceptions::AuthenticationException
143
+ # Auth is the same regardless of which address we hit — fail fast.
144
+ discard_socket
145
+ raise
146
+ rescue Exceptions::ServiceUnavailableException, IOError, SystemCallError => e
147
+ last_error = e
148
+ discard_socket
151
149
  end
152
150
 
153
151
  raise Exceptions::ServiceUnavailableException, 'No addresses to connect to' if last_error.nil?
@@ -246,12 +244,21 @@ module Neo4j
246
244
  begin
247
245
  @wire&.enqueue(Message.goodbye, @collector)
248
246
  bytes = @wire&.take_outbound
249
- @write_mutex.synchronize { @socket.write(bytes); @socket.flush } if bytes && !bytes.empty?
247
+ if bytes && !bytes.empty?
248
+ @write_mutex.synchronize do
249
+ @socket.write(bytes)
250
+ @socket.flush
251
+ end
252
+ end
250
253
  rescue StandardError
251
254
  # closing anyway
252
255
  end
253
256
  stop_reader
254
- @socket&.close rescue nil
257
+ begin
258
+ @socket&.close
259
+ rescue StandardError
260
+ nil
261
+ end
255
262
  end
256
263
 
257
264
  def closed?
@@ -521,7 +528,7 @@ module Neo4j
521
528
  response = fetch_response
522
529
  case response
523
530
  when Message::Success then break # PULL summary — end of stream
524
- when Message::Record then row ||= fields.zip(response.fields).to_h
531
+ when Message::Record then row ||= fields.zip(response.fields).to_h
525
532
  else response.assert_success! # FAILURE / IGNORED — raises
526
533
  end
527
534
  end
@@ -663,7 +670,11 @@ module Neo4j
663
670
 
664
671
  def discard_socket
665
672
  stop_reader
666
- @socket&.close rescue nil
673
+ begin
674
+ @socket&.close
675
+ rescue StandardError
676
+ nil
677
+ end
667
678
  @socket = nil
668
679
  # Reset all per-attempt I/O state so a retry on the next address (or a
669
680
  # later reset!/drain loop) doesn't carry a phantom in-flight request or
@@ -709,7 +720,8 @@ module Neo4j
709
720
  end
710
721
  rescue IOError, SystemCallError => e
711
722
  fail_broken(Exceptions::ServiceUnavailableException.new(
712
- "Connection to #{@address || @uri} broken: #{e.class}: #{e.message}"))
723
+ "Connection to #{@address || @uri} broken: #{e.class}: #{e.message}"
724
+ ))
713
725
  end
714
726
 
715
727
  # The dedicated reader: the sole socket reader for this connection's
@@ -779,10 +791,18 @@ module Neo4j
779
791
  # Wake the parked reader (@reader_cv) and any drainer blocked in
780
792
  # #wait_quiescent (@quiescent_cv) — stopping is a terminal transition
781
793
  # they must observe, else a concurrent reset!/fetch_all/alive? hangs.
782
- @reader_mutex.synchronize { @reader_stopped = true; @reader_cv.broadcast; @quiescent_cv.broadcast }
794
+ @reader_mutex.synchronize do
795
+ @reader_stopped = true
796
+ @reader_cv.broadcast
797
+ @quiescent_cv.broadcast
798
+ end
783
799
  return unless reader
784
800
 
785
- @socket&.close rescue nil
801
+ begin
802
+ @socket&.close
803
+ rescue StandardError
804
+ nil
805
+ end
786
806
  reader.join unless reader == Thread.current
787
807
  end
788
808
 
@@ -814,7 +834,11 @@ module Neo4j
814
834
  end
815
835
 
816
836
  def mark_closed_broken
817
- @socket&.close rescue nil
837
+ begin
838
+ @socket&.close
839
+ rescue StandardError
840
+ nil
841
+ end
818
842
  @closed = true
819
843
  fire_on_close
820
844
  end
@@ -926,10 +950,16 @@ module Neo4j
926
950
  # test_should_fail_when_acquisition_timeout_is_reached_first, where
927
951
  # acquisition 2s < connection 720s).
928
952
  connect_timeout = [timeout&.to_f, remaining_read_budget].compact.min
929
- tcp_socket = connect_timeout ? Socket.tcp(bare_host, port, connect_timeout: connect_timeout) : TCPSocket.new(bare_host, port)
953
+ tcp_socket = if connect_timeout
954
+ Socket.tcp(bare_host, port,
955
+ connect_timeout: connect_timeout)
956
+ else
957
+ TCPSocket.new(bare_host, port)
958
+ end
930
959
  rescue SystemCallError, SocketError => e
931
960
  raise Exceptions::ServiceUnavailableException,
932
- "Unable to connect to #{format_address(host, port)}, ensure the database is running and that there is a working network connection to it. (#{e.message})"
961
+ "Unable to connect to #{format_address(host,
962
+ port)}, ensure the database is running and that there is a working network connection to it. (#{e.message})"
933
963
  else
934
964
  @address = format_address(host, port)
935
965
  tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
@@ -961,11 +991,19 @@ module Neo4j
961
991
  ssl.post_connection_check(hostname) if tls.verify_hostname?
962
992
  ssl
963
993
  rescue OpenSSL::SSL::SSLError => e
964
- tcp_socket.close rescue nil
994
+ begin
995
+ tcp_socket.close
996
+ rescue StandardError
997
+ nil
998
+ end
965
999
  raise Exceptions::SecurityException,
966
1000
  "TLS handshake to #{format_address(hostname, port)} failed: #{e.message}"
967
1001
  rescue SystemCallError, IOError => e
968
- tcp_socket.close rescue nil
1002
+ begin
1003
+ tcp_socket.close
1004
+ rescue StandardError
1005
+ nil
1006
+ end
969
1007
  raise Exceptions::ServiceUnavailableException,
970
1008
  "Connection lost during TLS handshake to #{format_address(hostname, port)}: #{e.message}"
971
1009
  end
@@ -1047,7 +1085,6 @@ module Neo4j
1047
1085
  seconds = hints && hints[:'connection.recv_timeout_seconds']
1048
1086
  @recv_timeout = seconds if seconds&.positive?
1049
1087
  end
1050
-
1051
1088
  end
1052
1089
  end
1053
1090
  end
@@ -38,9 +38,9 @@ module Neo4j
38
38
  # DISCARD_ALL, single-DB, no routing in HELLO).
39
39
  SLOTS = [
40
40
  MANIFEST_SENTINEL,
41
- 0x00_08_08_05, # 5.0–5.8
42
- 0x00_02_04_04, # 4.2–4.4
43
- 0x00_00_00_03 # 3.0
41
+ 0x00_08_08_05, # 5.0–5.8
42
+ 0x00_02_04_04, # 4.2–4.4
43
+ 0x00_00_00_03 # 3.0
44
44
  ].freeze
45
45
 
46
46
  # Versions we'd accept from a manifest, highest-preference first.
@@ -91,15 +91,19 @@ module Neo4j
91
91
  @socket.flush
92
92
 
93
93
  server_reply = read_int32!('Server closed the connection during handshake')
94
- raise Exceptions::ServiceUnavailableException,
95
- 'Server does not support any of the proposed Bolt versions' if server_reply.zero?
94
+ if server_reply.zero?
95
+ raise Exceptions::ServiceUnavailableException,
96
+ 'Server does not support any of the proposed Bolt versions'
97
+ end
96
98
 
97
99
  # An HTTP server on the Bolt port replies with an HTTP status
98
100
  # line; its first four bytes spell "HTTP". Mirror Java's helpful
99
101
  # error instead of reporting a bogus protocol version.
100
- raise Exceptions::ClientException,
101
- 'Server responded HTTP. Make sure you are not trying to connect to the http ' \
102
- 'endpoint (HTTP defaults to port 7474 whereas BOLT defaults to port 7687)' if server_reply == HTTP_REPLY
102
+ if server_reply == HTTP_REPLY
103
+ raise Exceptions::ClientException,
104
+ 'Server responded HTTP. Make sure you are not trying to connect to the http ' \
105
+ 'endpoint (HTTP defaults to port 7474 whereas BOLT defaults to port 7687)'
106
+ end
103
107
 
104
108
  server_reply == MANIFEST_SENTINEL ? negotiate_manifest : server_reply
105
109
  end
@@ -170,8 +174,8 @@ module Neo4j
170
174
  buf = String.new(encoding: Encoding::BINARY)
171
175
  while buf.bytesize < n
172
176
  case (chunk = @socket.read_nonblock(n - buf.bytesize, exception: false))
173
- when :wait_readable then (@socket.wait_readable(remaining_budget) || return)
174
- when :wait_writable then (@socket.wait_writable(remaining_budget) || return)
177
+ when :wait_readable then @socket.wait_readable(remaining_budget) || return
178
+ when :wait_writable then @socket.wait_writable(remaining_budget) || return
175
179
  when nil then return
176
180
  else buf << chunk
177
181
  end
@@ -18,14 +18,14 @@ module Neo4j
18
18
  # Code-prefix → driver exception class. Order matters: more specific
19
19
  # patterns must come first.
20
20
  EXCEPTION_FOR_CODE = [
21
- [%r{^Neo\.ClientError\.Security\.Unauthorized}, Exceptions::AuthenticationException],
22
- [%r{^Neo\.ClientError\.Security\.AuthorizationExpired}, Exceptions::AuthorizationExpiredException],
23
- [%r{^Neo\.ClientError\.Security\.TokenExpired}, Exceptions::TokenExpiredException],
24
- [%r{^Neo\.ClientError\.Security}, Exceptions::SecurityException],
25
- [%r{^Neo\.ClientError\.Database\.DatabaseNotFound}, Exceptions::FatalDiscoveryException],
26
- [%r{^Neo\.ClientError}, Exceptions::ClientException],
27
- [%r{^Neo\.TransientError}, Exceptions::TransientException],
28
- [%r{^Neo\.DatabaseError}, Exceptions::DatabaseException]
21
+ [/^Neo\.ClientError\.Security\.Unauthorized/, Exceptions::AuthenticationException],
22
+ [/^Neo\.ClientError\.Security\.AuthorizationExpired/, Exceptions::AuthorizationExpiredException],
23
+ [/^Neo\.ClientError\.Security\.TokenExpired/, Exceptions::TokenExpiredException],
24
+ [/^Neo\.ClientError\.Security/, Exceptions::SecurityException],
25
+ [/^Neo\.ClientError\.Database\.DatabaseNotFound/, Exceptions::FatalDiscoveryException],
26
+ [/^Neo\.ClientError/, Exceptions::ClientException],
27
+ [/^Neo\.TransientError/, Exceptions::TransientException],
28
+ [/^Neo\.DatabaseError/, Exceptions::DatabaseException]
29
29
  ].freeze
30
30
 
31
31
  # Two `TransientError` codes the server may send that are actually
@@ -17,7 +17,7 @@ module Neo4j
17
17
  end
18
18
 
19
19
  def assert_success!
20
- raise Exceptions::ClientException, "Unexpected RECORD where SUCCESS was expected"
20
+ raise Exceptions::ClientException, 'Unexpected RECORD where SUCCESS was expected'
21
21
  end
22
22
 
23
23
  # A RECORD is a streamed row, not a request summary — it never
@@ -27,7 +27,7 @@ module Neo4j
27
27
  FAILURE = 0x7F
28
28
 
29
29
  class << self
30
- # Note: HELLO message building is now handled by protocol-specific handlers
30
+ # NOTE: HELLO message building is now handled by protocol-specific handlers
31
31
  # This method kept for backward compatibility but shouldn't be used directly
32
32
  def hello(user_agent:, auth:, routing: nil)
33
33
  extra = { user_agent: user_agent }
@@ -141,8 +141,8 @@ module Neo4j
141
141
  bump(created: -1, leased: -1)
142
142
  end
143
143
 
144
- def shutdown(&block)
145
- @stack.shutdown(&block)
144
+ def shutdown(&)
145
+ @stack.shutdown(&)
146
146
  # Every connection is closed now — keep the metrics truthful so a
147
147
  # post-close snapshot reports nothing live.
148
148
  @metrics_lock.synchronize { @created = @leased = 0 }
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Neo4j
4
4
  module Driver
@@ -39,12 +39,12 @@ module Neo4j
39
39
  @low_watermark = low_watermark || [@high_watermark / 2, 1].max
40
40
  @mutex = Mutex.new
41
41
  @cv = ConditionVariable.new
42
- @records = [] # incrementally filled by the reader, drained by the cursor
43
- @has_more = true # server may have more records for this stream
44
- @pull_in_flight = true # the first PULL is pipelined with RUN — promise unfulfilled
45
- @ended = false # terminal SUCCESS/IGNORED seen → no more records
46
- @error = nil # stream failed; re-raised to the cursor after buffered records
47
- @summary = nil # terminating SUCCESS metadata
42
+ @records = [] # incrementally filled by the reader, drained by the cursor
43
+ @has_more = true # server may have more records for this stream
44
+ @pull_in_flight = true # the first PULL is pipelined with RUN — promise unfulfilled
45
+ @ended = false # terminal SUCCESS/IGNORED seen → no more records
46
+ @error = nil # stream failed; re-raised to the cursor after buffered records
47
+ @summary = nil # terminating SUCCESS metadata
48
48
  end
49
49
 
50
50
  # --- Producer (reader) side -----------------------------------------
@@ -52,7 +52,10 @@ module Neo4j
52
52
  # Append a decoded record and wake a cursor parked in #await. Never blocks
53
53
  # (unbounded); the cursor's watermark bounds how much the server ships.
54
54
  def push_record(record)
55
- @mutex.synchronize { @records.push(record); @cv.broadcast }
55
+ @mutex.synchronize do
56
+ @records.push(record)
57
+ @cv.broadcast
58
+ end
56
59
  end
57
60
 
58
61
  # The current batch's terminal SUCCESS arrived — resolve the promise.
@@ -60,7 +63,11 @@ module Neo4j
60
63
  # so the cursor may issue the next once it drains past the low watermark.
61
64
  # Wake a cursor parked in #await waiting for exactly this.
62
65
  def batch_complete(has_more:)
63
- @mutex.synchronize { @has_more = has_more; @pull_in_flight = false; @cv.broadcast }
66
+ @mutex.synchronize do
67
+ @has_more = has_more
68
+ @pull_in_flight = false
69
+ @cv.broadcast
70
+ end
64
71
  end
65
72
 
66
73
  # Final batch (terminating SUCCESS without has_more, or IGNORED): stash the
@@ -34,9 +34,9 @@ module Neo4j
34
34
  @protocol = protocol
35
35
  @packer = PackStream::Packer.new(@protocol)
36
36
  @protocol.configure_packer(@packer)
37
- @outbound = binary_string # consumer-only (enqueue/take_outbound)
38
- @inbound = binary_string # reader-only: received bytes not yet parsed
39
- @message = binary_string # reader-only: chunks of the in-progress message
37
+ @outbound = binary_string # consumer-only (enqueue/take_outbound)
38
+ @inbound = binary_string # reader-only: received bytes not yet parsed
39
+ @message = binary_string # reader-only: chunks of the in-progress message
40
40
  # Response-ordering FIFO. Bolt replies in request order, so each sent
41
41
  # request pushes the handler that will receive its response(s); the
42
42
  # front handler always owns the next reply. A handler is any response
@@ -187,7 +187,7 @@ module Neo4j
187
187
  def register_hydration_handlers(unpacker)
188
188
  unpacker.register_hydration_handler(Message::SUCCESS) { |fields| Message::Success.new(fields[0] || {}) }
189
189
  unpacker.register_hydration_handler(Message::FAILURE) { |fields| Message::Failure.new(fields[0] || {}) }
190
- unpacker.register_hydration_handler(Message::RECORD) { |fields| Message::Record.new(fields[0] || []) }
190
+ unpacker.register_hydration_handler(Message::RECORD) { |fields| Message::Record.new(fields[0] || []) }
191
191
  unpacker.register_hydration_handler(Message::IGNORED) { |_| Message::Ignored.new }
192
192
 
193
193
  # Signature 0x4E - Node
@@ -183,7 +183,11 @@ module Neo4j
183
183
 
184
184
  def close
185
185
  @closed = true
186
- @pool&.shutdown { |conn| conn.close rescue nil }
186
+ @pool&.shutdown do |conn|
187
+ conn.close
188
+ rescue StandardError
189
+ nil
190
+ end
187
191
  end
188
192
 
189
193
  private
@@ -46,13 +46,13 @@ module Neo4j
46
46
 
47
47
  begin
48
48
  result = yield session
49
- rescue => block_error
49
+ rescue StandardError => e
50
50
  # Block raised; preserve as primary, attach close-time failures
51
51
  # as suppressed (Java try-with-resources semantics).
52
52
  begin
53
53
  session.close
54
54
  rescue Exceptions::Neo4jException => close_error
55
- block_error.add_suppressed(close_error) if block_error.respond_to?(:add_suppressed)
55
+ e.add_suppressed(close_error) if e.respond_to?(:add_suppressed)
56
56
  end
57
57
  raise
58
58
  else
@@ -6,7 +6,7 @@ module Neo4j
6
6
  class NoSuchRecordException < RuntimeError
7
7
  EMPTY = 'Cannot retrieve a single record, because this result is empty.'
8
8
  TOO_MANY = 'Expected a result with a single record, but this result ' \
9
- 'contains at least one more. Ensure your query returns only one record.'
9
+ 'contains at least one more. Ensure your query returns only one record.'
10
10
  NO_MORE = 'No more records'
11
11
  NO_PEEK_PAST = 'Cannot peek past the last record'
12
12
 
@@ -14,8 +14,10 @@ module Neo4j
14
14
  # Check the sign before rounding: a tiny negative timeout
15
15
  # (e.g. -0.4ms) would otherwise round to 0 and slip through.
16
16
  ms = timeout.to_f * 1000
17
- raise Exceptions::ClientException,
18
- "Transaction timeout must not be negative, but was #{ms}ms" if ms.negative?
17
+ if ms.negative?
18
+ raise Exceptions::ClientException,
19
+ "Transaction timeout must not be negative, but was #{ms}ms"
20
+ end
19
21
 
20
22
  ms.round
21
23
  end
@@ -16,6 +16,7 @@ module Neo4j
16
16
 
17
17
  def self.require_non_nil!(obj, message = nil)
18
18
  raise ArgumentError, [message, "can't be nil"].compact.join(' ') if obj.nil?
19
+
19
20
  obj
20
21
  end
21
22
 
@@ -24,14 +25,17 @@ module Neo4j
24
25
  # object carries its own text, so only bare strings are checked.
25
26
  def self.require_query_text!(query)
26
27
  raise ArgumentError, 'Cypher query text should not be null' if query.nil?
27
- raise ArgumentError, 'Cypher query text should not be an empty string' if query.is_a?(String) && query.strip.empty?
28
+ if query.is_a?(String) && query.strip.empty?
29
+ raise ArgumentError,
30
+ 'Cypher query text should not be an empty string'
31
+ end
28
32
 
29
33
  query
30
34
  end
31
35
 
32
36
  def self.require_non_nil_credentials!(username, password)
33
- require_non_nil! username, "Username"
34
- require_non_nil! password, "Password"
37
+ require_non_nil! username, 'Username'
38
+ require_non_nil! password, 'Password'
35
39
  end
36
40
  end
37
41
  end
@@ -7,37 +7,37 @@ module Neo4j
7
7
  # See https://neo4j.com/docs/bolt/current/packstream/ for the full table.
8
8
  module Markers
9
9
  TINY_STRING = 0x80
10
- TINY_LIST = 0x90
11
- TINY_MAP = 0xA0
10
+ TINY_LIST = 0x90
11
+ TINY_MAP = 0xA0
12
12
  TINY_STRUCT = 0xB0
13
13
 
14
- NULL = 0xC0
14
+ NULL = 0xC0
15
15
  FLOAT_64 = 0xC1
16
- FALSE = 0xC2
17
- TRUE = 0xC3
16
+ BOOLEAN_FALSE = 0xC2
17
+ BOOLEAN_TRUE = 0xC3
18
18
 
19
- INT_8 = 0xC8
19
+ INT_8 = 0xC8
20
20
  INT_16 = 0xC9
21
21
  INT_32 = 0xCA
22
22
  INT_64 = 0xCB
23
23
 
24
- BYTES_8 = 0xCC
24
+ BYTES_8 = 0xCC
25
25
  BYTES_16 = 0xCD
26
26
  BYTES_32 = 0xCE
27
27
 
28
- STRING_8 = 0xD0
28
+ STRING_8 = 0xD0
29
29
  STRING_16 = 0xD1
30
30
  STRING_32 = 0xD2
31
31
 
32
- LIST_8 = 0xD4
32
+ LIST_8 = 0xD4
33
33
  LIST_16 = 0xD5
34
34
  LIST_32 = 0xD6
35
35
 
36
- MAP_8 = 0xD8
36
+ MAP_8 = 0xD8
37
37
  MAP_16 = 0xD9
38
38
  MAP_32 = 0xDA
39
39
 
40
- STRUCT_8 = 0xDC
40
+ STRUCT_8 = 0xDC
41
41
  STRUCT_16 = 0xDD
42
42
 
43
43
  # PackStream V2 (Bolt 6.1+): a UUID is a top-level value — the marker
@@ -110,7 +110,7 @@ module Neo4j
110
110
  end
111
111
 
112
112
  def pack_boolean(value)
113
- @buffer << [value ? TRUE : FALSE].pack('C')
113
+ @buffer << [value ? BOOLEAN_TRUE : BOOLEAN_FALSE].pack('C')
114
114
  end
115
115
 
116
116
  def pack_integer(value)
@@ -246,10 +246,12 @@ module Neo4j
246
246
  # matching hydration handlers in Bolt::Connection.
247
247
  if @use_utc_datetime
248
248
  epoch_seconds = value.to_i
249
- offset_sig, zone_sig = 0x49, 0x69
249
+ offset_sig = 0x49
250
+ zone_sig = 0x69
250
251
  else
251
252
  epoch_seconds = value.to_i + tz_offset
252
- offset_sig, zone_sig = 0x46, 0x66
253
+ offset_sig = 0x46
254
+ zone_sig = 0x66
253
255
  end
254
256
  zone_name = named_zone_for(value)
255
257
 
@@ -29,7 +29,8 @@ module Neo4j
29
29
  def unpack_uuid_value
30
30
  hex = read_bytes(16).unpack1('H*')
31
31
  Types::UUID.from_string(
32
- "#{hex[0, 8]}-#{hex[8, 4]}-#{hex[12, 4]}-#{hex[16, 4]}-#{hex[20, 12]}")
32
+ "#{hex[0, 8]}-#{hex[8, 4]}-#{hex[12, 4]}-#{hex[16, 4]}-#{hex[20, 12]}"
33
+ )
33
34
  end
34
35
 
35
36
  # A ProtocolException (not a bare RuntimeError) so the failure reaches
@@ -49,9 +50,9 @@ module Neo4j
49
50
  case marker
50
51
  when NULL
51
52
  nil
52
- when FALSE
53
+ when BOOLEAN_FALSE
53
54
  false
54
- when TRUE
55
+ when BOOLEAN_TRUE
55
56
  true
56
57
  when FLOAT_64
57
58
  read_bytes(8).unpack1('G')
@@ -159,7 +160,8 @@ module Neo4j
159
160
 
160
161
  def read_bytes(n)
161
162
  data = @io.read(n)
162
- raise IOError, "Unexpected end of stream" if data.nil? || data.bytesize < n
163
+ raise IOError, 'Unexpected end of stream' if data.nil? || data.bytesize < n
164
+
163
165
  data
164
166
  end
165
167
  end
@@ -14,13 +14,7 @@ module Neo4j
14
14
  end
15
15
  end
16
16
 
17
- def keys
18
- @keys
19
- end
20
-
21
- def values
22
- @values
23
- end
17
+ attr_reader :keys, :values
24
18
 
25
19
  def [](key)
26
20
  case key
@@ -41,8 +35,8 @@ module Neo4j
41
35
  @map.dup
42
36
  end
43
37
 
44
- def each(&block)
45
- @map.each(&block)
38
+ def each(&)
39
+ @map.each(&)
46
40
  end
47
41
  end
48
42
  end