grumlin 0.19.5 → 0.20.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/.rspec +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +5 -3
- data/README.md +31 -0
- data/bin/console +2 -0
- data/gremlin_server/Dockerfile +4 -0
- data/gremlin_server/tinkergraph-gremlin/lib/tinkergraph-gremlin-3.5.3.jar +0 -0
- data/gremlin_server/tinkergraph-gremlin/plugin/tinkergraph-gremlin-3.5.3.jar +0 -0
- data/grumlin.gemspec +1 -3
- data/lib/definitions.yml +12 -2
- data/lib/grumlin/action.rb +7 -38
- data/lib/grumlin/expressions/cardinality.rb +15 -0
- data/lib/grumlin/expressions/p.rb +1 -1
- data/lib/grumlin/repository/instance_methods.rb +5 -5
- data/lib/grumlin/repository.rb +14 -6
- data/lib/grumlin/request_dispatcher.rb +2 -2
- data/lib/grumlin/shortcut.rb +6 -1
- data/lib/grumlin/shortcuts/storage.rb +105 -0
- data/lib/grumlin/shortcuts/upserts.rb +3 -3
- data/lib/grumlin/shortcuts.rb +9 -16
- data/lib/grumlin/shortcuts_applyer.rb +15 -17
- data/lib/grumlin/steppable.rb +32 -0
- data/lib/grumlin/steps.rb +2 -2
- data/lib/grumlin/sugar.rb +4 -6
- data/lib/grumlin/traversal_start.rb +1 -39
- data/lib/grumlin/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ab9e228cb2cd8ecc761136dab0e92a42aae268708aecf5784aac670a4404ecb
|
4
|
+
data.tar.gz: 984d2323e97056291370c37dadc2cf90d694f27caa753053a110165985dc067b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27a73c8e77850b99e030c129f8df2e30fc6933ad4da29e5a205b7812c64c88f24d7aceb2128af6687fc4bf35056509421989d2cae5a51c5db6f53c18f735fe97
|
7
|
+
data.tar.gz: adf371f27c60f2c0e70feaafcfede32dc64beef09b098bf35f01270b37049ee5ce76a68c184bf80abe33c7069ca8b947bbd54ecdcab42fd461a8bb09c270b1b1
|
data/.rspec
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
grumlin (0.
|
4
|
+
grumlin (0.20.0)
|
5
5
|
async-pool (~> 0.3)
|
6
6
|
async-websocket (~> 0.19)
|
7
7
|
oj (~> 3.13)
|
@@ -17,7 +17,7 @@ GEM
|
|
17
17
|
minitest (>= 5.1)
|
18
18
|
tzinfo (~> 2.0)
|
19
19
|
ast (2.4.2)
|
20
|
-
async (1.30.
|
20
|
+
async (1.30.3)
|
21
21
|
console (~> 1.10)
|
22
22
|
nio4r (~> 2.3)
|
23
23
|
timers (~> 4.1)
|
@@ -48,6 +48,7 @@ GEM
|
|
48
48
|
concurrent-ruby (1.1.10)
|
49
49
|
console (1.15.3)
|
50
50
|
fiber-local
|
51
|
+
dead_end (4.0.0)
|
51
52
|
diff-lcs (1.5.0)
|
52
53
|
docile (1.4.0)
|
53
54
|
e2mmap (0.1.0)
|
@@ -71,7 +72,7 @@ GEM
|
|
71
72
|
racc (~> 1.4)
|
72
73
|
nokogiri (1.13.6-x86_64-linux)
|
73
74
|
racc (~> 1.4)
|
74
|
-
oj (3.13.
|
75
|
+
oj (3.13.16)
|
75
76
|
overcommit (0.59.1)
|
76
77
|
childprocess (>= 0.6.3, < 5)
|
77
78
|
iniparse (~> 1.4)
|
@@ -172,6 +173,7 @@ PLATFORMS
|
|
172
173
|
DEPENDENCIES
|
173
174
|
async-rspec
|
174
175
|
benchmark-ips
|
176
|
+
dead_end
|
175
177
|
factory_bot
|
176
178
|
grumlin!
|
177
179
|
memory_profiler
|
data/README.md
CHANGED
@@ -143,6 +143,20 @@ class MyRepository
|
|
143
143
|
end
|
144
144
|
```
|
145
145
|
|
146
|
+
##### Overriding standard steps
|
147
|
+
|
148
|
+
Sometimes it may be useful to override standard steps. Grumlin does not allow it by default, but one
|
149
|
+
is still able to override standard steps if they know what they are doing:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
shortcut :addV, override: true do |label|
|
153
|
+
super(label).property(:default, :value)
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
This will create a new shortcut that overrides the standard step `addV` and adds default properties to all vertices
|
158
|
+
created by the repository that uses this shortcut.
|
159
|
+
|
146
160
|
#### Grumlin::Repository
|
147
161
|
`Grumlin::Repository` combines functionality of `Grumlin::Sugar` and `Grumlin::Shortcuts` as well as adds a few useful
|
148
162
|
shortcuts to make gremlin code more rubyish. Can be used as a drop in replacement for `Grumlin::Sugar`. Remember that
|
@@ -167,6 +181,23 @@ class MyRepository
|
|
167
181
|
hasAll(T.label => :triangle, color: color)
|
168
182
|
end
|
169
183
|
|
184
|
+
# `default_vertex_properties` and `default_edge_properties`
|
185
|
+
# override `addV` and `addE` according and inject hashes returned from passed
|
186
|
+
# as properties for newly created vertices and edges.
|
187
|
+
# In case if a repository is inherited, newly defined default properties will be merged to
|
188
|
+
# default properties defined in the parent repository.
|
189
|
+
default_vertex_properties do |_label|
|
190
|
+
{
|
191
|
+
created_at: Time.now.to_i
|
192
|
+
}
|
193
|
+
end
|
194
|
+
|
195
|
+
default_edge_properties do |_label|
|
196
|
+
{
|
197
|
+
created_at: Time.now.to_i
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
170
201
|
# g and __ are already aware of shortcuts
|
171
202
|
query(:triangles_with_color, return_mode: :list) do |color| # :list is the default return mode, also possible: :none, :single, :traversal
|
172
203
|
g.V.hasLabel(:triangle)
|
data/bin/console
CHANGED
data/gremlin_server/Dockerfile
CHANGED
data/grumlin.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.metadata["homepage_uri"] = spec.homepage
|
22
22
|
spec.metadata["source_code_uri"] = "https://github.com/zhulik/grumlin"
|
23
23
|
spec.metadata["changelog_uri"] = "https://github.com/zhulik/grumlin/blob/master/CHANGELOG.md"
|
24
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
24
25
|
|
25
26
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
27
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
@@ -32,7 +33,4 @@ Gem::Specification.new do |spec|
|
|
32
33
|
spec.add_dependency "oj", "~> 3.13"
|
33
34
|
spec.add_dependency "retryable", "~> 3.0"
|
34
35
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
35
|
-
spec.metadata = {
|
36
|
-
"rubygems_mfa_required" => "true"
|
37
|
-
}
|
38
36
|
end
|
data/lib/definitions.yml
CHANGED
@@ -8,9 +8,11 @@ steps:
|
|
8
8
|
- aggregate
|
9
9
|
- and
|
10
10
|
- as
|
11
|
+
- barrier
|
11
12
|
- both
|
12
13
|
- bothE
|
13
14
|
- by
|
15
|
+
- cap
|
14
16
|
- choose
|
15
17
|
- coalesce
|
16
18
|
- constant
|
@@ -19,6 +21,7 @@ steps:
|
|
19
21
|
- drop
|
20
22
|
- elementMap
|
21
23
|
- emit
|
24
|
+
- filter
|
22
25
|
- fold
|
23
26
|
- from
|
24
27
|
- group
|
@@ -37,6 +40,9 @@ steps:
|
|
37
40
|
- label
|
38
41
|
- limit
|
39
42
|
- map
|
43
|
+
- match
|
44
|
+
- max
|
45
|
+
- min
|
40
46
|
- none
|
41
47
|
- not
|
42
48
|
- option
|
@@ -77,9 +83,13 @@ steps:
|
|
77
83
|
- withSack
|
78
84
|
- withSideEffect
|
79
85
|
expressions:
|
86
|
+
cardinality:
|
87
|
+
- list
|
88
|
+
- set
|
89
|
+
- single
|
80
90
|
column:
|
81
|
-
|
82
|
-
|
91
|
+
- keys
|
92
|
+
- values
|
83
93
|
operator:
|
84
94
|
- addAll
|
85
95
|
- and
|
data/lib/grumlin/action.rb
CHANGED
@@ -1,32 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Grumlin
|
4
|
-
class Action
|
5
|
-
|
6
|
-
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
7
|
-
REGULAR_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
4
|
+
class Action < Steppable
|
5
|
+
attr_reader :name, :args, :params, :next_step, :configuration_steps, :previous_step, :shortcut
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
attr_reader :name, :args, :params, :shortcuts, :next_step, :configuration_steps, :previous_step
|
12
|
-
|
13
|
-
def initialize(name, args: [], params: {}, previous_step: nil, shortcuts: {}, pool: Grumlin.default_pool)
|
7
|
+
def initialize(name, args: [], params: {}, previous_step: nil, pool: nil)
|
8
|
+
super()
|
14
9
|
@name = name.to_sym
|
15
10
|
@args = args # TODO: add recursive validation: only json types or Action
|
16
11
|
@params = params # TODO: add recursive validation: only json types
|
17
12
|
@previous_step = previous_step
|
18
|
-
@
|
19
|
-
@pool = pool
|
20
|
-
end
|
21
|
-
|
22
|
-
ALL_STEPS.each do |step|
|
23
|
-
define_method step do |*args, **params|
|
24
|
-
step(step, *args, **params)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def step(name, *args, **params)
|
29
|
-
Action.new(name, args: args, params: params, previous_step: self, shortcuts: @shortcuts, pool: @pool)
|
13
|
+
@shortcut = shortcuts[@name]
|
14
|
+
@pool = pool || Grumlin.default_pool
|
30
15
|
end
|
31
16
|
|
32
17
|
def configuration_step?
|
@@ -45,23 +30,13 @@ module Grumlin
|
|
45
30
|
ALL_STEPS.include?(@name)
|
46
31
|
end
|
47
32
|
|
48
|
-
def shortcut?
|
49
|
-
@shortcuts.key?(@name)
|
50
|
-
end
|
51
|
-
|
52
|
-
def method_missing(name, *args, **params)
|
53
|
-
return step(name, *args, **params) if @shortcuts.key?(name)
|
54
|
-
|
55
|
-
super
|
56
|
-
end
|
57
|
-
|
58
33
|
def ==(other)
|
59
34
|
self.class == other.class &&
|
60
35
|
@name == other.name &&
|
61
36
|
@args == other.args &&
|
62
37
|
@params == other.params &&
|
63
38
|
@previous_step == other.previous_step &&
|
64
|
-
|
39
|
+
shortcuts == other.shortcuts
|
65
40
|
end
|
66
41
|
|
67
42
|
def steps
|
@@ -108,11 +83,5 @@ module Grumlin
|
|
108
83
|
client.write(bytecode(no_return: true))
|
109
84
|
end
|
110
85
|
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def respond_to_missing?(name, _include_private = false)
|
115
|
-
@shortcuts.key?(name)
|
116
|
-
end
|
117
86
|
end
|
118
87
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module Expressions
|
5
|
+
module Cardinality
|
6
|
+
SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :cardinality).map(&:to_sym).freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
extend Expression
|
10
|
+
|
11
|
+
define_steps(SUPPORTED_STEPS, "Cardinality")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -5,6 +5,8 @@ module Grumlin
|
|
5
5
|
module InstanceMethods
|
6
6
|
include Grumlin::Expressions
|
7
7
|
|
8
|
+
extend Forwardable
|
9
|
+
|
8
10
|
UPSERT_RETRY_PARAMS = {
|
9
11
|
on: [Grumlin::AlreadyExistsError, Grumlin::ConcurrentInsertFailedError],
|
10
12
|
sleep_method: ->(n) { Async::Task.current.sleep(n) },
|
@@ -14,12 +16,10 @@ module Grumlin
|
|
14
16
|
|
15
17
|
DEFAULT_ERROR_HANDLING_STRATEGY = ErrorHandlingStrategy.new(mode: :retry, **UPSERT_RETRY_PARAMS)
|
16
18
|
|
17
|
-
|
18
|
-
@__ ||= TraversalStart.new(self.class.shortcuts)
|
19
|
-
end
|
19
|
+
def_delegators :shortcuts, :g, :__
|
20
20
|
|
21
|
-
def
|
22
|
-
|
21
|
+
def shortcuts
|
22
|
+
self.class.shortcuts
|
23
23
|
end
|
24
24
|
|
25
25
|
def drop_vertex(id)
|
data/lib/grumlin/repository.rb
CHANGED
@@ -23,7 +23,7 @@ module Grumlin
|
|
23
23
|
|
24
24
|
define_method name do |*args, query_params: {}, **params, &block|
|
25
25
|
t = instance_exec(*args, **params, &query_block)
|
26
|
-
return t if
|
26
|
+
return t if t.nil? || (t.respond_to?(:empty?) && t.empty?)
|
27
27
|
|
28
28
|
unless t.is_a?(Grumlin::Action)
|
29
29
|
raise WrongQueryResult,
|
@@ -45,8 +45,20 @@ module Grumlin
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
def default_vertex_properties(&block)
|
49
|
+
shortcut :addV, override: true do |*args|
|
50
|
+
super(*args).props(**block.call(*args)) # rubocop:disable Performance/RedundantBlockCall
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_edge_properties(&block)
|
55
|
+
shortcut :addE, override: true do |*args|
|
56
|
+
super(*args).props(**block.call(*args)) # rubocop:disable Performance/RedundantBlockCall
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
48
60
|
def validate_return_mode!(return_mode)
|
49
|
-
return return_mode if RETURN_MODES.
|
61
|
+
return return_mode if RETURN_MODES.include?(return_mode)
|
50
62
|
|
51
63
|
raise ArgumentError, "unsupported return mode #{return_mode}. Supported modes: #{RETURN_MODES.keys}"
|
52
64
|
end
|
@@ -60,9 +72,5 @@ module Grumlin
|
|
60
72
|
raise ArgumentError,
|
61
73
|
"postprocess_with must be a String, Symbol or a callable object, given: #{postprocess_with.class}"
|
62
74
|
end
|
63
|
-
|
64
|
-
def empty_result?(result)
|
65
|
-
result.nil? || (result.respond_to?(:empty?) && result.empty?)
|
66
|
-
end
|
67
75
|
end
|
68
76
|
end
|
@@ -38,7 +38,7 @@ module Grumlin
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def add_request(request)
|
41
|
-
raise RequestAlreadyAddedError if @requests.
|
41
|
+
raise RequestAlreadyAddedError if @requests.include?(request[:requestId])
|
42
42
|
|
43
43
|
Async::Channel.new.tap do |channel|
|
44
44
|
@requests[request[:requestId]] = { request: request, result: [], channel: channel }
|
@@ -73,7 +73,7 @@ module Grumlin
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def ongoing_request?(request_id)
|
76
|
-
@requests.
|
76
|
+
@requests.include?(request_id)
|
77
77
|
end
|
78
78
|
|
79
79
|
def clear
|
data/lib/grumlin/shortcut.rb
CHANGED
@@ -9,8 +9,9 @@ module Grumlin
|
|
9
9
|
def_delegator :@block, :arity
|
10
10
|
def_delegator :@block, :source_location
|
11
11
|
|
12
|
-
def initialize(name, &block)
|
12
|
+
def initialize(name, lazy: true, &block)
|
13
13
|
@name = name
|
14
|
+
@lazy = lazy
|
14
15
|
@block = block
|
15
16
|
end
|
16
17
|
|
@@ -18,6 +19,10 @@ module Grumlin
|
|
18
19
|
@name == other.name && @block == other.block
|
19
20
|
end
|
20
21
|
|
22
|
+
def lazy?
|
23
|
+
@lazy
|
24
|
+
end
|
25
|
+
|
21
26
|
# TODO: to_s, inspect, preview
|
22
27
|
|
23
28
|
def apply(object, *args, **params)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module Shortcuts
|
5
|
+
class Storage
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def [](other)
|
10
|
+
new(other)
|
11
|
+
end
|
12
|
+
|
13
|
+
def empty
|
14
|
+
@empty ||= new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(storage = {})
|
19
|
+
@storage = storage
|
20
|
+
storage.each do |n, s|
|
21
|
+
add(n, s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def_delegator :@storage, :[]
|
26
|
+
def_delegator :@storage, :include?, :known?
|
27
|
+
def_delegator :@storage, :keys, :names
|
28
|
+
|
29
|
+
def ==(other)
|
30
|
+
@storage == other.storage
|
31
|
+
end
|
32
|
+
|
33
|
+
def add(name, shortcut)
|
34
|
+
# not lazy shortcuts are allowed to be overridden
|
35
|
+
if known?(name) && @storage[name] != shortcut && shortcut.lazy?
|
36
|
+
raise ArgumentError,
|
37
|
+
"shortcut '#{name}' already exists"
|
38
|
+
end
|
39
|
+
|
40
|
+
@storage[name] = shortcut
|
41
|
+
|
42
|
+
ac = action_class
|
43
|
+
|
44
|
+
shortcut_methods_module.define_method(name) do |*args, **params|
|
45
|
+
next ac.new(name, args: args, params: params, previous_step: self)
|
46
|
+
end
|
47
|
+
extend_traversal_classes(shortcut) unless shortcut.lazy?
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_from(other)
|
51
|
+
other.storage.each do |name, shortcut|
|
52
|
+
add(name, shortcut)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def g
|
57
|
+
__
|
58
|
+
end
|
59
|
+
|
60
|
+
def __
|
61
|
+
@__ ||= traversal_start_class.new
|
62
|
+
end
|
63
|
+
|
64
|
+
def traversal_start_class
|
65
|
+
@traversal_start_class ||= shortcut_aware_class(TraversalStart)
|
66
|
+
end
|
67
|
+
|
68
|
+
def action_class
|
69
|
+
@action_class ||= shortcut_aware_class(Action)
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
attr_reader :storage
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def shortcut_methods_module
|
79
|
+
@shortcut_methods_module ||= begin
|
80
|
+
shorts = self
|
81
|
+
Module.new do
|
82
|
+
define_method :shortcuts do
|
83
|
+
shorts
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def shortcut_aware_class(base)
|
90
|
+
methods = shortcut_methods_module
|
91
|
+
Class.new(base) do
|
92
|
+
include methods
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def extend_traversal_classes(shortcut)
|
97
|
+
m = Module.new do
|
98
|
+
define_method(shortcut.name, &shortcut.block)
|
99
|
+
end
|
100
|
+
action_class.include(m)
|
101
|
+
traversal_start_class.include(m)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -5,16 +5,16 @@ module Grumlin
|
|
5
5
|
module Upserts
|
6
6
|
extend Grumlin::Shortcuts
|
7
7
|
|
8
|
-
shortcut :upsertV do |label, id, create_properties, update_properties|
|
8
|
+
shortcut :upsertV do |label, id, create_properties = {}, update_properties = {}|
|
9
9
|
self.V(id)
|
10
10
|
.fold
|
11
|
-
.coalesce(
|
11
|
+
.coalesce(
|
12
12
|
__.unfold,
|
13
13
|
__.addV(label).props(**create_properties.merge(T.id => id))
|
14
14
|
).props(**update_properties)
|
15
15
|
end
|
16
16
|
|
17
|
-
shortcut :upsertE do |label, from, to, create_properties, update_properties|
|
17
|
+
shortcut :upsertE do |label, from, to, create_properties = {}, update_properties = {}|
|
18
18
|
self.V(from)
|
19
19
|
.outE(label).where(__.inV.hasId(to))
|
20
20
|
.fold
|
data/lib/grumlin/shortcuts.rb
CHANGED
@@ -11,33 +11,26 @@ module Grumlin
|
|
11
11
|
subclass.shortcuts_from(self)
|
12
12
|
end
|
13
13
|
|
14
|
-
def shortcut(name, shortcut = nil,
|
14
|
+
def shortcut(name, shortcut = nil, override: false, lazy: true, &block)
|
15
15
|
name = name.to_sym
|
16
|
-
|
17
|
-
if Grumlin::Action::REGULAR_STEPS.include?(name)
|
18
|
-
raise ArgumentError,
|
19
|
-
"cannot use names of standard gremlin steps"
|
20
|
-
end
|
16
|
+
lazy = false if override
|
21
17
|
|
22
|
-
if
|
23
|
-
raise ArgumentError,
|
18
|
+
if Grumlin::Action::REGULAR_STEPS.include?(name) && !override
|
19
|
+
raise ArgumentError,
|
20
|
+
"overriding standard gremlin steps is not allowed, if you know what you're doing, pass `override: true`"
|
24
21
|
end
|
25
22
|
|
26
|
-
shortcut
|
23
|
+
raise ArgumentError, "either shortcut or block must be passed" if [shortcut, block].count(&:nil?) != 1
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
shortcuts[name] = shortcut
|
25
|
+
shortcuts.add(name, shortcut || Shortcut.new(name, lazy: lazy, &block))
|
31
26
|
end
|
32
27
|
|
33
28
|
def shortcuts_from(other_shortcuts)
|
34
|
-
other_shortcuts.shortcuts
|
35
|
-
shortcut(name, shortcut)
|
36
|
-
end
|
29
|
+
shortcuts.add_from(other_shortcuts.shortcuts)
|
37
30
|
end
|
38
31
|
|
39
32
|
def shortcuts
|
40
|
-
@shortcuts ||=
|
33
|
+
@shortcuts ||= Storage.new
|
41
34
|
end
|
42
35
|
end
|
43
36
|
end
|
@@ -4,15 +4,17 @@ module Grumlin
|
|
4
4
|
class ShortcutsApplyer
|
5
5
|
class << self
|
6
6
|
def call(steps)
|
7
|
-
return steps
|
7
|
+
return steps if !steps.is_a?(Steps) || !steps.uses_shortcuts?
|
8
8
|
|
9
9
|
shortcuts = steps.shortcuts
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
steps = [
|
12
|
+
*process_steps(steps.configuration_steps, shortcuts),
|
13
|
+
*process_steps(steps.steps, shortcuts)
|
14
|
+
]
|
13
15
|
|
14
16
|
Steps.new(shortcuts).tap do |processed_steps|
|
15
|
-
|
17
|
+
steps.each do |step|
|
16
18
|
processed_steps.add(step.name, args: step.args, params: step.params)
|
17
19
|
end
|
18
20
|
end
|
@@ -22,21 +24,17 @@ module Grumlin
|
|
22
24
|
|
23
25
|
def process_steps(steps, shortcuts) # rubocop:disable Metrics/AbcSize
|
24
26
|
steps.each_with_object([]) do |step, result|
|
25
|
-
args = step.args.map
|
26
|
-
arg.is_a?(Steps) ? ShortcutsApplyer.call(arg) : arg
|
27
|
-
end
|
27
|
+
args = step.args.map { |arg| call(arg) }
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
action = shortcuts[step.name].apply(t, *args, **step.params)
|
32
|
-
next if action.nil? || action == t # Shortcut did not add any steps
|
29
|
+
shortcut = shortcuts[step.name]
|
30
|
+
next result << StepData.new(step.name, args: args, params: step.params) unless shortcut&.lazy?
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
t = shortcuts.__
|
33
|
+
action = shortcut.apply(t, *args, **step.params)
|
34
|
+
next if action.nil? || action == t # Shortcut did not add any steps
|
35
|
+
|
36
|
+
new_steps = call(Steps.from(action))
|
37
|
+
result.concat(new_steps.configuration_steps, new_steps.steps)
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
class Steppable
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
START_STEPS = Grumlin.definitions.dig(:steps, :start).map(&:to_sym).freeze
|
8
|
+
REGULAR_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
9
|
+
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
10
|
+
|
11
|
+
ALL_STEPS = START_STEPS + CONFIGURATION_STEPS + REGULAR_STEPS
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
return if respond_to?(:shortcuts)
|
15
|
+
|
16
|
+
raise RuntimerError,
|
17
|
+
"steppable must not be initialized directly, use Grumlin::Shortcuts::Storage#g or #__ instead"
|
18
|
+
end
|
19
|
+
|
20
|
+
ALL_STEPS.each do |step|
|
21
|
+
define_method step do |*args, **params|
|
22
|
+
shortcuts.action_class.new(step, args: args, params: params, previous_step: self)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def step(name, *args, **params)
|
27
|
+
shortcuts.action_class.new(name, args: args, params: params, previous_step: self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def_delegator :shortcuts, :__
|
31
|
+
end
|
32
|
+
end
|
data/lib/grumlin/steps.rb
CHANGED
@@ -11,7 +11,7 @@ module Grumlin
|
|
11
11
|
shortcuts = action.shortcuts
|
12
12
|
actions = []
|
13
13
|
|
14
|
-
until action.nil?
|
14
|
+
until action.nil? || action.is_a?(TraversalStart)
|
15
15
|
actions.unshift(action)
|
16
16
|
action = action.previous_step
|
17
17
|
end
|
@@ -56,7 +56,7 @@ module Grumlin
|
|
56
56
|
|
57
57
|
def shortcuts?(steps_ary)
|
58
58
|
steps_ary.any? do |step|
|
59
|
-
@shortcuts.
|
59
|
+
@shortcuts.known?(step.name) || step.args.any? do |arg|
|
60
60
|
arg.is_a?(Steps) ? arg.uses_shortcuts? : false
|
61
61
|
end
|
62
62
|
end
|
data/lib/grumlin/sugar.rb
CHANGED
@@ -6,12 +6,10 @@ module Grumlin
|
|
6
6
|
base.include(Grumlin::Expressions)
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def g(shortcuts = {})
|
14
|
-
Grumlin::TraversalStart.new(shortcuts)
|
9
|
+
%i[__ g].each do |name|
|
10
|
+
define_method name do |cuts = Shortcuts::Storage.empty|
|
11
|
+
cuts.send(name)
|
12
|
+
end
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
@@ -1,39 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Grumlin
|
4
|
-
class TraversalStart
|
5
|
-
START_STEPS = Grumlin.definitions.dig(:steps, :start).map(&:to_sym).freeze
|
6
|
-
REGULAR_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
7
|
-
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
8
|
-
|
9
|
-
ALL_STEPS = START_STEPS + CONFIGURATION_STEPS + REGULAR_STEPS
|
10
|
-
|
11
|
-
ALL_STEPS.each do |step|
|
12
|
-
define_method step do |*args, **params|
|
13
|
-
step(step, *args, **params)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
attr_reader :shortcuts
|
18
|
-
|
19
|
-
def initialize(shortcuts)
|
20
|
-
@shortcuts = shortcuts
|
21
|
-
end
|
22
|
-
|
23
|
-
def step(name, *args, **params)
|
24
|
-
Action.new(name, args: args, params: params, shortcuts: @shortcuts)
|
25
|
-
end
|
26
|
-
|
27
|
-
def method_missing(name, *args, **params)
|
28
|
-
return step(name, *args, **params) if @shortcuts.key?(name)
|
29
|
-
|
30
|
-
super
|
31
|
-
end
|
32
|
-
|
33
|
-
def __
|
34
|
-
@__ ||= TraversalStart.new(@shortcuts) # TODO: allow only regular and start steps
|
35
|
-
end
|
36
|
-
|
4
|
+
class TraversalStart < Steppable
|
37
5
|
def to_s(*)
|
38
6
|
self.class.to_s
|
39
7
|
end
|
@@ -41,11 +9,5 @@ module Grumlin
|
|
41
9
|
def inspect
|
42
10
|
self.class.inspect
|
43
11
|
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def respond_to_missing?(name, _include_private = false)
|
48
|
-
@shortcuts.key?(name)
|
49
|
-
end
|
50
12
|
end
|
51
13
|
end
|
data/lib/grumlin/version.rb
CHANGED
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.
|
4
|
+
version: 0.20.0
|
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-
|
11
|
+
date: 2022-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-pool
|
@@ -108,6 +108,8 @@ files:
|
|
108
108
|
- docker-compose.yml
|
109
109
|
- gremlin_server/Dockerfile
|
110
110
|
- gremlin_server/tinkergraph-empty.properties
|
111
|
+
- gremlin_server/tinkergraph-gremlin/lib/tinkergraph-gremlin-3.5.3.jar
|
112
|
+
- gremlin_server/tinkergraph-gremlin/plugin/tinkergraph-gremlin-3.5.3.jar
|
111
113
|
- grumlin.gemspec
|
112
114
|
- lib/async/channel.rb
|
113
115
|
- lib/definitions.yml
|
@@ -116,6 +118,7 @@ files:
|
|
116
118
|
- lib/grumlin/benchmark/repository.rb
|
117
119
|
- lib/grumlin/client.rb
|
118
120
|
- lib/grumlin/edge.rb
|
121
|
+
- lib/grumlin/expressions/cardinality.rb
|
119
122
|
- lib/grumlin/expressions/column.rb
|
120
123
|
- lib/grumlin/expressions/expression.rb
|
121
124
|
- lib/grumlin/expressions/operator.rb
|
@@ -135,9 +138,11 @@ files:
|
|
135
138
|
- lib/grumlin/shortcut.rb
|
136
139
|
- lib/grumlin/shortcuts.rb
|
137
140
|
- lib/grumlin/shortcuts/properties.rb
|
141
|
+
- lib/grumlin/shortcuts/storage.rb
|
138
142
|
- lib/grumlin/shortcuts/upserts.rb
|
139
143
|
- lib/grumlin/shortcuts_applyer.rb
|
140
144
|
- lib/grumlin/step_data.rb
|
145
|
+
- lib/grumlin/steppable.rb
|
141
146
|
- lib/grumlin/steps.rb
|
142
147
|
- lib/grumlin/steps_serializers/bytecode.rb
|
143
148
|
- lib/grumlin/steps_serializers/human_readable_bytecode.rb
|
@@ -159,6 +164,9 @@ homepage: https://github.com/zhulik/grumlin
|
|
159
164
|
licenses:
|
160
165
|
- MIT
|
161
166
|
metadata:
|
167
|
+
homepage_uri: https://github.com/zhulik/grumlin
|
168
|
+
source_code_uri: https://github.com/zhulik/grumlin
|
169
|
+
changelog_uri: https://github.com/zhulik/grumlin/blob/master/CHANGELOG.md
|
162
170
|
rubygems_mfa_required: 'true'
|
163
171
|
post_install_message:
|
164
172
|
rdoc_options: []
|