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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/neo4j_bolt/version.rb +1 -1
- data/lib/neo4j_bolt.rb +83 -34
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 316d22f20084bb29755e8693c25860bd4d3afa5e5aadce5b89e415bf53157b82
|
4
|
+
data.tar.gz: 405c68b29be5578f7859cdc973b956ccb9898a4b7d105cc19b0e31e81c5615b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94766bfe86f3487582229ed0d11fa4c2bc813adac23fe1065c5dc026c692e3b82c859978b08d5dfb78915382d224425b7e7f81eb06f620eebb23014d8e4934b9
|
7
|
+
data.tar.gz: e144730f9cb75b44450c0dfb3b56d76698c9839e1f54a375c4e7608cb6eb7d6cf70d1544a7065a78d08c4d813387da66ec758bc1749d24037899233c80feb3d7
|
data/Gemfile.lock
CHANGED
data/lib/neo4j_bolt/version.rb
CHANGED
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
|
19
|
-
CONNECTED
|
20
|
-
DEFUNCT
|
21
|
-
READY
|
22
|
-
STREAMING
|
23
|
-
TX_READY
|
24
|
-
TX_STREAMING
|
25
|
-
FAILED
|
26
|
-
INTERRUPTED
|
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(
|
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.
|
644
|
-
version
|
645
|
-
|
646
|
-
raise "Unable to establish connection to Neo4j using Bolt
|
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(
|
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
|
-
|
661
|
-
@
|
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(
|
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(
|
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(
|
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(
|
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.
|
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-
|
11
|
+
date: 2024-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|