flockdb 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|