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.
Files changed (4) hide show
  1. data/VERSION +1 -1
  2. data/flockdb.gemspec +1 -1
  3. data/lib/flock/mock_service.rb +109 -91
  4. metadata +2 -2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
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.1"
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"]
@@ -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
- @sources = @destinations = nil
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, graph_id, source, destination = fixture.values_at(:file, :graph, :source, :destination)
24
+ file, graph, source, dest = fixture.values_at(:file, :graph, :source, :destination)
18
25
 
19
- fixtures_data = YAML::load(ERB.new(File.open(file, 'r').read).result(binding)).sort
20
- fixtures_data.each do |key, value|
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: " + @sources.inspect + " - " + @destinations.inspect
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
- backward_data_source, forward_data_source = term.is_forward ? [sources, destinations] : [destinations, sources]
36
- backward_archived_data_source, forward_archived_data_source = term.is_forward ? [archived_sources, archived_destinations] : [archived_destinations, archived_sources]
37
- source_id, graph_id = term.source_id, term.graph_id
38
- destination_ids = term.destination_ids && term.destination_ids.unpack("Q*")
39
- case operation.operation_type
40
- when Edges::ExecuteOperationType::Add
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(source_id, graph_id, destination_id)
90
- !!destinations[[source_id, graph_id]].detect {|i| i == destination_id}
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
- query_term = select_operation.term
104
- data_source = query_term.is_forward ? destinations : sources
105
- data = data_source[[query_term.source_id, query_term.graph_id]]
106
- if query_term.destination_ids
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 = if page.cursor < Flock::CursorStart
129
- [-page.cursor - page.count, 0].max
130
- else
131
- page.cursor == Flock::CursorStart ? 0 : page.cursor
132
- end
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 ||= begin
146
- empty_result = Flock::Results.new
147
- empty_result.ids = ""
148
- empty_result.next_cursor = Flock::CursorEnd
149
- empty_result.prev_cursor = Flock::CursorEnd
150
- empty_result
151
- end
152
- end
153
-
154
- def sources
155
- @sources ||= Hash.new do |h, k|
156
- h[k] = []
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 destinations
161
- @destinations ||= Hash.new do |h, k|
162
- h[k] = []
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
- def archived_sources
167
- @archived_sources ||= Hash.new do |h, k|
168
- h[k] = []
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 archived_destinations
173
- @archived_destinations ||= Hash.new do |h, k|
174
- h[k] = []
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
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 1
9
- version: 0.3.1
8
+ - 2
9
+ version: 0.3.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Matt Freels