grumlin 0.8.0 → 0.11.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: 22dad640b5ac86f86381b9bc9fab03989e7b8c42c4b19234efc6b3a223d07055
4
- data.tar.gz: c0cea0f26f1e5a5a9ef1c6ab96335bf24e7f642968030b2b1f1c0a74210898d7
3
+ metadata.gz: 0f0edafd4d46b787eb3f8e0ec4032948bdb4de865e4de3199606fb470dc16ef3
4
+ data.tar.gz: f23ba59dfb18dabe70fc860c38ea4c1777214b4a37e04771b24210d90f449612
5
5
  SHA512:
6
- metadata.gz: 71b7e970733edc7db87736c449008389b47431d41c12382c426b0db348e106047343d279e3d8901d76dd44175478279b4c2e22cd896b690c9d63eedbf605b6ec
7
- data.tar.gz: 82f71e74fb61435de9d6a86fa8cceb4cea32cd8a87f91c6a941bbfbd622a21b67b434f3ccbe298f94265edb9999faa33ea4f80148a56a1e39c6491a575df1ae6
6
+ metadata.gz: 4629a25995953c6617a45721d7082baee59b76425636f6a4536308220bae3e7cb72b571317102339b1888c0e430dbe73320c12f44518940f45c67db829a9a265
7
+ data.tar.gz: fae1a56f95150f82da47a886da5e4b4a7ab0f725f66e68af61f6456c9a2f1af2cefc580ebf793cba612f0ceeda0b782361476a38511019062cc1534ad98fdb3c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grumlin (0.8.0)
4
+ grumlin (0.11.0)
5
5
  async-pool (~> 0.3)
6
6
  async-websocket (~> 0.19)
7
7
  oj (~> 3.12)
@@ -64,7 +64,7 @@ GEM
64
64
  nio4r (2.5.8)
65
65
  nokogiri (1.11.7-x86_64-linux)
66
66
  racc (~> 1.4)
67
- oj (3.13.4)
67
+ oj (3.13.6)
68
68
  overcommit (0.57.0)
69
69
  childprocess (>= 0.6.3, < 5)
70
70
  iniparse (~> 1.4)
@@ -7,7 +7,7 @@ module Grumlin
7
7
  # TODO: add other steps
8
8
  SUPPORTED_STEPS = %w[E V addE addV as by coalesce count dedup drop elementMap emit fold from group groupCount has
9
9
  hasId hasLabel hasNot in inV label limit not order out outE path project property repeat select
10
- to unfold valueMap values where].freeze
10
+ to unfold union valueMap values where].freeze
11
11
 
12
12
  def initialize(name, *args, previous_step: nil)
13
13
  @name = name
@@ -3,7 +3,7 @@
3
3
  module Grumlin
4
4
  # Incapsulates logic of converting step chains and step arguments to queries that can be sent to the server
5
5
  # and to human readable strings.
6
- class Bytecode
6
+ class Bytecode < TypedValue
7
7
  class NoneStep
8
8
  def to_bytecode
9
9
  ["none"]
@@ -13,6 +13,8 @@ module Grumlin
13
13
  NONE_STEP = NoneStep.new
14
14
 
15
15
  def initialize(step, no_return: false)
16
+ super(type: "Bytecode")
17
+
16
18
  @step = step
17
19
  @no_return = no_return
18
20
  end
@@ -22,27 +24,12 @@ module Grumlin
22
24
  end
23
25
  alias to_s inspect
24
26
 
25
- def to_query
26
- {
27
- requestId: SecureRandom.uuid,
28
- op: "bytecode",
29
- processor: "traversal",
30
- args: {
31
- gremlin: to_bytecode,
32
- aliases: { g: :g }
33
- }
34
- }
35
- end
36
-
37
27
  def to_readable_bytecode
38
28
  @to_readable_bytecode ||= steps.map { |s| serialize_arg(s, serialization_method: :to_readable_bytecode) }
39
29
  end
40
30
 
41
- def to_bytecode
42
- @to_bytecode ||= {
43
- "@type": "g:Bytecode",
44
- "@value": { step: (steps + (@no_return ? [NONE_STEP] : [])).map { |s| serialize_arg(s) } }
45
- }
31
+ def value
32
+ { step: (steps + (@no_return ? [NONE_STEP] : [])).map { |s| serialize_arg(s) } }
46
33
  end
47
34
 
48
35
  private
@@ -97,7 +97,7 @@ module Grumlin
97
97
  def write(bytecode)
98
98
  raise NotConnectedError unless connected?
99
99
 
100
- request = bytecode.to_query
100
+ request = to_query(bytecode.to_bytecode)
101
101
  channel = @request_dispatcher.add_request(request)
102
102
  @transport.write(request)
103
103
 
@@ -120,5 +120,17 @@ module Grumlin
120
120
  def build_transport
121
121
  Transport.new(@url, parent: @parent, **@client_options)
122
122
  end
123
+
124
+ def to_query(bytecode)
125
+ {
126
+ requestId: SecureRandom.uuid,
127
+ op: "bytecode",
128
+ processor: "traversal",
129
+ args: {
130
+ gremlin: bytecode,
131
+ aliases: { g: :g }
132
+ }
133
+ }
134
+ end
123
135
  end
124
136
  end
data/lib/grumlin/order.rb CHANGED
@@ -9,7 +9,7 @@ module Grumlin
9
9
  name = "@#{step}"
10
10
  return instance_variable_get(name) if instance_variable_defined?(name)
11
11
 
12
- instance_variable_set(name, TypedValue.new("Order", step))
12
+ instance_variable_set(name, TypedValue.new(type: "Order", value: step))
13
13
  end
14
14
  end
15
15
  end
data/lib/grumlin/p.rb CHANGED
@@ -3,12 +3,40 @@
3
3
  module Grumlin
4
4
  module P
5
5
  module P
6
- %w[within].each do |step|
7
- define_method step do |*args|
8
- { # TODO: replace with a TypedValue?
9
- "@type": "g:P",
10
- "@value": { predicate: "within", value: { "@type": "g:List", "@value": args } }
11
- }
6
+ class Predicate < TypedValue
7
+ def initialize(name, args:, arg_type: nil)
8
+ super(type: "P")
9
+ @name = name
10
+ @args = args
11
+ @arg_type = arg_type
12
+ end
13
+
14
+ def value
15
+ @value ||=
16
+ {
17
+ predicate: @name,
18
+ value: TypedValue.new(type: @arg_type, value: @args).to_bytecode
19
+ }
20
+ end
21
+ end
22
+
23
+ # TODO: support more predicates
24
+ %w[eq neq].each do |predicate|
25
+ define_method predicate do |*args|
26
+ Predicate.new(predicate, args: args[0])
27
+ end
28
+ end
29
+
30
+ %w[within without].each do |predicate|
31
+ define_method predicate do |*args|
32
+ args = if args.count == 1 && args[0].is_a?(Array)
33
+ args[0]
34
+ elsif args.count == 1 && args[0].is_a?(Set)
35
+ args[0].to_a
36
+ else
37
+ args.to_a
38
+ end
39
+ Predicate.new(predicate, args: args, arg_type: "List")
12
40
  end
13
41
  end
14
42
  end
data/lib/grumlin/pop.rb CHANGED
@@ -9,7 +9,7 @@ module Grumlin
9
9
  name = "@#{step}"
10
10
  return instance_variable_get(name) if instance_variable_defined?(name)
11
11
 
12
- instance_variable_set(name, TypedValue.new("Pop", step))
12
+ instance_variable_set(name, TypedValue.new(type: "Pop", value: step))
13
13
  end
14
14
  end
15
15
  end
@@ -44,7 +44,7 @@ module Grumlin
44
44
 
45
45
  request = @requests[request_id]
46
46
 
47
- check_errors!(response[:status])
47
+ check_errors!(response[:status], request[:request])
48
48
 
49
49
  case SUCCESS[response.dig(:status, :code)]
50
50
  when :success
@@ -77,9 +77,9 @@ module Grumlin
77
77
 
78
78
  private
79
79
 
80
- def check_errors!(status)
80
+ def check_errors!(status, query)
81
81
  if (error = ERRORS[status[:code]])
82
- raise(error, status)
82
+ raise error.new(status, query)
83
83
  end
84
84
 
85
85
  return unless SUCCESS[status[:code]].nil?
data/lib/grumlin/step.rb CHANGED
@@ -10,8 +10,18 @@ module Grumlin
10
10
  end
11
11
 
12
12
  def next
13
- @enum ||= toList.to_enum
14
- @enum.next
13
+ to_enum.next
14
+ end
15
+
16
+ def hasNext # rubocop:disable Naming/MethodName
17
+ to_enum.peek
18
+ true
19
+ rescue StopIteration
20
+ false
21
+ end
22
+
23
+ def to_enum
24
+ @to_enum ||= toList.to_enum
15
25
  end
16
26
 
17
27
  def toList
data/lib/grumlin/t.rb CHANGED
@@ -9,7 +9,7 @@ module Grumlin
9
9
  name = "@#{step}"
10
10
  return instance_variable_get(name) if instance_variable_defined?(name)
11
11
 
12
- instance_variable_set(name, TypedValue.new("T", step))
12
+ instance_variable_set(name, TypedValue.new(type: "T", value: step))
13
13
  end
14
14
  end
15
15
  end
@@ -1,19 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Grumlin
4
- # TODO: find a better name
5
4
  class TypedValue
6
- def initialize(type, value)
5
+ attr_reader :type, :value
6
+
7
+ def initialize(type: nil, value: nil)
7
8
  @type = type
8
9
  @value = value
9
10
  end
10
11
 
11
12
  def to_bytecode
12
- @to_bytecode ||= { "@type": "g:#{@type}", "@value": @value }
13
+ @to_bytecode ||= if type.nil?
14
+ value
15
+ else
16
+ {
17
+ "@type": "g:#{type}",
18
+ "@value": value
19
+ }
20
+ end
13
21
  end
14
22
 
15
23
  def inspect
16
- "<#{@type}.#{@value}>"
24
+ "<#{type}.#{value}>"
17
25
  end
18
26
  alias to_s inspect
19
27
  alias to_readable_bytecode inspect
data/lib/grumlin/u.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Grumlin
4
4
  module U
5
5
  # TODO: add other start steps
6
- SUPPORTED_START_STEPS = %w[V addV count has out unfold values].freeze
6
+ SUPPORTED_START_STEPS = %w[V addV count fold has out repeat unfold values].freeze
7
7
 
8
8
  class << self
9
9
  SUPPORTED_START_STEPS.each do |step|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Grumlin
4
- VERSION = "0.8.0"
4
+ VERSION = "0.11.0"
5
5
  end
data/lib/grumlin.rb CHANGED
@@ -57,11 +57,12 @@ module Grumlin
57
57
  class UnknownTypeError < ProtocolError; end
58
58
 
59
59
  class StatusError < Error
60
- attr_reader :status
60
+ attr_reader :status, :query
61
61
 
62
- def initialize(status)
62
+ def initialize(status, query)
63
63
  super(status[:message])
64
64
  @status = status
65
+ @query = query
65
66
  end
66
67
  end
67
68
 
@@ -103,16 +104,10 @@ module Grumlin
103
104
  @client_concurrency = 5
104
105
  @client_factory = ->(url, parent) { Grumlin::Client.new(url, parent: parent) }
105
106
  end
106
-
107
- def default_pool
108
- @default_pool ||= Async::Pool::Controller.new(Grumlin::Client::PoolResource, limit: pool_size)
109
- end
110
-
111
- def reset!
112
- @default_pool = nil
113
- end
114
107
  end
115
108
 
109
+ @pool_mutex = Mutex.new
110
+
116
111
  class << self
117
112
  def configure
118
113
  yield config
@@ -123,14 +118,26 @@ module Grumlin
123
118
  end
124
119
 
125
120
  def default_pool
126
- config.default_pool
121
+ if Thread.current.thread_variable_get(:grumlin_default_pool)
122
+ return Thread.current.thread_variable_get(:grumlin_default_pool)
123
+ end
124
+
125
+ @pool_mutex.synchronize do
126
+ Thread.current.thread_variable_set(:grumlin_default_pool,
127
+ Async::Pool::Controller.new(Grumlin::Client::PoolResource,
128
+ limit: config.pool_size))
129
+ end
127
130
  end
128
131
 
129
132
  def close
130
- default_pool.wait while default_pool.busy?
131
-
132
- default_pool.close
133
- config.reset!
133
+ return if Thread.current.thread_variable_get(:grumlin_default_pool).nil?
134
+
135
+ @pool_mutex.synchronize do
136
+ pool = Thread.current.thread_variable_get(:grumlin_default_pool)
137
+ pool.wait while pool.busy?
138
+ pool.close
139
+ Thread.current.thread_variable_set(:grumlin_default_pool, nil)
140
+ end
134
141
  end
135
142
  end
136
143
  end
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.8.0
4
+ version: 0.11.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: 2021-09-07 00:00:00.000000000 Z
11
+ date: 2021-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-pool