neo4j-ruby-driver 0.1.1

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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +68 -0
  5. data/Rakefile +16 -0
  6. data/ffi/bolt/address.rb +11 -0
  7. data/ffi/bolt/auth.rb +10 -0
  8. data/ffi/bolt/auto_releasable.rb +22 -0
  9. data/ffi/bolt/boolean.rb +9 -0
  10. data/ffi/bolt/bytes.rb +10 -0
  11. data/ffi/bolt/config.rb +10 -0
  12. data/ffi/bolt/connection.rb +44 -0
  13. data/ffi/bolt/connector.rb +17 -0
  14. data/ffi/bolt/dictionary.rb +15 -0
  15. data/ffi/bolt/error.rb +74 -0
  16. data/ffi/bolt/float.rb +9 -0
  17. data/ffi/bolt/integer.rb +9 -0
  18. data/ffi/bolt/library.rb +12 -0
  19. data/ffi/bolt/lifecycle.rb +9 -0
  20. data/ffi/bolt/list.rb +10 -0
  21. data/ffi/bolt/status.rb +15 -0
  22. data/ffi/bolt/string.rb +9 -0
  23. data/ffi/bolt/structure.rb +10 -0
  24. data/ffi/bolt/value.rb +35 -0
  25. data/ffi/bolt/values_private.rb +36 -0
  26. data/ffi/neo4j/driver.rb +45 -0
  27. data/ffi/neo4j/driver/access_mode.rb +10 -0
  28. data/ffi/neo4j/driver/auth_tokens.rb +17 -0
  29. data/ffi/neo4j/driver/config.rb +11 -0
  30. data/ffi/neo4j/driver/graph_database.rb +29 -0
  31. data/ffi/neo4j/driver/internal/async/access_mode_connection.rb +19 -0
  32. data/ffi/neo4j/driver/internal/async/direct_connection.rb +88 -0
  33. data/ffi/neo4j/driver/internal/bookmarks_holder.rb +30 -0
  34. data/ffi/neo4j/driver/internal/direct_connection_provider.rb +27 -0
  35. data/ffi/neo4j/driver/internal/driver_factory.rb +38 -0
  36. data/ffi/neo4j/driver/internal/error_handling.rb +50 -0
  37. data/ffi/neo4j/driver/internal/explicit_transaction.rb +144 -0
  38. data/ffi/neo4j/driver/internal/handlers/pull_all_response_handler.rb +101 -0
  39. data/ffi/neo4j/driver/internal/handlers/response_handler.rb +46 -0
  40. data/ffi/neo4j/driver/internal/handlers/run_response_handler.rb +32 -0
  41. data/ffi/neo4j/driver/internal/handlers/session_pull_all_response_handler.rb +32 -0
  42. data/ffi/neo4j/driver/internal/handlers/transaction_pull_all_response_handler.rb +23 -0
  43. data/ffi/neo4j/driver/internal/internal_driver.rb +41 -0
  44. data/ffi/neo4j/driver/internal/internal_record.rb +22 -0
  45. data/ffi/neo4j/driver/internal/internal_statement_result.rb +52 -0
  46. data/ffi/neo4j/driver/internal/messaging/bolt_protocol.rb +24 -0
  47. data/ffi/neo4j/driver/internal/messaging/v1/bolt_protocol_v1.rb +59 -0
  48. data/ffi/neo4j/driver/internal/messaging/v2/bolt_protocol_v2.rb +16 -0
  49. data/ffi/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +63 -0
  50. data/ffi/neo4j/driver/internal/network_session.rb +124 -0
  51. data/ffi/neo4j/driver/internal/session_factory_impl.rb +28 -0
  52. data/ffi/neo4j/driver/internal/summary/internal_result_summary.rb +67 -0
  53. data/ffi/neo4j/driver/internal/summary/internal_server_info.rb +19 -0
  54. data/ffi/neo4j/driver/internal/summary/internal_summary_counters.rb +23 -0
  55. data/ffi/neo4j/driver/internal/util/metadata_extractor.rb +15 -0
  56. data/ffi/neo4j/driver/internal/value/base_time_value.rb +22 -0
  57. data/ffi/neo4j/driver/internal/value/date_value.rb +25 -0
  58. data/ffi/neo4j/driver/internal/value/duration_value.rb +27 -0
  59. data/ffi/neo4j/driver/internal/value/local_date_time_value.rb +24 -0
  60. data/ffi/neo4j/driver/internal/value/local_time_value.rb +19 -0
  61. data/ffi/neo4j/driver/internal/value/node_value.rb +18 -0
  62. data/ffi/neo4j/driver/internal/value/offset_time_value.rb +25 -0
  63. data/ffi/neo4j/driver/internal/value/path_value.rb +41 -0
  64. data/ffi/neo4j/driver/internal/value/point2_d_value.rb +24 -0
  65. data/ffi/neo4j/driver/internal/value/point3_d_value.rb +24 -0
  66. data/ffi/neo4j/driver/internal/value/relationship_value.rb +18 -0
  67. data/ffi/neo4j/driver/internal/value/structure_value.rb +42 -0
  68. data/ffi/neo4j/driver/internal/value/time_with_zone_id_value.rb +25 -0
  69. data/ffi/neo4j/driver/internal/value/time_with_zone_offset_value.rb +28 -0
  70. data/ffi/neo4j/driver/internal/value/unbound_relationship_value.rb +18 -0
  71. data/ffi/neo4j/driver/internal/value/value_adapter.rb +95 -0
  72. data/ffi/neo4j/driver/statement.rb +14 -0
  73. data/ffi/neo4j/driver/summary/statement_type.rb +14 -0
  74. data/ffi/neo4j/driver/types/entity.rb +17 -0
  75. data/ffi/neo4j/driver/types/node.rb +16 -0
  76. data/ffi/neo4j/driver/types/path.rb +35 -0
  77. data/ffi/neo4j/driver/types/relationship.rb +19 -0
  78. data/lib/loader.rb +18 -0
  79. data/lib/neo4j/driver/auto_closable.rb +32 -0
  80. data/lib/neo4j/driver/exceptions/authentication_exception.rb +10 -0
  81. data/lib/neo4j/driver/exceptions/client_exception.rb +10 -0
  82. data/lib/neo4j/driver/exceptions/database_exception.rb +10 -0
  83. data/lib/neo4j/driver/exceptions/illegal_state_exception.rb +10 -0
  84. data/lib/neo4j/driver/exceptions/neo4j_exception.rb +18 -0
  85. data/lib/neo4j/driver/exceptions/no_such_record_exception.rb +33 -0
  86. data/lib/neo4j/driver/exceptions/protocol_exception.rb +10 -0
  87. data/lib/neo4j/driver/exceptions/security_exception.rb +10 -0
  88. data/lib/neo4j/driver/exceptions/service_unavailable_exception.rb +10 -0
  89. data/lib/neo4j/driver/exceptions/session_expired_exception.rb +10 -0
  90. data/lib/neo4j/driver/exceptions/transient_exception.rb +10 -0
  91. data/lib/neo4j/driver/exceptions/untrusted_server_exception.rb +10 -0
  92. data/lib/neo4j/driver/internal/duration_normalizer.rb +42 -0
  93. data/lib/neo4j/driver/internal/ruby_signature.rb +18 -0
  94. data/lib/neo4j/driver/types/byte_array.rb +17 -0
  95. data/lib/neo4j/driver/types/local_date_time.rb +20 -0
  96. data/lib/neo4j/driver/types/local_time.rb +19 -0
  97. data/lib/neo4j/driver/types/offset_time.rb +19 -0
  98. data/lib/neo4j/driver/types/point.rb +39 -0
  99. data/lib/neo4j/driver/types/time.rb +43 -0
  100. data/lib/neo4j/driver/version.rb +7 -0
  101. data/lib/neo4j_ruby_driver.rb +19 -0
  102. data/neo4j-ruby-driver.gemspec +63 -0
  103. metadata +274 -0
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ class ExplicitTransaction
7
+ include ErrorHandling
8
+
9
+ delegate :finalize, to: :@handler
10
+
11
+ def initialize(connection, session)
12
+ @connection = connection
13
+ @protocol = connection.protocol
14
+ @session = session
15
+ @state = :active
16
+ end
17
+
18
+ def begin(initial_bookmarks, config)
19
+ chain @protocol.begin_transaction(@connection, initial_bookmarks, config)
20
+ self
21
+ rescue StandardError => e
22
+ @connection.release
23
+ raise e
24
+ end
25
+
26
+ def run(query, parameters = {})
27
+ ensure_can_run_queries
28
+ @protocol.run_in_explicit_transaction(@connection, Statement.new(query, parameters), self)
29
+ end
30
+
31
+ def success
32
+ @state = :marked_success if @state == :active
33
+ end
34
+
35
+ def failure
36
+ @state = :marked_failed if %i[active marked_success].include? @state
37
+ end
38
+
39
+ def mark_terminated
40
+ @state = :terminated
41
+ end
42
+
43
+ def close
44
+ case @state
45
+ when :marked_success
46
+ commit
47
+ when :committed, :rolled_back
48
+ nil
49
+ else
50
+ rollback
51
+ end
52
+ end
53
+
54
+ def open?
55
+ !%i[committed rolled_back].include? @state
56
+ end
57
+
58
+ def chain(*handlers)
59
+ handlers.each do |handler|
60
+ handler.previous = @handler
61
+ @handler = handler
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def commit
68
+ case @state
69
+ when :committed
70
+ nil
71
+ when :rolled_back
72
+ raise Exceptions::ClientExceptiom, "Can't commit, transaction has been rolled back"
73
+ else
74
+ begin
75
+ do_commit
76
+ # handleCommitOrRollback( error )
77
+ ensure
78
+ transaction_closed(:committed)
79
+ end
80
+ end
81
+ end
82
+
83
+ def do_commit
84
+ if @state == :terminated
85
+ raise Exceptions::ClientException, "Transaction can't be committed. " \
86
+ 'It has been rolled back either because of an error or explicit termination'
87
+ end
88
+
89
+ # @session.bookmarks = @protocol.commit_transaction(@connection)
90
+ chain @protocol.commit_transaction(@connection)
91
+ finalize
92
+ @session.bookmarks = @connection.last_bookmark
93
+ end
94
+
95
+ def rollback
96
+ case @state
97
+ when :committed
98
+ raise ClientException, "Can't rollback, transaction has been committed"
99
+ when :rolled_back
100
+ nil
101
+ else
102
+ begin
103
+ do_rollback
104
+ # resultCursors.retrieveNotConsumedError()
105
+ # handleCommitOrRollback( error )
106
+ ensure
107
+ transaction_closed(:rolled_back)
108
+ end
109
+ end
110
+ end
111
+
112
+ def do_rollback
113
+ return if @state == :terminated
114
+
115
+ chain @protocol.rollback_transaction(@connection)
116
+ finalize
117
+ end
118
+
119
+ def transaction_closed(new_state)
120
+ @state = new_state
121
+ @session.release_connection
122
+ end
123
+
124
+ def ensure_can_run_queries
125
+ reason =
126
+ case @state
127
+ when :committed
128
+ 'Cannot run more statements in this transaction, it has been committed'
129
+ when :rolled_back
130
+ 'Cannot run more statements in this transaction, it has been rolled back'
131
+ when :marked_failed
132
+ 'Cannot run more statements in this transaction, it has been marked for failure. ' \
133
+ 'Please either rollback or close this transaction'
134
+ when :terminated
135
+ 'Cannot run more statements in this transaction, ' \
136
+ 'it has either experienced an fatal error or was explicitly terminated'
137
+ end
138
+
139
+ raise Exceptions::ClientException, reason if reason
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ module Handlers
7
+ class PullAllResponseHandler < ResponseHandler
8
+ delegate :bolt_connection, to: :connection
9
+ delegate :statement_keys, to: :run_handler
10
+ attr_reader :connection
11
+
12
+ def initialize(statement, run_handler, connection, metadata_extractor)
13
+ super(connection)
14
+ @statement = statement
15
+ @previous = run_handler
16
+ @metadate_extractor = metadata_extractor
17
+ @records = []
18
+ end
19
+
20
+ def consume
21
+ # @ignore_records = true
22
+ @records.clear
23
+ finalize
24
+ @summary
25
+ rescue StandardError => e
26
+ on_failure(e)
27
+ raise e
28
+ end
29
+
30
+ def summary
31
+ unless @finished
32
+ while (record = fetch)
33
+ @records << record
34
+ end
35
+ end
36
+ @summary ||= Summary::InternalResultSummary.new(@statement, run_handler.result_available_after,
37
+ bolt_connection)
38
+ end
39
+
40
+ def peek
41
+ @records.first || ((@records << fetch).first unless @finished)
42
+ end
43
+
44
+ def next
45
+ peek
46
+ @records.shift
47
+ end
48
+
49
+ def on_success
50
+ @finished = true
51
+ summary
52
+
53
+ after_success(nil)
54
+
55
+ # @records.clear
56
+ @failure = nil
57
+ end
58
+
59
+ def failure
60
+ # bolt_summary if connection.open?
61
+ end
62
+
63
+ def on_failure(error)
64
+ @finished = true
65
+ summary
66
+
67
+ after_failure(error)
68
+
69
+ @records.clear
70
+ @failure = error
71
+ end
72
+
73
+ private
74
+
75
+ def run_handler
76
+ @previous
77
+ end
78
+
79
+ def fetch
80
+ run_handler.finalize
81
+ bolt_connection_fetch = Bolt::Connection.fetch(bolt_connection, request)
82
+ case bolt_connection_fetch
83
+ when -1
84
+ check_status(Bolt::Connection.status(bolt_connection))
85
+ when 1
86
+ InternalRecord.new(run_handler.statement_keys,
87
+ Value::ValueAdapter.to_ruby(Bolt::Connection.field_values(bolt_connection)))
88
+ else
89
+ @finished = true
90
+ check_summary_failure
91
+ nil
92
+ end
93
+ rescue StandardError => e
94
+ @finished = true
95
+ raise e
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ module Handlers
7
+ class ResponseHandler
8
+ delegate :bolt_connection, to: :connection
9
+ attr_reader :connection
10
+ attr_accessor :request, :previous
11
+
12
+ def initialize(connection)
13
+ @connection = connection
14
+ end
15
+
16
+ def finalize
17
+ return if @finished
18
+ @finished = true
19
+ begin
20
+ previous&.finalize
21
+ ensure
22
+ Bolt::Connection.fetch_summary(bolt_connection, request)
23
+ check_summary_failure
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def check_summary_failure
30
+ summary
31
+ if Bolt::Connection.summary_success(bolt_connection) == 1
32
+ after_success(nil)
33
+ else
34
+ failure = Value::ValueAdapter.to_ruby(Bolt::Connection.failure(bolt_connection))
35
+ raise Exceptions::ClientException.new(failure[:code], failure[:message])
36
+ end
37
+ end
38
+
39
+ def summary; end
40
+
41
+ def after_success(metadata); end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ module Handlers
7
+ class RunResponseHandler < ResponseHandler
8
+ attr_reader :result_available_after
9
+
10
+ def initialize(connection, metadata_extractor)
11
+ super(connection)
12
+ @statement_keys = []
13
+ @metadata_extractor = metadata_extractor
14
+ end
15
+
16
+ def statement_keys
17
+ finalize
18
+ @statement_keys
19
+ end
20
+
21
+ def finalize
22
+ return if @finished
23
+ super
24
+ @statement_keys = Value::ValueAdapter.to_ruby(Bolt::Connection.field_names(bolt_connection))
25
+ metadata = Value::ValueAdapter.to_ruby(Bolt::Connection.metadata(bolt_connection))
26
+ @result_available_after = metadata[:result_available_after] || metadata[:t_first]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ module Handlers
7
+ class SessionPullAllResponseHandler < PullAllResponseHandler
8
+ def initialize(statement, run_handler, connection, bookmarks_holder, metadata_extractor)
9
+ super(statement, run_handler, connection, metadata_extractor)
10
+ @bookmarks_holder = bookmarks_holder
11
+ end
12
+
13
+ def after_success(metadata)
14
+ @bookmarks_holder.bookmarks = connection.last_bookmark
15
+ release_connection
16
+ # @bookmarks_holder.bookmarks = @metadata_extractor.extract_bookmarks(metadata)
17
+ end
18
+
19
+ def after_failure(_error)
20
+ release_connection
21
+ end
22
+
23
+ private
24
+
25
+ def release_connection
26
+ connection.release
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ module Handlers
7
+ class TransactionPullAllResponseHandler < PullAllResponseHandler
8
+ def initialize(statement, run_handler, connection, tx, metadata_extractor)
9
+ super(statement, run_handler, connection, metadata_extractor)
10
+ @tx = tx
11
+ @tx.chain run_handler, self
12
+ end
13
+
14
+ def after_success(_metadata); end
15
+
16
+ def after_failure(_error)
17
+ @tx.mark_terminated
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ class InternalDriver
7
+ extend AutoClosable
8
+ include ErrorHandling
9
+
10
+ attr_reader :session_factory
11
+ delegate :verify_connectivity, to: :session_factory
12
+ auto_closable :session
13
+
14
+ def initialize(session_factory)
15
+ @session_factory = session_factory
16
+ @closed = Concurrent::AtomicBoolean.new(false)
17
+ end
18
+
19
+ def session(*args)
20
+ new_session(*Neo4j::Driver::Internal::RubySignature.session(args))
21
+ end
22
+
23
+ def close
24
+ session_factory.close if @closed.make_true
25
+ # Bolt::Connector.destroy(@connector)
26
+ end
27
+
28
+ private
29
+
30
+ def new_session(mode, bookmarks)
31
+ assert_open
32
+ session_factory.new_instance(mode, bookmarks)
33
+ end
34
+
35
+ def assert_open
36
+ raise Exceptions::IllegalStateException, 'This driver instance has already been closed' if @closed.true?
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module Internal
6
+ class InternalRecord
7
+ attr_reader :values
8
+ delegate :first, to: :values
9
+
10
+ def initialize(keys, values)
11
+ @keys = keys
12
+ @values = values
13
+ end
14
+
15
+ def [](key)
16
+ field_index = key.is_a?(Integer) ? key : @keys.index(key.to_s)
17
+ @values[field_index] if field_index
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end