grumlin 0.22.4 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +9 -9
  4. data/Gemfile.lock +10 -8
  5. data/README.md +102 -141
  6. data/Rakefile +1 -1
  7. data/bin/console +18 -3
  8. data/doc/middlewares.md +97 -0
  9. data/grumlin.gemspec +1 -0
  10. data/lib/async/channel.rb +54 -56
  11. data/lib/grumlin/benchmark/repository.rb +10 -14
  12. data/lib/grumlin/client.rb +92 -112
  13. data/lib/grumlin/config.rb +30 -15
  14. data/lib/grumlin/dummy_transaction.rb +13 -15
  15. data/lib/grumlin/edge.rb +18 -20
  16. data/lib/grumlin/expressions/cardinality.rb +5 -9
  17. data/lib/grumlin/expressions/column.rb +5 -9
  18. data/lib/grumlin/expressions/expression.rb +7 -11
  19. data/lib/grumlin/expressions/operator.rb +5 -9
  20. data/lib/grumlin/expressions/order.rb +5 -9
  21. data/lib/grumlin/expressions/p.rb +27 -31
  22. data/lib/grumlin/expressions/pop.rb +5 -9
  23. data/lib/grumlin/expressions/scope.rb +5 -9
  24. data/lib/grumlin/expressions/t.rb +5 -9
  25. data/lib/grumlin/expressions/text_p.rb +5 -9
  26. data/lib/grumlin/expressions/with_options.rb +17 -21
  27. data/lib/grumlin/features/feature_list.rb +8 -12
  28. data/lib/grumlin/features/neptune_features.rb +5 -9
  29. data/lib/grumlin/features/tinkergraph_features.rb +5 -9
  30. data/lib/grumlin/features.rb +8 -10
  31. data/lib/grumlin/middlewares/apply_shortcuts.rb +8 -0
  32. data/lib/grumlin/middlewares/build_query.rb +20 -0
  33. data/lib/grumlin/middlewares/builder.rb +15 -0
  34. data/lib/grumlin/middlewares/cast_results.rb +7 -0
  35. data/lib/grumlin/middlewares/find_blocklisted_steps.rb +14 -0
  36. data/lib/grumlin/middlewares/find_mutating_steps.rb +9 -0
  37. data/lib/grumlin/middlewares/middleware.rb +11 -0
  38. data/lib/grumlin/middlewares/run_query.rb +7 -0
  39. data/lib/grumlin/middlewares/serialize_to_bytecode.rb +9 -0
  40. data/lib/grumlin/middlewares/serialize_to_steps.rb +8 -0
  41. data/lib/grumlin/path.rb +11 -13
  42. data/lib/grumlin/property.rb +14 -16
  43. data/lib/grumlin/query_validators/blocklisted_steps_validator.rb +22 -0
  44. data/lib/grumlin/query_validators/validator.rb +36 -0
  45. data/lib/grumlin/repository/error_handling_strategy.rb +36 -40
  46. data/lib/grumlin/repository/instance_methods.rb +115 -118
  47. data/lib/grumlin/repository.rb +82 -58
  48. data/lib/grumlin/request_dispatcher.rb +55 -57
  49. data/lib/grumlin/request_error_factory.rb +53 -55
  50. data/lib/grumlin/shortcut.rb +19 -21
  51. data/lib/grumlin/shortcuts/properties.rb +12 -16
  52. data/lib/grumlin/shortcuts/storage.rb +67 -74
  53. data/lib/grumlin/shortcuts/upserts.rb +18 -22
  54. data/lib/grumlin/shortcuts.rb +23 -25
  55. data/lib/grumlin/shortcuts_applyer.rb +27 -29
  56. data/lib/grumlin/step.rb +92 -0
  57. data/lib/grumlin/step_data.rb +12 -14
  58. data/lib/grumlin/steppable.rb +24 -22
  59. data/lib/grumlin/steps.rb +51 -54
  60. data/lib/grumlin/steps_serializers/bytecode.rb +53 -56
  61. data/lib/grumlin/steps_serializers/human_readable_bytecode.rb +17 -21
  62. data/lib/grumlin/steps_serializers/serializer.rb +7 -11
  63. data/lib/grumlin/steps_serializers/string.rb +26 -30
  64. data/lib/grumlin/test/rspec/db_cleaner_context.rb +8 -12
  65. data/lib/grumlin/test/rspec/gremlin_context.rb +18 -16
  66. data/lib/grumlin/test/rspec.rb +1 -5
  67. data/lib/grumlin/transaction.rb +26 -27
  68. data/lib/grumlin/transport.rb +71 -73
  69. data/lib/grumlin/traversal_start.rb +31 -33
  70. data/lib/grumlin/traversal_strategies/options_strategy.rb +3 -7
  71. data/lib/grumlin/traverser.rb +5 -7
  72. data/lib/grumlin/typed_value.rb +11 -13
  73. data/lib/grumlin/typing.rb +70 -72
  74. data/lib/grumlin/version.rb +1 -1
  75. data/lib/grumlin/vertex.rb +14 -16
  76. data/lib/grumlin/vertex_property.rb +14 -16
  77. data/lib/grumlin/with_extension.rb +17 -19
  78. data/lib/grumlin.rb +23 -19
  79. metadata +32 -6
  80. data/lib/grumlin/action.rb +0 -92
  81. data/lib/grumlin/sugar.rb +0 -15
data/lib/grumlin.rb CHANGED
@@ -17,6 +17,7 @@ require "async/barrier"
17
17
  require "async/http/endpoint"
18
18
  require "async/websocket/client"
19
19
 
20
+ require "middleware"
20
21
  require "retryable"
21
22
 
22
23
  require "zeitwerk"
@@ -34,6 +35,7 @@ module Grumlin
34
35
  class Error < StandardError; end
35
36
 
36
37
  class TransactionError < Error; end
38
+
37
39
  class Rollback < TransactionError; end
38
40
 
39
41
  class UnknownError < Error; end
@@ -99,15 +101,19 @@ module Grumlin
99
101
  end
100
102
 
101
103
  class VertexAlreadyExistsError < AlreadyExistsError; end
104
+
102
105
  class EdgeAlreadyExistsError < AlreadyExistsError; end
103
106
 
104
107
  class ConcurrentModificationError < ServerError; end
108
+
105
109
  class ConcurrentInsertFailedError < ConcurrentModificationError; end
106
110
 
107
111
  class ConcurrentVertexInsertFailedError < ConcurrentInsertFailedError; end
112
+
108
113
  class ConcurrentEdgeInsertFailedError < ConcurrentInsertFailedError; end
109
114
 
110
115
  class ConcurrentVertexPropertyInsertFailedError < ConcurrentInsertFailedError; end
116
+
111
117
  class ConcurrentEdgePropertyInsertFailedError < ConcurrentInsertFailedError; end
112
118
 
113
119
  class ServerSerializationError < ServerSideError; end
@@ -134,8 +140,6 @@ module Grumlin
134
140
 
135
141
  class WrongQueryResult < RepositoryError; end
136
142
 
137
- @pool_mutex = Mutex.new
138
-
139
143
  class << self
140
144
  def configure
141
145
  yield config
@@ -147,6 +151,10 @@ module Grumlin
147
151
  @config ||= Config.new
148
152
  end
149
153
 
154
+ def default_middlewares
155
+ config.middlewares
156
+ end
157
+
150
158
  # returns a subset of features for currently configured backend.
151
159
  # The features lists are hardcoded as there is no way to get them
152
160
  # from the remote server.
@@ -155,26 +163,22 @@ module Grumlin
155
163
  end
156
164
 
157
165
  def default_pool
158
- if Thread.current.thread_variable_get(:grumlin_default_pool)
159
- return Thread.current.thread_variable_get(:grumlin_default_pool)
160
- end
161
-
162
- @pool_mutex.synchronize do
163
- Thread.current.thread_variable_set(:grumlin_default_pool,
164
- Async::Pool::Controller.new(Grumlin::Client::PoolResource,
165
- limit: config.pool_size))
166
- end
166
+ t = Thread.current
167
+ return t.thread_variable_get(:grumlin_default_pool) if t.thread_variable_get(:grumlin_default_pool)
168
+
169
+ t.thread_variable_set(:grumlin_default_pool,
170
+ Async::Pool::Controller.new(Grumlin::Client::PoolResource,
171
+ limit: config.pool_size))
167
172
  end
168
173
 
169
174
  def close
170
- return if Thread.current.thread_variable_get(:grumlin_default_pool).nil?
171
-
172
- @pool_mutex.synchronize do
173
- pool = Thread.current.thread_variable_get(:grumlin_default_pool)
174
- pool.wait while pool.busy?
175
- pool.close
176
- Thread.current.thread_variable_set(:grumlin_default_pool, nil)
177
- end
175
+ t = Thread.current
176
+ return if t.thread_variable_get(:grumlin_default_pool).nil?
177
+
178
+ pool = t.thread_variable_get(:grumlin_default_pool)
179
+ pool.wait while pool.busy?
180
+ pool.close
181
+ t.thread_variable_set(:grumlin_default_pool, nil)
178
182
  end
179
183
 
180
184
  def definitions
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grumlin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.4
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gleb Sinyavskiy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-22 00:00:00.000000000 Z
11
+ date: 2022-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-pool
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0.20'
47
+ - !ruby/object:Gem::Dependency
48
+ name: ibsciss-middleware
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 0.4.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.4.0
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: oj
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -110,6 +124,7 @@ files:
110
124
  - Rakefile
111
125
  - bin/console
112
126
  - bin/setup
127
+ - doc/middlewares.md
113
128
  - docker-compose.yml
114
129
  - gremlin_server/Dockerfile
115
130
  - gremlin_server/tinkergraph-empty.properties
@@ -119,7 +134,6 @@ files:
119
134
  - lib/async/channel.rb
120
135
  - lib/definitions.yml
121
136
  - lib/grumlin.rb
122
- - lib/grumlin/action.rb
123
137
  - lib/grumlin/benchmark/repository.rb
124
138
  - lib/grumlin/client.rb
125
139
  - lib/grumlin/config.rb
@@ -140,8 +154,20 @@ files:
140
154
  - lib/grumlin/features/feature_list.rb
141
155
  - lib/grumlin/features/neptune_features.rb
142
156
  - lib/grumlin/features/tinkergraph_features.rb
157
+ - lib/grumlin/middlewares/apply_shortcuts.rb
158
+ - lib/grumlin/middlewares/build_query.rb
159
+ - lib/grumlin/middlewares/builder.rb
160
+ - lib/grumlin/middlewares/cast_results.rb
161
+ - lib/grumlin/middlewares/find_blocklisted_steps.rb
162
+ - lib/grumlin/middlewares/find_mutating_steps.rb
163
+ - lib/grumlin/middlewares/middleware.rb
164
+ - lib/grumlin/middlewares/run_query.rb
165
+ - lib/grumlin/middlewares/serialize_to_bytecode.rb
166
+ - lib/grumlin/middlewares/serialize_to_steps.rb
143
167
  - lib/grumlin/path.rb
144
168
  - lib/grumlin/property.rb
169
+ - lib/grumlin/query_validators/blocklisted_steps_validator.rb
170
+ - lib/grumlin/query_validators/validator.rb
145
171
  - lib/grumlin/repository.rb
146
172
  - lib/grumlin/repository/error_handling_strategy.rb
147
173
  - lib/grumlin/repository/instance_methods.rb
@@ -153,6 +179,7 @@ files:
153
179
  - lib/grumlin/shortcuts/storage.rb
154
180
  - lib/grumlin/shortcuts/upserts.rb
155
181
  - lib/grumlin/shortcuts_applyer.rb
182
+ - lib/grumlin/step.rb
156
183
  - lib/grumlin/step_data.rb
157
184
  - lib/grumlin/steppable.rb
158
185
  - lib/grumlin/steps.rb
@@ -160,7 +187,6 @@ files:
160
187
  - lib/grumlin/steps_serializers/human_readable_bytecode.rb
161
188
  - lib/grumlin/steps_serializers/serializer.rb
162
189
  - lib/grumlin/steps_serializers/string.rb
163
- - lib/grumlin/sugar.rb
164
190
  - lib/grumlin/test/rspec.rb
165
191
  - lib/grumlin/test/rspec/db_cleaner_context.rb
166
192
  - lib/grumlin/test/rspec/gremlin_context.rb
@@ -195,9 +221,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
195
221
  version: 2.7.0
196
222
  required_rubygems_version: !ruby/object:Gem::Requirement
197
223
  requirements:
198
- - - ">="
224
+ - - ">"
199
225
  - !ruby/object:Gem::Version
200
- version: '0'
226
+ version: 1.3.1
201
227
  requirements: []
202
228
  rubygems_version: 3.2.33
203
229
  signing_key:
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grumlin
4
- class Action < Steppable
5
- attr_reader :name, :args, :params, :next_step, :configuration_steps, :previous_step, :shortcut
6
-
7
- # client is only used when a traversal is a part of transaction
8
- def initialize(name, args: [], params: {}, previous_step: nil, pool: Grumlin.default_pool, session_id: nil)
9
- super(pool: pool, session_id: session_id)
10
-
11
- @name = name.to_sym
12
- @args = args # TODO: add recursive validation: only json types or Action
13
- @params = params # TODO: add recursive validation: only json types
14
- @previous_step = previous_step
15
- @shortcut = shortcuts[@name]
16
- end
17
-
18
- def configuration_step?
19
- CONFIGURATION_STEPS.include?(@name) || name.to_sym == :tx
20
- end
21
-
22
- def start_step?
23
- START_STEPS.include?(@name)
24
- end
25
-
26
- def regular_step?
27
- REGULAR_STEPS.include?(@name)
28
- end
29
-
30
- def supported_step?
31
- ALL_STEPS.include?(@name)
32
- end
33
-
34
- def ==(other)
35
- self.class == other.class &&
36
- @name == other.name &&
37
- @args == other.args &&
38
- @params == other.params &&
39
- @previous_step == other.previous_step &&
40
- shortcuts == other.shortcuts
41
- end
42
-
43
- def steps
44
- @steps ||= Steps.from(self)
45
- end
46
-
47
- def to_s(**params)
48
- StepsSerializers::String.new(steps, **params).serialize
49
- end
50
-
51
- # TODO: add human readable mode
52
- def inspect
53
- conf_steps, regular_steps = StepsSerializers::HumanReadableBytecode.new(steps).serialize
54
- "#{conf_steps.any? ? conf_steps : nil}#{regular_steps}"
55
- end
56
-
57
- def bytecode(no_return: false)
58
- StepsSerializers::Bytecode.new(steps, no_return: no_return)
59
- end
60
-
61
- def next
62
- to_enum.next
63
- end
64
-
65
- def hasNext # rubocop:disable Naming/MethodName
66
- to_enum.peek
67
- true
68
- rescue StopIteration
69
- false
70
- end
71
-
72
- def to_enum
73
- @to_enum ||= toList.to_enum
74
- end
75
-
76
- def toList
77
- client_write(bytecode)
78
- end
79
-
80
- def iterate
81
- client_write(bytecode(no_return: true))
82
- end
83
-
84
- private
85
-
86
- def client_write(payload)
87
- @pool.acquire do |client|
88
- client.write(payload, session_id: @session_id)
89
- end
90
- end
91
- end
92
- end
data/lib/grumlin/sugar.rb DELETED
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grumlin
4
- module Sugar
5
- def self.included(base)
6
- base.include(Grumlin::Expressions)
7
- end
8
-
9
- %i[__ g].each do |name|
10
- define_method name do |cuts = Shortcuts::Storage.empty|
11
- cuts.send(name)
12
- end
13
- end
14
- end
15
- end