flockdb 0.3.1 → 0.3.2
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.
- data/VERSION +1 -1
- data/flockdb.gemspec +1 -1
- data/lib/flock/mock_service.rb +109 -91
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2
|
data/flockdb.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{flockdb}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Matt Freels", "Rael Dornfest", "Nick Kallen"]
|
data/lib/flock/mock_service.rb
CHANGED
@@ -2,10 +2,17 @@ module Flock
|
|
2
2
|
module MockService
|
3
3
|
extend self
|
4
4
|
|
5
|
+
EXEC_OPS = {
|
6
|
+
Edges::ExecuteOperationType::Add => :add,
|
7
|
+
Edges::ExecuteOperationType::Remove => :remove,
|
8
|
+
Edges::ExecuteOperationType::Archive => :archive
|
9
|
+
}
|
10
|
+
|
5
11
|
attr_accessor :timeout, :fixtures
|
6
12
|
|
7
13
|
def clear
|
8
|
-
@
|
14
|
+
@forward_edges = nil
|
15
|
+
@backward_edges = nil
|
9
16
|
end
|
10
17
|
|
11
18
|
def load(fixtures = nil)
|
@@ -14,71 +21,28 @@ module Flock
|
|
14
21
|
clear
|
15
22
|
|
16
23
|
fixtures.each do |fixture|
|
17
|
-
file,
|
24
|
+
file, graph, source, dest = fixture.values_at(:file, :graph, :source, :destination)
|
18
25
|
|
19
|
-
|
20
|
-
|
21
|
-
sources[[value[destination], graph_id]] << value[source]
|
22
|
-
destinations[[value[source], graph_id]] << value[destination]
|
26
|
+
YAML::load(ERB.new(File.open(file, 'r').read).result(binding)).sort.each do |key, row|
|
27
|
+
add(row[source], graph, row[dest])
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
26
31
|
|
27
32
|
def inspect
|
28
|
-
"Flock::MockService:
|
33
|
+
"Flock::MockService: ( #{@forward_edges.inspect} - #{@backward_edges.inspect} )"
|
29
34
|
end
|
30
35
|
|
31
36
|
def execute(operations)
|
32
37
|
operations = operations.operations
|
33
38
|
operations.each do |operation|
|
34
39
|
term = operation.term
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
if destination_ids.nil?
|
42
|
-
backward_archived_data_source.delete([source_id, graph_id]).to_a.each do |n|
|
43
|
-
(forward_data_source[[n, graph_id]] << source_id).uniq!
|
44
|
-
(backward_data_source[[source_id, graph_id]] << n).uniq!
|
45
|
-
forward_archived_data_source[[n, graph_id]].delete(source_id)
|
46
|
-
end
|
47
|
-
else
|
48
|
-
destination_ids.each do |destination_id|
|
49
|
-
backward_data_source[[destination_id, graph_id]] << source_id
|
50
|
-
forward_data_source[[source_id, graph_id]] << destination_id
|
51
|
-
end
|
52
|
-
end
|
53
|
-
when Edges::ExecuteOperationType::Remove
|
54
|
-
if destination_ids.nil?
|
55
|
-
backward_data_source.delete([source_id, graph_id]).to_a.each do |n|
|
56
|
-
forward_data_source[[n, graph_id]].delete(source_id)
|
57
|
-
end
|
58
|
-
else
|
59
|
-
destination_ids.each do |destination_id|
|
60
|
-
backward_data_source[[destination_id, graph_id]].delete(source_id)
|
61
|
-
forward_data_source[[source_id, graph_id]].delete(destination_id)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
when Edges::ExecuteOperationType::Archive
|
65
|
-
if destination_ids.nil?
|
66
|
-
backward_data_source.delete([source_id, graph_id]).to_a.each do |n|
|
67
|
-
forward_archived_data_source[[n, graph_id]] << source_id
|
68
|
-
backward_archived_data_source[[source_id, graph_id]] << n
|
69
|
-
forward_data_source[[n, graph_id]].delete(source_id)
|
70
|
-
end
|
71
|
-
else
|
72
|
-
destination_ids.each do |destination_id|
|
73
|
-
if backward_data_source[[destination_id, graph_id]].delete(source_id)
|
74
|
-
backward_archived_data_source[[destination_id, graph_id]] << source_id
|
75
|
-
end
|
76
|
-
if forward_data_source[[source_id, graph_id]].delete(destination_id)
|
77
|
-
forward_archived_data_source[[source_id, graph_id]] << destination_id
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
40
|
+
graph, source = term.graph_id, term.source_id
|
41
|
+
dest = term.destination_ids && term.destination_ids.unpack('Q*')
|
42
|
+
|
43
|
+
source, dest = dest, source unless term.is_forward
|
44
|
+
|
45
|
+
self.send(EXEC_OPS[operation.operation_type], source, graph, dest)
|
82
46
|
end
|
83
47
|
end
|
84
48
|
|
@@ -86,8 +50,8 @@ module Flock
|
|
86
50
|
iterate(select_query(select_operations), page)
|
87
51
|
end
|
88
52
|
|
89
|
-
def contains(
|
90
|
-
|
53
|
+
def contains(source, graph, dest)
|
54
|
+
forward_edges[graph][:normal][source].include?(dest)
|
91
55
|
end
|
92
56
|
|
93
57
|
def count(select_operations)
|
@@ -95,18 +59,16 @@ module Flock
|
|
95
59
|
end
|
96
60
|
|
97
61
|
private
|
62
|
+
|
98
63
|
def select_query(select_operations)
|
99
64
|
stack = []
|
100
65
|
select_operations.each do |select_operation|
|
101
66
|
case select_operation.operation_type
|
102
67
|
when Edges::SelectOperationType::SimpleQuery
|
103
|
-
|
104
|
-
|
105
|
-
data =
|
106
|
-
|
107
|
-
data &= query_term.destination_ids.unpack("Q*")
|
108
|
-
end
|
109
|
-
stack.push(data)
|
68
|
+
term = select_operation.term
|
69
|
+
source = term.is_forward ? forward_edges : backward_edges
|
70
|
+
data = source[term.graph_id][:normal][term.source_id]
|
71
|
+
stack.push(term.destination_ids ? (term.destination_ids.unpack('Q*') & data) : data)
|
110
72
|
when Edges::SelectOperationType::Intersection
|
111
73
|
stack.push(stack.pop & stack.pop)
|
112
74
|
when Edges::SelectOperationType::Union
|
@@ -120,16 +82,15 @@ module Flock
|
|
120
82
|
stack.pop
|
121
83
|
end
|
122
84
|
|
123
|
-
private
|
124
|
-
|
125
85
|
def iterate(data, page)
|
126
86
|
return empty_result if page.cursor == Flock::CursorEnd
|
127
87
|
|
128
|
-
start =
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
88
|
+
start =
|
89
|
+
if page.cursor < Flock::CursorStart
|
90
|
+
[-page.cursor - page.count, 0].max
|
91
|
+
else
|
92
|
+
page.cursor == Flock::CursorStart ? 0 : page.cursor
|
93
|
+
end
|
133
94
|
rv = data.slice(start, page.count)
|
134
95
|
next_cursor = (start + page.count >= data.size) ? Flock::CursorEnd : start + page.count
|
135
96
|
prev_cursor = (start <= 0) ? Flock::CursorEnd : -start
|
@@ -142,36 +103,93 @@ module Flock
|
|
142
103
|
end
|
143
104
|
|
144
105
|
def empty_result
|
145
|
-
@empty_result ||=
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
106
|
+
@empty_result ||=
|
107
|
+
begin
|
108
|
+
empty_result = Flock::Results.new
|
109
|
+
empty_result.ids = ""
|
110
|
+
empty_result.next_cursor = Flock::CursorEnd
|
111
|
+
empty_result.prev_cursor = Flock::CursorEnd
|
112
|
+
empty_result
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
[:forward_edges, :backward_edges].each do |name|
|
118
|
+
class_eval("def #{name}; @#{name} ||= new_edges_hash end")
|
119
|
+
end
|
120
|
+
|
121
|
+
def new_edges_hash
|
122
|
+
Hash.new { |h,k| h[k] = Hash.new { |h,k| h[k] = Hash.new { |h2,k2| h2[k2] = [] } } }
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_row(store, source, dest)
|
126
|
+
(store[source] << dest).uniq!
|
127
|
+
end
|
128
|
+
|
129
|
+
def add_edge(source, graph, dest, state)
|
130
|
+
add_row(forward_edges[graph][state], source, dest)
|
131
|
+
add_row(backward_edges[graph][state], dest, source)
|
132
|
+
[source, graph, dest]
|
133
|
+
end
|
134
|
+
|
135
|
+
def remove_row(store, source, dest)
|
136
|
+
store[source].delete(dest).tap do
|
137
|
+
store.delete(source) if store[source].empty?
|
157
138
|
end
|
158
139
|
end
|
159
140
|
|
160
|
-
def
|
161
|
-
|
162
|
-
|
141
|
+
def remove_edge(source, graph, dest, state)
|
142
|
+
forward = remove_row(forward_edges[graph][state], source, dest)
|
143
|
+
backward = remove_row(backward_edges[graph][state], dest, source)
|
144
|
+
|
145
|
+
[source, graph, dest] if forward and backward
|
146
|
+
end
|
147
|
+
|
148
|
+
def remove_node(source, graph, dest, state)
|
149
|
+
raise unless source or dest
|
150
|
+
|
151
|
+
sources, dests = Array(source), Array(dest)
|
152
|
+
|
153
|
+
sources = dests.map{|dest| backward_edges[graph][state][dest] }.inject([]) {|a,b| a.concat b } if sources.empty?
|
154
|
+
dests = sources.map{|source| forward_edges[graph][state][source] }.inject([]) {|a,b| a.concat b } if dests.empty?
|
155
|
+
|
156
|
+
[].tap do |deleted|
|
157
|
+
sources.each {|s| dests.each {|d| deleted << remove_edge(s, graph, d, state) } }
|
158
|
+
end.compact
|
159
|
+
end
|
160
|
+
|
161
|
+
def unarchive_node(source, graph, dest)
|
162
|
+
remove_node(source, graph, dest, :archived).tap do |deleted|
|
163
|
+
deleted.each {|d| add_edge(source, graph, dest, :normal) }
|
163
164
|
end
|
164
165
|
end
|
165
166
|
|
166
|
-
|
167
|
-
|
168
|
-
|
167
|
+
# actual graph helpers
|
168
|
+
|
169
|
+
def add(source, graph, dest)
|
170
|
+
if source.nil? or dest.nil?
|
171
|
+
unarchive_node(source, graph, dest)
|
172
|
+
else
|
173
|
+
sources, dests = Array(source), Array(dest)
|
174
|
+
|
175
|
+
sources.each do |s|
|
176
|
+
dests.each do |d|
|
177
|
+
add_edge(s, graph, d, :normal)
|
178
|
+
remove_edge(s, graph, d, :archived)
|
179
|
+
end
|
180
|
+
end
|
169
181
|
end
|
170
182
|
end
|
171
183
|
|
172
|
-
def
|
173
|
-
|
174
|
-
|
184
|
+
def remove(source, graph, dest)
|
185
|
+
remove_node(source, graph, dest, :archived)
|
186
|
+
remove_node(source, graph, dest, :normal)
|
187
|
+
end
|
188
|
+
|
189
|
+
def archive(source, graph, dest)
|
190
|
+
remove_node(source, graph, dest, :normal).tap do |deleted|
|
191
|
+
p deleted
|
192
|
+
deleted.each {|source, graph, dest| add_edge(source, graph, dest, :archived) }
|
175
193
|
end
|
176
194
|
end
|
177
195
|
end
|