pacer 1.4.2-java → 1.5.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +20 -1
  3. data/README.md +29 -15
  4. data/Rakefile +0 -1
  5. data/lib/pacer/core/graph/edges_route.rb +5 -5
  6. data/lib/pacer/core/graph/vertices_route.rb +7 -7
  7. data/lib/pacer/core/route.rb +39 -23
  8. data/lib/pacer/filter/collection_filter.rb +6 -5
  9. data/lib/pacer/filter/empty_filter.rb +1 -0
  10. data/lib/pacer/filter/loop_filter.rb +13 -2
  11. data/lib/pacer/filter/property_filter.rb +1 -1
  12. data/lib/pacer/filter/property_filter/filters.rb +1 -1
  13. data/lib/pacer/filter/uniq_section.rb +56 -0
  14. data/lib/pacer/filter/where_filter/node_visitor.rb +13 -12
  15. data/lib/pacer/graph/graph_ml.rb +4 -2
  16. data/lib/pacer/graph/graph_transactions_mixin.rb +26 -0
  17. data/lib/pacer/graph/pacer_graph.rb +1 -1
  18. data/lib/pacer/loader.rb +2 -1
  19. data/lib/pacer/pipe/collection_filter_pipe.rb +2 -0
  20. data/lib/pacer/pipe/id_collection_filter_pipe.rb +12 -2
  21. data/lib/pacer/pipe/loop_pipe.rb +1 -1
  22. data/lib/pacer/pipe/property_comparison_pipe.rb +6 -6
  23. data/lib/pacer/pipes.rb +5 -4
  24. data/lib/pacer/route/mixin/bulk_operations.rb +22 -21
  25. data/lib/pacer/support/enumerable.rb +0 -4
  26. data/lib/pacer/transform/identity.rb +10 -0
  27. data/lib/pacer/transform/lookup_ids.rb +2 -2
  28. data/lib/pacer/version.rb +3 -4
  29. data/lib/pacer/wrappers/edge_wrapper.rb +3 -1
  30. data/lib/pacer/wrappers/element_wrapper.rb +5 -3
  31. data/lib/pacer/wrappers/vertex_wrapper.rb +8 -2
  32. data/pom.xml +3 -30
  33. data/spec/pacer/blueprints/neo4j2_spec.rb +62 -0
  34. data/spec/pacer/blueprints/neo4j_spec.rb +6 -4
  35. data/spec/pacer/core/graph/graph_route_spec.rb +11 -3
  36. data/spec/pacer/core/route_spec.rb +1 -1
  37. data/spec/pacer/filter/empty_filter_spec.rb +1 -1
  38. data/spec/pacer/route/mixin/bulk_operations_spec.rb +11 -3
  39. data/spec/pacer/wrapper/element_wrapper_spec.rb +15 -15
  40. data/spec/pacer/wrapper/vertex_wrapper_spec.rb +4 -4
  41. data/spec/spec_helper.rb +5 -4
  42. data/spec/support/graph_runner.rb +11 -0
  43. data/spec/support/use_transactions.rb +4 -0
  44. metadata +7 -4
  45. data/lib/pacer/support/array.rb +0 -18
@@ -17,8 +17,10 @@ module Pacer
17
17
  rescue java.net.MalformedURLException
18
18
  stream = java.io.FileInputStream.new path
19
19
  end
20
- graph.send :creating_elements do
21
- com.tinkerpop.blueprints.util.io.graphml.GraphMLReader.input_graph graph.blueprints_graph, stream
20
+ graph.transaction(nesting: true) do
21
+ graph.send :creating_elements do
22
+ com.tinkerpop.blueprints.util.io.graphml.GraphMLReader.input_graph graph.blueprints_graph, stream
23
+ end
22
24
  end
23
25
  true
24
26
  ensure
@@ -6,6 +6,10 @@ module Pacer
6
6
  threadlocal_graph_info.fetch(:tx_depth, 0) > 0
7
7
  end
8
8
 
9
+ def in_read_transaction?
10
+ threadlocal_graph_info.fetch(:read_tx_depth, 0) > 0
11
+ end
12
+
9
13
  # Basic usage:
10
14
  #
11
15
  # graph.transaction do |commit, rollback|
@@ -47,6 +51,24 @@ module Pacer
47
51
  end
48
52
  end
49
53
 
54
+ def read_transaction
55
+ tgi = threadlocal_graph_info
56
+ read_tx_depth = tgi[:read_tx_depth] ||= 0
57
+ tgi[:read_tx_depth] += 1
58
+ # Blueprints auto-starts the transaction
59
+ yield
60
+ ensure
61
+ rtd = tgi[:read_tx_depth] -= 1
62
+ if rtd == 0 and tgi[:tx_depth] == 0 and blueprints_graph.is_a? TransactionalGraph
63
+ # rollback after the bottom read transaction (no changes outside a real transaction block should have been possible)
64
+ blueprints_graph.stopTransaction TransactionalGraph::Conclusion::FAILURE
65
+ end
66
+ end
67
+
68
+ def reopen_read_transaction
69
+ # override this implementation-specific hook if needed (see pacer-neo4j)
70
+ end
71
+
50
72
  # Set this to true if you don't want to use transactions.
51
73
  #
52
74
  # By default, transactions are enabled.
@@ -71,6 +93,8 @@ module Pacer
71
93
  commit_implicit_transaction
72
94
  when :rollback
73
95
  rollback_implicit_transaction
96
+ else
97
+ fail Pacer::ClientError, "invalid value for #implicit_transaction: #{ implicit_transaction.inspect }"
74
98
  end
75
99
  end
76
100
 
@@ -135,11 +159,13 @@ module Pacer
135
159
  end
136
160
  puts "transaction committed" if Pacer.verbose == :very
137
161
  blueprints_graph.stopTransaction TransactionalGraph::Conclusion::SUCCESS
162
+ reopen_read_transaction
138
163
  on_commit_block.call if on_commit_block
139
164
  end
140
165
  rollback = ->(message = nil) do
141
166
  puts ["transaction rolled back", message].compact.join(': ') if Pacer.verbose == :very
142
167
  blueprints_graph.stopTransaction TransactionalGraph::Conclusion::FAILURE
168
+ reopen_read_transaction
143
169
  end
144
170
  [commit, rollback]
145
171
  end
@@ -204,7 +204,7 @@ module Pacer
204
204
  end
205
205
 
206
206
  def features
207
- blueprints_graph.features
207
+ blueprints_graph.getFeatures
208
208
  end
209
209
 
210
210
  def inspect
@@ -53,7 +53,6 @@ require 'pacer/blueprints/group_vertex'
53
53
 
54
54
  require 'pacer/blueprints/payload_elements'
55
55
 
56
- require 'pacer/support/array'
57
56
  require 'pacer/support/array_list'
58
57
  require 'pacer/support/enumerable'
59
58
  require 'pacer/support/proc'
@@ -79,7 +78,9 @@ require 'pacer/filter/block_filter'
79
78
  require 'pacer/filter/object_filter'
80
79
  require 'pacer/filter/random_filter'
81
80
  require 'pacer/filter/limit_section_filter'
81
+ require 'pacer/filter/uniq_section'
82
82
 
83
+ require 'pacer/transform/identity'
83
84
  require 'pacer/transform/branch'
84
85
  require 'pacer/transform/cap'
85
86
  require 'pacer/transform/stream_sort'
@@ -4,6 +4,8 @@ module Pacer
4
4
  AbstractCollectionFilterPipe = com.tinkerpop.pipes.filter.CollectionFilterPipe
5
5
  end
6
6
 
7
+ # This seemingly-useless class only exists because the class in Pipes
8
+ # is marked abstract despite being complete.
7
9
  class CollectionFilterPipe < Renamed::AbstractCollectionFilterPipe
8
10
  end
9
11
  end
@@ -1,13 +1,23 @@
1
1
  module Pacer::Pipes
2
2
  class IdCollectionFilterPipe < RubyPipe
3
+ import com.tinkerpop.blueprints.Contains
4
+ attr_reader :contains_in
5
+
3
6
  def initialize(ids, comparison)
4
7
  super()
5
8
  @ids = Set[*ids]
6
- @comparison = comparison
9
+ if comparison == Contains::IN
10
+ @contains_in = true
11
+ elsif
12
+ comparison == Contains::NOT_IN
13
+ @contains_in = false
14
+ else
15
+ fail InternalError, "Unknown comparison type for ID collection filter"
16
+ end
7
17
  end
8
18
 
9
19
  def processNextStart
10
- if @comparison == Pacer::Pipes::EQUAL
20
+ if contains_in
11
21
  while true
12
22
  element = @starts.next
13
23
  if element and @ids.include? element.getId
@@ -1,6 +1,7 @@
1
1
  module Pacer::Pipes
2
2
  class LoopPipe < RubyPipe
3
3
  import java.util.ArrayList
4
+ BlueprintsGraph = com.tinkerpop.blueprints.Graph
4
5
 
5
6
  def initialize(graph, looping_pipe, control_block)
6
7
  super()
@@ -42,7 +43,6 @@ module Pacer::Pipes
42
43
 
43
44
  def processNextStart
44
45
  while true
45
- # FIXME: hasNext shouldn't be raising an exception...
46
46
  has_next = looping_pipe.hasNext
47
47
  if has_next
48
48
  element = looping_pipe.next
@@ -15,17 +15,17 @@ module Pacer::Pipes
15
15
  l = obj.getProperty(@left)
16
16
  r = obj.getProperty(@right)
17
17
  case @filter
18
- when FilterPipe::Filter::EQUAL
18
+ when Compare::EQUAL
19
19
  return obj if l == r
20
- when FilterPipe::Filter::NOT_EQUAL
20
+ when Compare::NOT_EQUAL
21
21
  return obj if l != r
22
- when FilterPipe::Filter::GREATER_THAN
22
+ when Compare::GREATER_THAN
23
23
  return obj if l and r and l > r
24
- when FilterPipe::Filter::LESS_THAN
24
+ when Compare::LESS_THAN
25
25
  return obj if l and r and l < r
26
- when FilterPipe::Filter::GREATER_THAN_EQUAL
26
+ when Compare::GREATER_THAN_EQUAL
27
27
  return obj if l and r and l >= r
28
- when FilterPipe::Filter::LESS_THAN_EQUAL
28
+ when Compare::LESS_THAN_EQUAL
29
29
  return obj if l and r and l <= r
30
30
  end
31
31
  end
@@ -11,15 +11,16 @@ module Pacer
11
11
  import com.tinkerpop.pipes.filter.RangeFilterPipe
12
12
  import com.tinkerpop.pipes.filter.FilterPipe
13
13
 
14
- import com.tinkerpop.gremlin.pipes.transform.IdPipe
15
- import com.tinkerpop.gremlin.pipes.transform.PropertyPipe
14
+ import com.tinkerpop.pipes.transform.IdPipe
15
+ import com.tinkerpop.pipes.transform.PropertyPipe
16
16
 
17
17
  IN = com.tinkerpop.blueprints.Direction::IN
18
18
  OUT = com.tinkerpop.blueprints.Direction::OUT
19
19
  BOTH = com.tinkerpop.blueprints.Direction::BOTH
20
20
 
21
- EQUAL = FilterPipe::Filter::EQUAL
22
- NOT_EQUAL = FilterPipe::Filter::NOT_EQUAL
21
+ import com.tinkerpop.blueprints.Compare
22
+ EQUAL = Compare::EQUAL
23
+ NOT_EQUAL = Compare::NOT_EQUAL
23
24
  #GREATER_THAN, LESS_THAN, GREATER_THAN_EQUAL, LESS_THAN_EQUAL
24
25
  end
25
26
 
@@ -19,33 +19,34 @@ module Pacer::Routes
19
19
  # +size+ records.
20
20
  def bulk_job(size = nil, target_graph = nil, pre_commit = nil)
21
21
  target_graph ||= graph
22
- if target_graph and not target_graph.in_bulk_job?
23
- begin
24
- target_graph.in_bulk_job = true
25
- size ||= target_graph.bulk_job_size
26
- counter = 0
27
- target_graph.transaction(nesting: true) do |commit, rollback|
22
+ graph.read_transaction do
23
+ if target_graph and not target_graph.in_bulk_job?
24
+ begin
25
+ target_graph.in_bulk_job = true
26
+ size ||= target_graph.bulk_job_size
27
+ counter = 0
28
28
  print "Bulk job ->" if Pacer.verbose?
29
29
  each_slice(size) do |slice|
30
- print " #{counter}" if Pacer.verbose?
31
- counter += size
32
- slice.each do |element|
33
- yield element
30
+ target_graph.transaction(nesting: true) do
31
+ print " #{counter}" if Pacer.verbose?
32
+ counter += size
33
+ slice.each do |element|
34
+ yield element
35
+ end
36
+ pre_commit.call if pre_commit
34
37
  end
35
- pre_commit.call if pre_commit
36
- commit.call
37
38
  end
39
+ ensure
40
+ puts '!' if Pacer.verbose?
41
+ target_graph.in_bulk_job = false
38
42
  end
39
- ensure
40
- puts '!' if Pacer.verbose?
41
- target_graph.in_bulk_job = false
42
- end
43
- elsif target_graph
44
- each do |element|
45
- yield element
43
+ elsif target_graph
44
+ each do |element|
45
+ yield element
46
+ end
47
+ else
48
+ raise 'No graph in route for bulk job'
46
49
  end
47
- else
48
- raise 'No graph in route for bulk job'
49
50
  end
50
51
  end
51
52
  end
@@ -47,10 +47,6 @@ module Enumerable
47
47
  Pacer::Pipes::EnumerablePipe.new self
48
48
  end
49
49
 
50
- def +(other)
51
- Pacer::Pipes::MultiPipe.new [self, other]
52
- end
53
-
54
50
  # NOTE: if this is a collection of wrapped vertices or edges, Java pipes
55
51
  # may crash with something like:
56
52
  #
@@ -0,0 +1,10 @@
1
+ module Pacer
2
+ module Routes
3
+ module RouteOperations
4
+ def identity
5
+ chain_route route_name: 'identity', pipe_class: com.tinkerpop.pipes.IdentityPipe
6
+ end
7
+ end
8
+ end
9
+ end
10
+
@@ -16,8 +16,8 @@ module Pacer
16
16
 
17
17
  module Transform
18
18
  module LookupIds
19
- import com.tinkerpop.gremlin.pipes.transform.IdVertexPipe
20
- import com.tinkerpop.gremlin.pipes.transform.IdEdgePipe
19
+ import com.tinkerpop.pipes.transform.IdVertexPipe
20
+ import com.tinkerpop.pipes.transform.IdEdgePipe
21
21
 
22
22
  def attach_pipe(end_pipe)
23
23
  fail ClientError, 'Can not look up elements without the graph' unless graph
@@ -1,14 +1,13 @@
1
1
  module Pacer
2
2
  unless const_defined? :VERSION
3
- VERSION = "1.4.2"
3
+ VERSION = "1.5.1"
4
4
 
5
5
  JAR = "pacer-#{ VERSION }-standalone.jar"
6
6
  JAR_PATH = "lib/#{ JAR }"
7
7
 
8
8
  START_TIME = Time.now
9
9
 
10
- BLUEPRINTS_VERSION = "2.3.0"
11
- PIPES_VERSION = "2.3.0"
12
- GREMLIN_VERSION = "2.3.0"
10
+ BLUEPRINTS_VERSION = "2.6.0-SNAPSHOT"
11
+ PIPES_VERSION = "2.5.0"
13
12
  end
14
13
  end
@@ -87,7 +87,9 @@ module Pacer::Wrappers
87
87
  # standard ruby console representation of an instantiated object.
88
88
  # @return [String]
89
89
  def inspect
90
- "#<E[#{element_id}]:#{display_name}>"
90
+ graph.read_transaction do
91
+ "#<E[#{element_id}]:#{display_name}>"
92
+ end
91
93
  end
92
94
 
93
95
  # Returns the display name of the edge.
@@ -122,15 +122,17 @@ module Pacer::Wrappers
122
122
  # @param [#to_s] key the property name
123
123
  # @param [Object] value the value to set the property to
124
124
  def []=(key, value)
125
- value = graph.encode_property(value)
125
+ begin
126
+ value = graph.encode_property(value)
127
+ rescue Exception => e
128
+ throw Pacer::ClientError.new "Unable to serialize #{ key }: #{ value.class }"
129
+ end
126
130
  key = key.to_s
127
131
  if value
128
132
  element.setProperty(key, value)
129
133
  else
130
134
  element.removeProperty(key)
131
135
  end
132
- rescue Exception => e
133
- throw Pacer::ClientError.new "Unable to serialize #{ key }: #{ value.class }"
134
136
  end
135
137
 
136
138
  # Specialize result to return self for elements.
@@ -75,7 +75,11 @@ module Pacer::Wrappers
75
75
  # @yield [v] Optional block yields the vertex with the extensions added.
76
76
  # @return nil or the result of the block or the extended vertex
77
77
  def as(*exts)
78
- if as?(*exts)
78
+ if exts.length == 1 and not exts.first.is_a?(Module) and not exts.first.is_a?(Class) and exts.first
79
+ # NB: oops, I defined route#as to be the same as route#section. If the signature is
80
+ # matching the section method, then defer to it.
81
+ section *exts
82
+ elsif as?(*exts)
79
83
  exts_to_add = extensions_missing(exts)
80
84
  extended = exts_to_add.empty? ? self : add_extensions(exts_to_add)
81
85
  if block_given?
@@ -113,7 +117,9 @@ module Pacer::Wrappers
113
117
  # standard ruby console representation of an instantiated object.
114
118
  # @return [String]
115
119
  def inspect
116
- "#<#{ ["V[#{element_id}]", display_name].compact.join(' ') }>"
120
+ graph.read_transaction do
121
+ "#<#{ ["V[#{element_id}]", display_name].compact.join(' ') }>"
122
+ end
117
123
  end
118
124
 
119
125
  # Returns the display name of the vertex.
data/pom.xml CHANGED
@@ -7,10 +7,9 @@
7
7
  <artifactId>pacer</artifactId>
8
8
  <!-- NOTE: the following properties are automatically updated based on the values in lib/pacer-neo4j/version.rb -->
9
9
  <properties>
10
- <blueprints.version>2.3.0</blueprints.version>
11
- <gem.version>1.4.2</gem.version>
12
- <pipes.version>2.3.0</pipes.version>
13
- <gremlin.version>2.3.0</gremlin.version>
10
+ <blueprints.version>2.6.0-SNAPSHOT</blueprints.version>
11
+ <gem.version>1.5.1</gem.version>
12
+ <pipes.version>2.5.0</pipes.version>
14
13
  </properties>
15
14
  <!-- NOTE: the following properties are automatically updated based on the values in lib/pacer-neo4j/version.rb -->
16
15
  <version>${gem.version}</version>
@@ -41,34 +40,8 @@
41
40
  <artifactId>pipes</artifactId>
42
41
  <version>${pipes.version}</version>
43
42
  </dependency>
44
- <!-- MOAR GRAPH TRAVERSAL SUPPORT -->
45
- <dependency>
46
- <groupId>com.tinkerpop.gremlin</groupId>
47
- <artifactId>gremlin-java</artifactId>
48
- <version>${gremlin.version}</version>
49
- </dependency>
50
43
  </dependencies>
51
44
 
52
- <repositories>
53
- <repository>
54
- <id>tinkerpop-repository</id>
55
- <name>TinkerPop Maven2 Repository</name>
56
- <url>http://tinkerpop.com/maven2</url>
57
- <snapshots>
58
- <enabled>true</enabled>
59
- <updatePolicy>always</updatePolicy>
60
- </snapshots>
61
- </repository>
62
- </repositories>
63
-
64
- <distributionManagement>
65
- <repository>
66
- <id>tinkerpop-repository</id>
67
- <name>TinkerPop Maven2 Repository</name>
68
- <url>ftp://ftp.tinkerpop.com:21/public/maven2/</url>
69
- </repository>
70
- </distributionManagement>
71
-
72
45
  <build>
73
46
  <directory>${basedir}/target</directory>
74
47
  <finalName>${project.artifactId}-${project.version}</finalName>
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ module Neo2Spec
4
+ class Person < Pacer::Wrappers::VertexWrapper
5
+ def self.route_conditions(graph)
6
+ { type: 'person' }
7
+ end
8
+ end
9
+
10
+ class Frog < Pacer::Wrappers::VertexWrapper
11
+ def self.route_conditions(graph)
12
+ { frog: 'yes' }
13
+ end
14
+ end
15
+
16
+ Run.neo4j2 :read_only do
17
+ use_pacer_graphml_data :read_only
18
+
19
+ describe '#vertex' do
20
+ it 'should not raise an exception for invalid key type' do
21
+ graph.vertex('bad id').should be_nil
22
+ end
23
+ end
24
+
25
+ describe '#edge' do
26
+ it 'should not raise an exception for invalid key type' do
27
+ graph.edge('bad id').should be_nil
28
+ end
29
+ end
30
+
31
+ describe 'indexed' do
32
+ before do
33
+ # TODO FIXME: why do the presence of these key indices break lots of
34
+ # subsequent tests if they are on graph rather than graph2?
35
+ graph2.create_key_index :type, :vertex
36
+ graph2.create_key_index :name, :vertex
37
+ end
38
+
39
+ describe Person do
40
+ subject { graph2.v(Person) }
41
+
42
+ # sanity checks
43
+ it { should be_a Pacer::Filter::LuceneFilter }
44
+ its(:query) { should == 'type:"person"' }
45
+ # This doesn't work because neo indices are out of sync before the transaction finalizes
46
+ #its(:count) { should == 2 }
47
+
48
+ its(:wrapper) { should == Person }
49
+ end
50
+
51
+ describe Frog do
52
+ subject { graph2.v(Frog) }
53
+
54
+ # sanity checks
55
+ it { should_not be_a Pacer::Filter::LuceneFilter }
56
+ its(:count) { should == 0 }
57
+
58
+ its(:wrapper) { should == Frog }
59
+ end
60
+ end
61
+ end
62
+ end