pacer 2.0.12-java → 2.0.13-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/ext/pom.xml +3 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/ExpandablePipe.java +21 -10
- data/ext/src/main/java/com/xnlogic/pacer/pipes/IdCollectionFilterPipe.java +6 -5
- data/ext/src/main/java/com/xnlogic/pacer/pipes/IsUniquePipe.java +6 -16
- data/ext/src/test/java/com/xnlogic/pacer/pipes/ExpandablePipeTest.java +10 -13
- data/ext/src/test/java/com/xnlogic/pacer/pipes/LabelCollectionFilterPipeTest.java +45 -30
- data/lib/pacer/core/route.rb +0 -1
- data/lib/pacer/filter/java_loop_filter.rb +2 -1
- data/lib/pacer/filter/loop_filter.rb +0 -2
- data/lib/pacer/filter/where_filter/node_visitor.rb +21 -27
- data/lib/pacer/graph/graph_transactions_mixin.rb +9 -0
- data/lib/pacer/pipe/loop_pipe.rb +1 -4
- data/lib/pacer/transform/intersect_sections.rb +35 -0
- data/lib/pacer/version.rb +1 -1
- data/lib/pacer/wrappers/vertex_wrapper.rb +1 -1
- data/lib/pacer-ext.jar +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13555fbf36509b247945a23559f60d2b5eddb0e4
|
4
|
+
data.tar.gz: 258b4dd295d67b91dfbb8aa29969b7bef809fb2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ed67f63063e560b02926a116fcace7dd285d7522d2f8165ccc659b34df9a66756c6bb31013e37a540844781a58fad4ebb6a2eb99dbec68ab772ed9d75e341a2
|
7
|
+
data.tar.gz: d1b69243930b7906702a5c67f5b2359b2dbf9f3b61bcf26c68a3b8bfe9b2cf51ab0a060277c9a13faee0efc5732279e9f70ba15a647e384f021ada7603bf2bdf
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Pacer
|
2
|
-
[![Coverage Status](https://img.shields.io/coveralls/pangloss/pacer.svg)](https://coveralls.io/r/pangloss/pacer) [![Build Status](https://travis-ci.org/pangloss/pacer.svg)](https://travis-ci.org/pangloss/pacer)
|
2
|
+
[![Coverage Status](https://img.shields.io/coveralls/pangloss/pacer.svg)](https://coveralls.io/r/pangloss/pacer) [![Build Status](https://travis-ci.org/pangloss/pacer.svg)](https://travis-ci.org/pangloss/pacer) [![Code Climate](https://codeclimate.com/github/pangloss/pacer/badges/gpa.svg)](https://codeclimate.com/github/pangloss/pacer)
|
3
3
|
|
4
4
|
Pacer is a JRuby library that enables very expressive graph traversals.
|
5
5
|
|
6
|
-
It currently supports all of the major graph databases including [OrientDB]
|
6
|
+
It currently supports all of the major graph databases including [OrientDB](http://orientdb.com), [Neo4j](http://neo4j.org)
|
7
7
|
and [Dex](http://www.sparsity-technologies.com/dex) thanks to the
|
8
8
|
[Tinkerpop](http://tinkerpop.com) graphdb stack. Plus there's a very
|
9
9
|
convenient in-memory graph called TinkerGraph which is part of
|
@@ -25,7 +25,7 @@ Pacer has a [google group](http://groups.google.com/group/pacer-users?lnk=gcimv)
|
|
25
25
|
Check out the [wiki](https://github.com/pangloss/pacer/wiki) for detailed explanations of many of Pacer's features. Please contribute to it or open issues against it if there is anything missing that you want to see.
|
26
26
|
|
27
27
|
Pacer is also documented with a comprehensive RSpec test suite and with a
|
28
|
-
thorough YARD documentation. [Dig in!](http://rubydoc.info/github/pangloss/pacer/
|
28
|
+
thorough YARD documentation. [Dig in!](http://www.rubydoc.info/github/pangloss/pacer/master)
|
29
29
|
|
30
30
|
If you like, you can also use the documentation locally via
|
31
31
|
|
data/ext/pom.xml
CHANGED
@@ -2,6 +2,9 @@ package com.xnlogic.pacer.pipes;
|
|
2
2
|
|
3
3
|
import com.tinkerpop.pipes.AbstractPipe;
|
4
4
|
import com.tinkerpop.pipes.Pipe;
|
5
|
+
|
6
|
+
import java.util.Iterator;
|
7
|
+
import java.util.NoSuchElementException;
|
5
8
|
import java.util.Queue;
|
6
9
|
import java.util.LinkedList;
|
7
10
|
import java.util.List;
|
@@ -12,14 +15,21 @@ public class ExpandablePipe<T> extends AbstractPipe<T, T> {
|
|
12
15
|
private Object metadata;
|
13
16
|
private Object nextMetadata;
|
14
17
|
|
15
|
-
private List path;
|
16
|
-
private List nextPath;
|
18
|
+
private List<Object> path;
|
19
|
+
private List<Object> nextPath;
|
17
20
|
|
18
21
|
public ExpandablePipe() {
|
19
22
|
this.queue = new LinkedList<EPTriple>();
|
23
|
+
|
24
|
+
// By default, initialize this pipe with an empty iterator
|
25
|
+
setStarts(new Iterator<T>() {
|
26
|
+
public boolean hasNext() {return false;}
|
27
|
+
public T next() {throw new NoSuchElementException();}
|
28
|
+
public void remove() {}
|
29
|
+
});
|
20
30
|
}
|
21
31
|
|
22
|
-
public void add(T element, Object metadata, List path) {
|
32
|
+
public void add(T element, Object metadata, List<Object> path) {
|
23
33
|
this.queue.add(new EPTriple(element, metadata, path));
|
24
34
|
}
|
25
35
|
|
@@ -48,15 +58,16 @@ public class ExpandablePipe<T> extends AbstractPipe<T, T> {
|
|
48
58
|
return toReturn;
|
49
59
|
}
|
50
60
|
|
51
|
-
|
61
|
+
@SuppressWarnings("unchecked")
|
62
|
+
protected T processNextStart() {
|
52
63
|
if (this.queue.isEmpty()) {
|
53
64
|
this.nextMetadata = null;
|
54
65
|
T r = this.starts.next();
|
55
66
|
|
56
67
|
if (this.pathEnabled && this.starts instanceof Pipe) {
|
57
|
-
this.nextPath = ((Pipe)this.starts).getCurrentPath();
|
68
|
+
this.nextPath = ((Pipe<T, T>)this.starts).getCurrentPath();
|
58
69
|
} else {
|
59
|
-
this.nextPath = new ArrayList();
|
70
|
+
this.nextPath = new ArrayList<Object>();
|
60
71
|
}
|
61
72
|
return r;
|
62
73
|
} else {
|
@@ -67,8 +78,8 @@ public class ExpandablePipe<T> extends AbstractPipe<T, T> {
|
|
67
78
|
}
|
68
79
|
}
|
69
80
|
|
70
|
-
public List getPathToHere() {
|
71
|
-
List path = new ArrayList();
|
81
|
+
public List<Object> getPathToHere() {
|
82
|
+
List<Object> path = new ArrayList<Object>();
|
72
83
|
|
73
84
|
if (this.path != null) {
|
74
85
|
for (Object p : this.path) {
|
@@ -82,9 +93,9 @@ public class ExpandablePipe<T> extends AbstractPipe<T, T> {
|
|
82
93
|
private class EPTriple {
|
83
94
|
public T element;
|
84
95
|
public Object metadata;
|
85
|
-
public List path;
|
96
|
+
public List<Object> path;
|
86
97
|
|
87
|
-
public EPTriple(T element, Object metadata, List path) {
|
98
|
+
public EPTriple(T element, Object metadata, List<Object> path) {
|
88
99
|
this.element = element;
|
89
100
|
this.metadata = metadata;
|
90
101
|
this.path = path;
|
@@ -9,19 +9,20 @@ import com.tinkerpop.blueprints.Element;
|
|
9
9
|
import com.tinkerpop.pipes.AbstractPipe;
|
10
10
|
|
11
11
|
public class IdCollectionFilterPipe<E extends Element> extends AbstractPipe<E, E> {
|
12
|
-
private Set ids;
|
12
|
+
private Set<Object> ids;
|
13
13
|
private boolean containsIn;
|
14
14
|
|
15
15
|
// TODO: Consider making this a derived exception. Also, this constructor is the reverse of the Ruby one. Is this ok?
|
16
16
|
// Also also, is an Object array the way to go? Can we nail down the type further?
|
17
|
-
|
17
|
+
@SuppressWarnings("unchecked")
|
18
|
+
public IdCollectionFilterPipe(final Collection<?> ids, final Contains comparison) throws RuntimeException {
|
18
19
|
super();
|
19
20
|
if (ids instanceof Set) {
|
20
|
-
this.ids = (Set)ids;
|
21
|
+
this.ids = (Set<Object>)ids;
|
21
22
|
} else if (ids == null) {
|
22
|
-
this.ids = new HashSet();
|
23
|
+
this.ids = new HashSet<Object>();
|
23
24
|
} else {
|
24
|
-
this.ids = new HashSet();
|
25
|
+
this.ids = new HashSet<Object>();
|
25
26
|
this.ids.addAll(ids);
|
26
27
|
}
|
27
28
|
if (comparison == Contains.IN)
|
@@ -1,15 +1,13 @@
|
|
1
1
|
package com.xnlogic.pacer.pipes;
|
2
2
|
|
3
|
-
import java.util.
|
3
|
+
import java.util.LinkedHashSet;
|
4
|
+
import java.util.Set;
|
4
5
|
|
5
6
|
import com.tinkerpop.pipes.AbstractPipe;
|
6
|
-
import com.tinkerpop.pipes.filter.DuplicateFilterPipe;
|
7
|
-
import com.tinkerpop.pipes.util.iterators.ExpandableIterator;
|
8
7
|
|
9
8
|
public class IsUniquePipe<T> extends AbstractPipe<T, T> {
|
10
9
|
private boolean unique;
|
11
|
-
private
|
12
|
-
private DuplicateFilterPipe<T> uniquePipe;
|
10
|
+
private Set<T> historySet;
|
13
11
|
|
14
12
|
public IsUniquePipe() {
|
15
13
|
super();
|
@@ -18,10 +16,8 @@ public class IsUniquePipe<T> extends AbstractPipe<T, T> {
|
|
18
16
|
|
19
17
|
protected T processNextStart() {
|
20
18
|
T value = this.starts.next();
|
21
|
-
|
22
19
|
if (this.unique)
|
23
20
|
this.checkUniqueness(value);
|
24
|
-
|
25
21
|
return value;
|
26
22
|
}
|
27
23
|
|
@@ -39,20 +35,14 @@ public class IsUniquePipe<T> extends AbstractPipe<T, T> {
|
|
39
35
|
}
|
40
36
|
|
41
37
|
protected void checkUniqueness(T value) {
|
42
|
-
|
43
|
-
this.expando.add(value);
|
44
|
-
this.uniquePipe.next();
|
45
|
-
} catch (NoSuchElementException nsee) {
|
38
|
+
if (!this.historySet.add(value)) {
|
46
39
|
this.unique = false;
|
47
|
-
this.
|
48
|
-
this.expando = null;
|
40
|
+
this.historySet = null;
|
49
41
|
}
|
50
42
|
}
|
51
43
|
|
52
44
|
protected void prepareState() {
|
45
|
+
this.historySet = new LinkedHashSet<T>();
|
53
46
|
this.unique = true;
|
54
|
-
this.expando = new ExpandableIterator<T>();
|
55
|
-
this.uniquePipe = new DuplicateFilterPipe<T>();
|
56
|
-
this.uniquePipe.setStarts(this.expando);
|
57
47
|
}
|
58
48
|
}
|
@@ -1,29 +1,26 @@
|
|
1
1
|
package com.xnlogic.pacer.pipes;
|
2
2
|
|
3
|
-
import static org.junit.Assert
|
4
|
-
import org.junit.
|
5
|
-
|
3
|
+
import static org.junit.Assert.assertNull;
|
4
|
+
import static org.junit.Assert.assertTrue;
|
5
|
+
|
6
6
|
import java.util.ArrayList;
|
7
|
-
|
8
|
-
import
|
9
|
-
import com.tinkerpop.pipes.AbstractPipe;
|
10
|
-
import java.util.Iterator;
|
11
|
-
import com.xnlogic.pacer.pipes.ExpandablePipe;
|
7
|
+
|
8
|
+
import org.junit.Test;
|
12
9
|
|
13
10
|
public class ExpandablePipeTest {
|
14
11
|
|
15
12
|
@Test
|
16
13
|
public void queueWithElementsTest() {
|
17
|
-
ExpandablePipe expandablePipe = new ExpandablePipe();
|
14
|
+
ExpandablePipe<String> expandablePipe = new ExpandablePipe<String>();
|
18
15
|
|
19
|
-
ArrayList input = new ArrayList();
|
16
|
+
ArrayList<String> input = new ArrayList<String>();
|
20
17
|
input.add("X");
|
21
18
|
|
22
19
|
expandablePipe.setStarts(input.iterator());
|
23
20
|
|
24
|
-
expandablePipe.add("a", 1, new ArrayList());
|
25
|
-
expandablePipe.add("b", 2, new ArrayList());
|
26
|
-
expandablePipe.add("c", 3, new ArrayList());
|
21
|
+
expandablePipe.add("a", 1, new ArrayList<Object>());
|
22
|
+
expandablePipe.add("b", 2, new ArrayList<Object>());
|
23
|
+
expandablePipe.add("c", 3, new ArrayList<Object>());
|
27
24
|
|
28
25
|
Object result = expandablePipe.next();
|
29
26
|
assertTrue(result.equals("a"));
|
@@ -20,6 +20,7 @@ public class LabelCollectionFilterPipeTest {
|
|
20
20
|
@Before
|
21
21
|
public void setup() throws Exception {
|
22
22
|
this.graph = new TinkerGraph();
|
23
|
+
createEdges();
|
23
24
|
}
|
24
25
|
|
25
26
|
@After
|
@@ -42,53 +43,67 @@ public class LabelCollectionFilterPipeTest {
|
|
42
43
|
this.edges = Arrays.asList(e1, e2, e3, e4);
|
43
44
|
}
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Collection<String> edgeLabels = Arrays.asList("edge2", "edge3");
|
46
|
+
|
47
|
+
|
48
|
+
private LabelCollectionFilterPipe initPipeAndConsumeSomeItems(Collection<String> edgeLabels, int itemsToConsume) {
|
49
49
|
LabelCollectionFilterPipe labelCollectionFilterPipe = new LabelCollectionFilterPipe(edgeLabels);
|
50
|
-
|
51
50
|
labelCollectionFilterPipe.setStarts(this.edges);
|
52
|
-
Edge e = labelCollectionFilterPipe.next();
|
53
|
-
assertEquals("E2", e.getId());
|
54
51
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
for (int i = 0; i < itemsToConsume; i++) {
|
53
|
+
labelCollectionFilterPipe.next();
|
54
|
+
}
|
55
|
+
|
56
|
+
return labelCollectionFilterPipe;
|
59
57
|
}
|
60
58
|
|
61
59
|
|
60
|
+
|
61
|
+
@Test
|
62
|
+
public void hasSomeMatchingEdgesTest() {
|
63
|
+
LabelCollectionFilterPipe pipe = initPipeAndConsumeSomeItems(Arrays.asList("edge2", "edge3"), 0);
|
64
|
+
assertEquals("E2", pipe.next().getId());
|
65
|
+
}
|
66
|
+
|
67
|
+
@Test
|
68
|
+
public void hasSomeMatchingEdgesTest2() {
|
69
|
+
LabelCollectionFilterPipe pipe = initPipeAndConsumeSomeItems(Arrays.asList("edge2", "edge3"), 1);
|
70
|
+
assertEquals("E3", pipe.next().getId());
|
71
|
+
}
|
72
|
+
|
62
73
|
@Test(expected=NoSuchElementException.class)
|
74
|
+
public void hasSomeMatchingEdgesTest3() {
|
75
|
+
LabelCollectionFilterPipe pipe = initPipeAndConsumeSomeItems(Arrays.asList("edge2", "edge3"), 2);
|
76
|
+
pipe.next();
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
@Test
|
63
81
|
public void hasSomeMatchingEdgesWithSetTest() {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
82
|
+
LabelCollectionFilterPipe pipe = initPipeAndConsumeSomeItems(new HashSet<String>(Arrays.asList("edge2", "edge3")), 0);
|
83
|
+
assertEquals("E2", pipe.next().getId());
|
84
|
+
}
|
85
|
+
|
86
|
+
@Test
|
87
|
+
public void hasSomeMatchingEdgesWithSetTest2() {
|
88
|
+
LabelCollectionFilterPipe pipe = initPipeAndConsumeSomeItems(new HashSet<String>(Arrays.asList("edge2", "edge3")), 1);
|
89
|
+
assertEquals("E3", pipe.next().getId());
|
90
|
+
}
|
91
|
+
|
92
|
+
@Test(expected=NoSuchElementException.class)
|
93
|
+
public void hasSomeMatchingEdgesWithSetTest3() {
|
94
|
+
LabelCollectionFilterPipe pipe = initPipeAndConsumeSomeItems(new HashSet<String>(Arrays.asList("edge2", "edge3")), 2);
|
95
|
+
pipe.next();
|
76
96
|
}
|
77
97
|
|
78
98
|
@Test(expected=NoSuchElementException.class)
|
79
99
|
public void hasNoMatchingEdgesTest() {
|
80
|
-
|
81
|
-
|
82
|
-
LabelCollectionFilterPipe labelCollectionFilterPipe = new LabelCollectionFilterPipe(edgeLabels);
|
83
|
-
|
84
|
-
labelCollectionFilterPipe.setStarts(this.edges);
|
85
|
-
labelCollectionFilterPipe.next();
|
100
|
+
LabelCollectionFilterPipe pipe = initPipeAndConsumeSomeItems(new HashSet<String>(Arrays.asList("edge5", "edge6")), 0);
|
101
|
+
pipe.next();
|
86
102
|
}
|
87
103
|
|
88
104
|
|
89
105
|
@Test(expected=NoSuchElementException.class)
|
90
106
|
public void noEdgesToMatchTest() {
|
91
|
-
this.createEdges();
|
92
107
|
LabelCollectionFilterPipe labelCollectionFilterPipe = new LabelCollectionFilterPipe(null);
|
93
108
|
|
94
109
|
labelCollectionFilterPipe.setStarts(this.edges);
|
data/lib/pacer/core/route.rb
CHANGED
@@ -8,7 +8,7 @@ module Pacer
|
|
8
8
|
def all(opts = {}, &block)
|
9
9
|
if opts[:include_self]
|
10
10
|
branch do |this|
|
11
|
-
this
|
11
|
+
this.identity
|
12
12
|
end.branch do |this|
|
13
13
|
this.java_loop(opts, &block)
|
14
14
|
end.merge_exhaustive
|
@@ -24,6 +24,7 @@ module Pacer
|
|
24
24
|
import com.tinkerpop.pipes.branch.LoopPipe
|
25
25
|
|
26
26
|
attr_reader :looping_route
|
27
|
+
attr_accessor :include_self
|
27
28
|
|
28
29
|
def looping_route=(route)
|
29
30
|
if route.is_a? Proc
|
@@ -212,8 +212,6 @@ HELP
|
|
212
212
|
|
213
213
|
def expandable(route = nil)
|
214
214
|
expando = Pacer::Pipes::ExpandablePipe.new
|
215
|
-
empty = java.util.ArrayList.new
|
216
|
-
expando.setStarts empty.iterator
|
217
215
|
if route
|
218
216
|
control_pipe = Pacer::Route.pipeline route
|
219
217
|
control_pipe.setStarts expando
|
@@ -156,21 +156,6 @@ module Pacer
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
-
def visitAndNode(node)
|
160
|
-
a = comparable_pipe node.first_node.accept(self)
|
161
|
-
b = comparable_pipe node.second_node.accept(self)
|
162
|
-
|
163
|
-
if a.pipe == AndFilterPipe and b.pipe == AndFilterPipe
|
164
|
-
Pipe.new AndFilterPipe, *a.args, *b.args
|
165
|
-
elsif a.pipe == AndFilterPipe
|
166
|
-
Pipe.new AndFilterPipe, *a.args, b
|
167
|
-
elsif b.pipe == AndFilterPipe
|
168
|
-
Pipe.new AndFilterPipe, a, *b.args
|
169
|
-
else
|
170
|
-
Pipe.new AndFilterPipe, a, b
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
159
|
def visitArrayNode(node)
|
175
160
|
Value.new Value.new(node.child_nodes.map { |n| n.accept self }).values!
|
176
161
|
end
|
@@ -246,19 +231,12 @@ module Pacer
|
|
246
231
|
Value.new nil
|
247
232
|
end
|
248
233
|
|
249
|
-
def
|
250
|
-
|
251
|
-
|
234
|
+
def visitAndNode(node)
|
235
|
+
visit_and_or(AndFilterPipe, node)
|
236
|
+
end
|
252
237
|
|
253
|
-
|
254
|
-
|
255
|
-
elsif a.pipe == OrFilterPipe
|
256
|
-
Pipe.new OrFilterPipe, *a.args, b
|
257
|
-
elsif b.pipe == OrFilterPipe
|
258
|
-
Pipe.new OrFilterPipe, a, *b.args
|
259
|
-
else
|
260
|
-
Pipe.new OrFilterPipe, a, b
|
261
|
-
end
|
238
|
+
def visitOrNode(node)
|
239
|
+
visit_and_or(OrFilterPipe, node)
|
262
240
|
end
|
263
241
|
|
264
242
|
def visitRootNode(node)
|
@@ -308,6 +286,22 @@ module Pacer
|
|
308
286
|
def visitZArrayNode(node)
|
309
287
|
Value.new []
|
310
288
|
end
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
def visit_and_or(pipe_class, node)
|
293
|
+
a = comparable_pipe node.first_node.accept(self)
|
294
|
+
b = comparable_pipe node.second_node.accept(self)
|
295
|
+
if a.pipe == pipe_class and b.pipe == pipe_class
|
296
|
+
Pipe.new pipe_class, *a.args, *b.args
|
297
|
+
elsif a.pipe == pipe_class
|
298
|
+
Pipe.new pipe_class, *a.args, b
|
299
|
+
elsif b.pipe == pipe_class
|
300
|
+
Pipe.new pipe_class, a, *b.args
|
301
|
+
else
|
302
|
+
Pipe.new pipe_class, a, b
|
303
|
+
end
|
304
|
+
end
|
311
305
|
end
|
312
306
|
end
|
313
307
|
end
|
@@ -39,7 +39,13 @@ module Pacer
|
|
39
39
|
# nesting: false -- (default) raise an exception instead of starting a nested transaction
|
40
40
|
def transaction(opts = {})
|
41
41
|
commit, rollback = start_transaction! opts
|
42
|
+
tx_depth = nil
|
42
43
|
begin
|
44
|
+
if Pacer.verbose == :very
|
45
|
+
tx_depth = threadlocal_graph_info[:dx_depth]
|
46
|
+
puts "--#{self.class.name} transaction #{ tx_depth } --> "
|
47
|
+
puts caller[0,3]
|
48
|
+
end
|
43
49
|
r = yield commit, rollback
|
44
50
|
commit.call(false)
|
45
51
|
r
|
@@ -47,6 +53,7 @@ module Pacer
|
|
47
53
|
rollback.call e.message
|
48
54
|
raise
|
49
55
|
ensure
|
56
|
+
puts "--#{self.class.name} #{ tx_depth } <-- " if Pacer.verbose == :very
|
50
57
|
finish_transaction!
|
51
58
|
end
|
52
59
|
end
|
@@ -156,6 +163,8 @@ module Pacer
|
|
156
163
|
end
|
157
164
|
|
158
165
|
# NOTE pacer-orient reimplements this
|
166
|
+
# A better name for this would be "create_real_transaction", vs. the other finalizers which are all mock transactions in the default
|
167
|
+
# implementation.
|
159
168
|
def base_tx_finalizers
|
160
169
|
tx_id = threadlocal_graph_info[:tx_id] = rand
|
161
170
|
commit = ->(reopen = true) do
|
data/lib/pacer/pipe/loop_pipe.rb
CHANGED
@@ -10,8 +10,6 @@ module Pacer::Pipes
|
|
10
10
|
@wrapper = Pacer::Wrappers::WrapperSelector.build graph
|
11
11
|
|
12
12
|
@expando = ExpandablePipe.new
|
13
|
-
empty = ArrayList.new
|
14
|
-
@expando.setStarts empty.iterator
|
15
13
|
looping_pipe.setStarts(@expando)
|
16
14
|
if control_block.arity < 0 or control_block.arity > 2
|
17
15
|
@yield_paths = true
|
@@ -43,8 +41,7 @@ module Pacer::Pipes
|
|
43
41
|
|
44
42
|
def processNextStart
|
45
43
|
while true
|
46
|
-
|
47
|
-
if has_next
|
44
|
+
if looping_pipe.hasNext
|
48
45
|
element = looping_pipe.next
|
49
46
|
depth = (expando.metadata || 0) + 1
|
50
47
|
self.next_path = looping_pipe.getCurrentPath if pathEnabled
|
@@ -1,18 +1,53 @@
|
|
1
1
|
module Pacer
|
2
2
|
module Routes
|
3
3
|
module RouteOperations
|
4
|
+
# Set operations on sections like intersect_sections, difference_sections, etc. allow a route to do things like produce a stream of the set of
|
5
|
+
# employees who worked in multiple groups within a compnay, in a single traversal. To take that example further, imagine that we define the
|
6
|
+
# following traversals:
|
7
|
+
#
|
8
|
+
# company.groups.employees
|
9
|
+
#
|
10
|
+
# Give me all of the employees who have worked in every group in the company:
|
11
|
+
#
|
12
|
+
# company.groups.as(:g).employees.intersect_sections(:g)
|
13
|
+
#
|
14
|
+
# To understand how this works, we can think about the underlying structure of the graph, with a company with 2 groups which share employee e2
|
15
|
+
# and also have their own employees:
|
16
|
+
#
|
17
|
+
# (c)--->(g1)=--->(e1)
|
18
|
+
# | '-->(e2)
|
19
|
+
# | /
|
20
|
+
# | .---`
|
21
|
+
# '---(g2)=--->(e3)
|
22
|
+
#
|
23
|
+
# The simple route company.groups.employees.paths will produce:
|
24
|
+
# [c, g1, e1]
|
25
|
+
# [c, g1, e2]
|
26
|
+
# [c, g2, e2]
|
27
|
+
# [c, g2, e3]
|
28
|
+
#
|
29
|
+
# By adding a section to the groups with groups.as(:section_name), we set up the mechanism allowing us to respond to the event when the group in
|
30
|
+
# the path changes in subsequent stages of the route. That is what .intersect_sections(:section_name) does. It can conceptually keep a set of
|
31
|
+
# employees from each group and then when the source data has been exhausted, it can do a set intersection on those groups, then use the
|
32
|
+
# resulting set as its source of resulting data.
|
33
|
+
#
|
4
34
|
def intersect_sections(section)
|
5
35
|
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :intersection
|
6
36
|
end
|
7
37
|
|
38
|
+
# See details on intersect_section. Emits only elements that are not in other sections.
|
8
39
|
def difference_sections(section)
|
9
40
|
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :difference
|
10
41
|
end
|
11
42
|
|
43
|
+
# See details on intersect_section. Emits only elements that are in the first section and not in any subsequent ones.
|
12
44
|
def left_difference_sections(section)
|
13
45
|
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :left_difference
|
14
46
|
end
|
15
47
|
|
48
|
+
# See details on intersect_section. Emits only elements that are in the last section and not in the right difference of the previous section.
|
49
|
+
#
|
50
|
+
# This one can be confusing if you've got more than 2 sections...
|
16
51
|
def right_difference_sections(section)
|
17
52
|
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :right_difference
|
18
53
|
end
|
data/lib/pacer/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Pacer
|
2
|
-
VERSION = "2.0.
|
2
|
+
VERSION = "2.0.13"
|
3
3
|
# Clients may optionally define the following constants in the Pacer namespace:
|
4
4
|
# - LOAD_JARS : set to false to manage jar loading in the client. Be sure to load the jars defined in JARFILES.
|
5
5
|
# - LOCKJAR_LOCK_OPTS : set some options to be passed to LockJar.lock (ie. :lockfile, :download_artifacts, :local_repo)
|
@@ -102,7 +102,7 @@ module Pacer::Wrappers
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def as?(*exts)
|
105
|
-
|
105
|
+
extensions_missing(exts).all? do |ext|
|
106
106
|
rc = if ext.respond_to? :route_conditions
|
107
107
|
ext.route_conditions(graph)
|
108
108
|
elsif ext.respond_to? :lookup
|
data/lib/pacer-ext.jar
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pacer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.13
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Darrick Wiebe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lock_jar
|