neo4j_bolt 0.2.1 → 0.3.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
  SHA256:
3
- metadata.gz: fb231b117247cda9063d3d8c7ee9922ebef33a345291a8ea7261ec51a903fe4f
4
- data.tar.gz: f269e02fe8e439f404d211767224866a9d623356c893befa682d19eee31030fe
3
+ metadata.gz: 316d22f20084bb29755e8693c25860bd4d3afa5e5aadce5b89e415bf53157b82
4
+ data.tar.gz: 405c68b29be5578f7859cdc973b956ccb9898a4b7d105cc19b0e31e81c5615b3
5
5
  SHA512:
6
- metadata.gz: dd7b2031de0005b704fef01043f9ca393df3f8d4a79b07d879d348a17cc9b3eeb018b2282f25a31a9e0c691e47280fadde04bc21fc3390253c3f092d16807a2c
7
- data.tar.gz: 698bbc17d5acd365458ada7feea3d802def624bc2052652f34c1c13e75d6d8b3ebd67b20210ce9300b5d0d8aa278f66f0bc514710f5f52119d2ad9db2e8aa5b5
6
+ metadata.gz: 94766bfe86f3487582229ed0d11fa4c2bc813adac23fe1065c5dc026c692e3b82c859978b08d5dfb78915382d224425b7e7f81eb06f620eebb23014d8e4934b9
7
+ data.tar.gz: e144730f9cb75b44450c0dfb3b56d76698c9839e1f54a375c4e7608cb6eb7d6cf70d1544a7065a78d08c4d813387da66ec758bc1749d24037899233c80feb3d7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- neo4j_bolt (0.2.1)
4
+ neo4j_bolt (0.3.0)
5
5
  gli
6
6
  pry
7
7
 
@@ -1,3 +1,3 @@
1
1
  module Neo4jBolt
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/neo4j_bolt.rb CHANGED
@@ -15,15 +15,16 @@ module Neo4jBolt
15
15
  CONSTRAINT_INDEX_PREFIX = 'neo4j_bolt_'
16
16
 
17
17
  module ServerState
18
- DISCONNECTED = 0
19
- CONNECTED = 1
20
- DEFUNCT = 2
21
- READY = 3
22
- STREAMING = 4
23
- TX_READY = 5
24
- TX_STREAMING = 6
25
- FAILED = 7
26
- INTERRUPTED = 8
18
+ DISCONNECTED = 0
19
+ CONNECTED = 1
20
+ DEFUNCT = 2
21
+ READY = 3
22
+ STREAMING = 4
23
+ TX_READY = 5
24
+ TX_STREAMING = 6
25
+ FAILED = 7
26
+ INTERRUPTED = 8
27
+ AUTHENTICATION = 10
27
28
  end
28
29
  SERVER_STATE_LABELS = Hash[ServerState::constants.map { |value| [ServerState::const_get(value), value] }]
29
30
 
@@ -39,6 +40,7 @@ module Neo4jBolt
39
40
  BOLT_PULL = 0x3F
40
41
  BOLT_NODE = 0x4E
41
42
  BOLT_RELATIONSHIP = 0x52
43
+ BOLT_LOGON = 0x6A
42
44
  BOLT_SUCCESS = 0x70
43
45
  BOLT_RECORD = 0x71
44
46
  BOLT_IGNORED = 0x7E
@@ -301,7 +303,7 @@ module Neo4jBolt
301
303
  end
302
304
 
303
305
  def append_token(i)
304
- # STDERR.puts BOLT_MARKER_LABELS[i]
306
+ # STDERR.puts "Appending token: [#{BOLT_MARKER_LABELS[i]}]"
305
307
  append_uint8(i)
306
308
  end
307
309
 
@@ -335,6 +337,7 @@ module Neo4jBolt
335
337
 
336
338
  def append_s(s)
337
339
  s = s.to_s
340
+ # STDERR.puts "Appending string: [#{s}]"
338
341
  if s.bytesize < 16
339
342
  append_uint8(0x80 + s.bytesize)
340
343
  elsif s.bytesize < 0x100
@@ -398,6 +401,7 @@ module Neo4jBolt
398
401
  end
399
402
 
400
403
  def append_dict(d)
404
+ # STDERR.puts "Appending dict: [#{d.to_json}]"
401
405
  if d.size < 16
402
406
  append_uint8(0xA0 + d.size)
403
407
  elsif d.size < 0x100
@@ -439,6 +443,35 @@ module Neo4jBolt
439
443
  end
440
444
 
441
445
  def flush()
446
+ # STDERR.puts "Flushing buffer with #{@buffer.size} bytes..."
447
+
448
+ # offset = 0
449
+ # last_offset = 0
450
+ # while offset < @buffer.size
451
+ # if offset % 16 == 0
452
+ # STDERR.write sprintf('%04x | ', offset)
453
+ # end
454
+ # STDERR.write sprintf("%02x ", @buffer[offset])
455
+ # offset += 1
456
+ # if offset % 16 == 0
457
+ # STDERR.write ' ' * 4
458
+ # (last_offset...offset).each do |i|
459
+ # b = @buffer[i]
460
+ # STDERR.write (b >= 32 && b < 128) ? b.chr : '.'
461
+ # end
462
+ # STDERR.puts
463
+ # last_offset = offset
464
+ # end
465
+ # end
466
+ # (16 - offset + last_offset).times { STDERR.write ' ' }
467
+ # STDERR.write ' ' * 4
468
+ # (last_offset...offset).each do |i|
469
+ # b = @buffer[i]
470
+ # STDERR.write (b >= 32 && b < 128) ? b.chr : '.'
471
+ # end
472
+ # STDERR.puts
473
+
474
+
442
475
  size = @buffer.size
443
476
  offset = 0
444
477
  while size > 0
@@ -602,12 +635,16 @@ module Neo4jBolt
602
635
 
603
636
  def read_response(&block)
604
637
  loop do
638
+ # STDERR.puts "Reading response:"
605
639
  buffer = BoltBuffer.new(@socket)
640
+ # buffer.dump
606
641
  response_dict = parse(buffer)
607
642
  buffer.flush()
643
+ # STDERR.puts "Response marker: #{BOLT_MARKER_LABELS[response_dict[:marker]]}"
644
+ # STDERR.puts response_dict.to_yaml
608
645
  if response_dict[:marker] == BoltMarker::BOLT_FAILURE
609
646
  # STDERR.puts "RESETTING CONNECTION"
610
- append_uint8(0xb1)
647
+ append_uint8(0xb0)
611
648
  append_token(BoltMarker::BOLT_RESET)
612
649
  flush()
613
650
  read_response() do |data|
@@ -627,38 +664,50 @@ module Neo4jBolt
627
664
  end
628
665
 
629
666
  def connect()
630
- # STDERR.write "Connecting to Neo4j via Bolt..."
631
667
  @socket = TCPSocket.new(Neo4jBolt.bolt_host, Neo4jBolt.bolt_port)
632
- # @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
633
- # @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 50)
634
- # @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10)
635
- # @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT, 5)
636
668
  # The line below is important, otherwise we'll have to wait 40ms before every read
637
669
  @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
638
670
  @buffer = []
639
671
  @socket.write("\x60\x60\xB0\x17")
672
+ @socket.write("\x00\x00\x04\x05")
640
673
  @socket.write("\x00\x00\x04\x04")
641
674
  @socket.write("\x00\x00\x00\x00")
642
675
  @socket.write("\x00\x00\x00\x00")
643
- @socket.write("\x00\x00\x00\x00")
644
- version = @socket.read(4).unpack('N').first
645
- if version != 0x00000404
646
- raise "Unable to establish connection to Neo4j using Bolt protocol version 4.4!"
676
+ @bolt_version = @socket.read(4).unpack('V').first >> 16
677
+ # STDERR.puts "Handshake Bolt version: 0x%08x" % @bolt_version
678
+ unless [0x0504, 0x0404].include?(@bolt_version)
679
+ raise "Unable to establish connection to Neo4j using Bolt!"
647
680
  end
648
681
  @state.set(ServerState::CONNECTED)
649
- data = {
650
- :routing => nil,
651
- :scheme => 'none',
652
- :user_agent => 'neo4j_bolt/0.1'
653
- }
654
682
  append_uint8(0xb1)
655
683
  append_token(BoltMarker::BOLT_HELLO)
656
- append_dict(data)
684
+ append_dict({
685
+ :routing => nil,
686
+ :scheme => 'none',
687
+ :user_agent => "neo4j_bolt/#{Neo4jBolt::VERSION}",
688
+ :bolt_agent => {
689
+ :product => "neo4j_bolt/#{Neo4jBolt::VERSION}",
690
+ },
691
+ })
657
692
  flush()
658
693
  read_response() do |data|
659
694
  if data[:marker] == BoltMarker::BOLT_SUCCESS
660
- @state.set(ServerState::READY)
661
- @neo4j_version = data[:data]['server']
695
+ parts = data[:data]['server'].split('/')[1].split('.').map { |x| x.to_i}
696
+ if @bolt_version >= 0x0501
697
+ @state.set(ServerState::AUTHENTICATION)
698
+ append_uint8(0xb1)
699
+ append_token(BoltMarker::BOLT_LOGON)
700
+ append_dict({:scheme => 'none'})
701
+ flush()
702
+ read_response() do |data2|
703
+ @state.set(ServerState::READY)
704
+ if data2[:marker] == BoltMarker::BOLT_SUCCESS
705
+ @state.set(ServerState::READY)
706
+ end
707
+ end
708
+ else
709
+ @state.set(ServerState::READY)
710
+ end
662
711
  elsif data[:marker] == BoltMarker::BOLT_FAILURE
663
712
  @state.set(ServerState::DEFUNCT)
664
713
  else
@@ -671,7 +720,7 @@ module Neo4jBolt
671
720
  end
672
721
 
673
722
  def disconnect()
674
- append_uint8(0xb1)
723
+ append_uint8(0xb0)
675
724
  append_token(BoltMarker::BOLT_GOODBYE)
676
725
  flush()
677
726
  @state.set(ServerState::DEFUNCT)
@@ -708,13 +757,13 @@ module Neo4jBolt
708
757
  raise
709
758
  ensure
710
759
  @transaction -= 1
711
- if @transaction == 0 && @transaction_failed &&
760
+ if @transaction == 0 && @transaction_failed
712
761
  # TODO: Not sure about this, read remaining response but don't block
713
762
  # read_response()
714
- # STDERR.puts "!!! Rolling back transaction !!!"
763
+ # STDERR.puts "!!! Rolling back transaction !!! --- state is #{@state}"
715
764
  if @state == ServerState::TX_READY
716
765
  assert(@state == ServerState::TX_READY)
717
- append_uint8(0xb1)
766
+ append_uint8(0xb0)
718
767
  append_token(BoltMarker::BOLT_ROLLBACK)
719
768
  flush()
720
769
  read_response do |data|
@@ -730,7 +779,7 @@ module Neo4jBolt
730
779
  end
731
780
  end
732
781
  if (@transaction == 0) && (!@transaction_failed)
733
- append_uint8(0xb1)
782
+ append_uint8(0xb0)
734
783
  append_token(BoltMarker::BOLT_COMMIT)
735
784
  flush()
736
785
  read_response() do |data|
@@ -769,7 +818,7 @@ module Neo4jBolt
769
818
  end
770
819
  transaction do
771
820
  assert(@state == ServerState::TX_READY || @state == ServerState::TX_STREAMING || @state == ServerState::FAILED)
772
- append_uint8(0xb1)
821
+ append_uint8(0xb3)
773
822
  append_token(BoltMarker::BOLT_RUN)
774
823
  append_s(query)
775
824
  # Because something might go wrong while filling the buffer with
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j_bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Specht
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-10 00:00:00.000000000 Z
11
+ date: 2024-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec