pacer 2.0.12-java → 2.0.13-java
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/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
|
-
[](https://coveralls.io/r/pangloss/pacer) [](https://travis-ci.org/pangloss/pacer)
|
2
|
+
[](https://coveralls.io/r/pangloss/pacer) [](https://travis-ci.org/pangloss/pacer) [](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
|