inventory_refresh 0.1.3 → 0.2.0
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/.gitignore +6 -0
- data/Gemfile +4 -0
- data/bundler.d/.gitkeep +0 -0
- data/inventory_refresh.gemspec +4 -4
- data/lib/inventory_refresh/inventory_collection/builder.rb +249 -0
- data/lib/inventory_refresh/inventory_collection/graph.rb +0 -15
- data/lib/inventory_refresh/inventory_collection/helpers/associations_helper.rb +80 -0
- data/lib/inventory_refresh/inventory_collection/helpers/initialize_helper.rb +456 -0
- data/lib/inventory_refresh/inventory_collection/helpers/questions_helper.rb +132 -0
- data/lib/inventory_refresh/inventory_collection/helpers.rb +6 -0
- data/lib/inventory_refresh/inventory_collection/index/type/skeletal.rb +5 -5
- data/lib/inventory_refresh/inventory_collection/reference.rb +4 -0
- data/lib/inventory_refresh/inventory_collection/scanner.rb +111 -18
- data/lib/inventory_refresh/inventory_collection/serialization.rb +7 -7
- data/lib/inventory_refresh/inventory_collection/unconnected_edge.rb +19 -0
- data/lib/inventory_refresh/inventory_collection.rb +114 -649
- data/lib/inventory_refresh/inventory_object.rb +17 -11
- data/lib/inventory_refresh/inventory_object_lazy.rb +20 -10
- data/lib/inventory_refresh/persister.rb +212 -0
- data/lib/inventory_refresh/save_collection/base.rb +18 -3
- data/lib/inventory_refresh/save_collection/saver/base.rb +25 -62
- data/lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb +73 -225
- data/lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb +226 -0
- data/lib/inventory_refresh/save_collection/saver/retention_helper.rb +115 -0
- data/lib/inventory_refresh/save_collection/saver/sql_helper.rb +122 -0
- data/lib/inventory_refresh/save_collection/saver/sql_helper_update.rb +24 -5
- data/lib/inventory_refresh/save_collection/saver/sql_helper_upsert.rb +6 -6
- data/lib/inventory_refresh/save_collection/sweeper.rb +69 -0
- data/lib/inventory_refresh/save_inventory.rb +18 -8
- data/lib/inventory_refresh/target_collection.rb +12 -0
- data/lib/inventory_refresh/version.rb +1 -1
- data/lib/inventory_refresh.rb +1 -0
- metadata +24 -15
- data/lib/inventory_refresh/save_collection/recursive.rb +0 -52
- data/lib/inventory_refresh/save_collection/saver/concurrent_safe.rb +0 -71
@@ -13,7 +13,7 @@ module InventoryRefresh
|
|
13
13
|
indexed_inventory_collections = inventory_collections.index_by(&:name)
|
14
14
|
|
15
15
|
inventory_collections.each do |inventory_collection|
|
16
|
-
new(inventory_collection, indexed_inventory_collections).scan!
|
16
|
+
new(inventory_collection, indexed_inventory_collections, build_association_hash(inventory_collections)).scan!
|
17
17
|
end
|
18
18
|
|
19
19
|
inventory_collections.each do |inventory_collection|
|
@@ -22,9 +22,21 @@ module InventoryRefresh
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
def build_association_hash(inventory_collections)
|
27
|
+
associations_hash = {}
|
28
|
+
parents = inventory_collections.map(&:parent).compact.uniq
|
29
|
+
parents.each do |parent|
|
30
|
+
parent.class.reflect_on_all_associations(:has_many).each do |association|
|
31
|
+
through_assoc = association.options.try(:[], :through)
|
32
|
+
associations_hash[association.name] = through_assoc if association.options.try(:[], :through)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
associations_hash
|
36
|
+
end
|
25
37
|
end
|
26
38
|
|
27
|
-
attr_reader :inventory_collection, :indexed_inventory_collections
|
39
|
+
attr_reader :associations_hash, :inventory_collection, :indexed_inventory_collections
|
28
40
|
|
29
41
|
# Boolean helpers the scanner uses from the :inventory_collection
|
30
42
|
delegate :inventory_object_lazy?,
|
@@ -40,19 +52,26 @@ module InventoryRefresh
|
|
40
52
|
:to => :inventory_collection
|
41
53
|
|
42
54
|
# The data scanner modifies inside of the :inventory_collection
|
43
|
-
delegate :
|
55
|
+
delegate :all_manager_uuids_scope,
|
56
|
+
:association,
|
57
|
+
:arel,
|
58
|
+
:attribute_references,
|
59
|
+
:custom_save_block,
|
44
60
|
:data_collection_finalized=,
|
45
61
|
:dependency_attributes,
|
62
|
+
:targeted?,
|
46
63
|
:targeted_scope,
|
64
|
+
:parent,
|
47
65
|
:parent_inventory_collections,
|
48
66
|
:parent_inventory_collections=,
|
49
67
|
:references,
|
50
68
|
:transitive_dependency_attributes,
|
51
69
|
:to => :inventory_collection
|
52
70
|
|
53
|
-
def initialize(inventory_collection, indexed_inventory_collections)
|
71
|
+
def initialize(inventory_collection, indexed_inventory_collections, associations_hash)
|
54
72
|
@inventory_collection = inventory_collection
|
55
73
|
@indexed_inventory_collections = indexed_inventory_collections
|
74
|
+
@associations_hash = associations_hash
|
56
75
|
end
|
57
76
|
|
58
77
|
def scan!
|
@@ -66,26 +85,85 @@ module InventoryRefresh
|
|
66
85
|
end
|
67
86
|
end
|
68
87
|
|
69
|
-
#
|
70
|
-
|
71
|
-
|
72
|
-
ic = indexed_inventory_collections[inventory_collection_index]
|
73
|
-
if ic.nil?
|
74
|
-
raise "Can't find InventoryCollection #{inventory_collection_index} from #{inventory_collection}" if targeted?
|
75
|
-
else
|
76
|
-
# Add parent_inventory_collection as a dependency, so e.g. disconnect is done in a right order
|
77
|
-
(dependency_attributes[:__parent_inventory_collections] ||= Set.new) << ic
|
78
|
-
ic
|
79
|
-
end
|
80
|
-
end.compact
|
88
|
+
# Scan InventoryCollection skeletal data
|
89
|
+
inventory_collection.skeletal_primary_index.each_value do |inventory_object|
|
90
|
+
scan_inventory_object!(inventory_object)
|
81
91
|
end
|
82
92
|
|
93
|
+
build_parent_inventory_collections!
|
94
|
+
scan_all_manager_uuids_scope!
|
95
|
+
|
83
96
|
# Mark InventoryCollection as finalized aka. scanned
|
84
97
|
self.data_collection_finalized = true
|
85
98
|
end
|
86
99
|
|
87
100
|
private
|
88
101
|
|
102
|
+
def scan_all_manager_uuids_scope!
|
103
|
+
return if all_manager_uuids_scope.nil?
|
104
|
+
|
105
|
+
all_manager_uuids_scope.each do |scope|
|
106
|
+
scope.each_value do |value|
|
107
|
+
scan_all_manager_uuids_scope_attribute!(value)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def build_parent_inventory_collections!
|
113
|
+
if parent_inventory_collections.nil?
|
114
|
+
build_parent_inventory_collection!
|
115
|
+
else
|
116
|
+
# We can't figure out what immediate parent is, we'll add parent_inventory_collections as dependencies
|
117
|
+
parent_inventory_collections.each { |ic_name| add_parent_inventory_collection_dependency!(ic_name) }
|
118
|
+
end
|
119
|
+
|
120
|
+
return if parent_inventory_collections.blank?
|
121
|
+
|
122
|
+
# Transform InventoryCollection object names to actual objects
|
123
|
+
self.parent_inventory_collections = parent_inventory_collections.map { |x| load_inventory_collection_by_name(x) }
|
124
|
+
end
|
125
|
+
|
126
|
+
def build_parent_inventory_collection!
|
127
|
+
return unless supports_building_inventory_collection?
|
128
|
+
|
129
|
+
if association.present? && parent.present? && associations_hash[association].present?
|
130
|
+
# Add immediate parent IC as dependency
|
131
|
+
add_parent_inventory_collection_dependency!(associations_hash[association])
|
132
|
+
# Add root IC in parent_inventory_collections
|
133
|
+
self.parent_inventory_collections = [find_parent_inventory_collection(associations_hash, inventory_collection.association)]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def supports_building_inventory_collection?
|
138
|
+
# Don't try to introspect ICs with custom query or saving code
|
139
|
+
return if arel.present? || custom_save_block.present?
|
140
|
+
# We support :parent_inventory_collections only for targeted mode, where all ICs are present
|
141
|
+
return unless targeted?
|
142
|
+
|
143
|
+
true
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_parent_inventory_collection_dependency!(ic_name)
|
147
|
+
ic = load_inventory_collection_by_name(ic_name)
|
148
|
+
(dependency_attributes[:__parent_inventory_collections] ||= Set.new) << ic if ic
|
149
|
+
end
|
150
|
+
|
151
|
+
def find_parent_inventory_collection(hash, name)
|
152
|
+
if hash[name]
|
153
|
+
find_parent_inventory_collection(hash, hash[name])
|
154
|
+
else
|
155
|
+
name
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def load_inventory_collection_by_name(name)
|
160
|
+
ic = indexed_inventory_collections[name]
|
161
|
+
if ic.nil?
|
162
|
+
raise "Can't find InventoryCollection :#{name} referenced from #{inventory_collection}" if targeted?
|
163
|
+
end
|
164
|
+
ic
|
165
|
+
end
|
166
|
+
|
89
167
|
def scan_inventory_object!(inventory_object)
|
90
168
|
inventory_object.data.each do |key, value|
|
91
169
|
if value.kind_of?(Array)
|
@@ -96,8 +174,23 @@ module InventoryRefresh
|
|
96
174
|
end
|
97
175
|
end
|
98
176
|
|
177
|
+
def loadable?(value)
|
178
|
+
inventory_object_lazy?(value) || inventory_object?(value)
|
179
|
+
end
|
180
|
+
|
181
|
+
def add_reference(value_inventory_collection, value)
|
182
|
+
value_inventory_collection.add_reference(value.reference, :key => value.key)
|
183
|
+
end
|
184
|
+
|
185
|
+
def scan_all_manager_uuids_scope_attribute!(value)
|
186
|
+
return unless loadable?(value)
|
187
|
+
|
188
|
+
add_reference(value.inventory_collection, value)
|
189
|
+
(dependency_attributes[:__all_manager_uuids_scope] ||= Set.new) << value.inventory_collection
|
190
|
+
end
|
191
|
+
|
99
192
|
def scan_inventory_object_attribute!(key, value)
|
100
|
-
return
|
193
|
+
return unless loadable?(value)
|
101
194
|
value_inventory_collection = value.inventory_collection
|
102
195
|
|
103
196
|
# Storing attributes and their dependencies
|
@@ -105,7 +198,7 @@ module InventoryRefresh
|
|
105
198
|
|
106
199
|
# Storing a reference in the target inventory_collection, then each IC knows about all the references and can
|
107
200
|
# e.g. load all the referenced uuids from a DB
|
108
|
-
|
201
|
+
add_reference(value_inventory_collection, value)
|
109
202
|
|
110
203
|
if inventory_object_lazy?(value)
|
111
204
|
# Storing if attribute is a transitive dependency, so a lazy_find :key results in dependency
|
@@ -4,6 +4,7 @@ module InventoryRefresh
|
|
4
4
|
class InventoryCollection
|
5
5
|
class Serialization
|
6
6
|
delegate :all_manager_uuids,
|
7
|
+
:all_manager_uuids=,
|
7
8
|
:build,
|
8
9
|
:targeted_scope,
|
9
10
|
:data,
|
@@ -27,18 +28,17 @@ module InventoryRefresh
|
|
27
28
|
# @param available_inventory_collections [Array<InventoryRefresh::InventoryCollection>] List of available
|
28
29
|
# InventoryCollection objects
|
29
30
|
def from_hash(inventory_objects_data, available_inventory_collections)
|
30
|
-
targeted_scope.merge!(inventory_objects_data["manager_uuids"].map(&:symbolize_keys!))
|
31
|
+
targeted_scope.merge!(inventory_objects_data["manager_uuids"].map(&:symbolize_keys!)) if inventory_objects_data["manager_uuids"]
|
31
32
|
|
32
|
-
inventory_objects_data['data'].each do |inventory_object_data|
|
33
|
+
(inventory_objects_data['data'] || []).each do |inventory_object_data|
|
33
34
|
build(hash_to_data(inventory_object_data, available_inventory_collections).symbolize_keys!)
|
34
35
|
end
|
35
36
|
|
36
|
-
inventory_objects_data['partial_data'].each do |inventory_object_data|
|
37
|
+
(inventory_objects_data['partial_data'] || []).each do |inventory_object_data|
|
37
38
|
skeletal_primary_index.build(hash_to_data(inventory_object_data, available_inventory_collections).symbolize_keys!)
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
-
# self.all_manager_uuids = inventory_objects_data['all_manager_uuids']
|
41
|
+
self.all_manager_uuids = inventory_objects_data['all_manager_uuids']
|
42
42
|
end
|
43
43
|
|
44
44
|
# Serializes InventoryCollection's data storage into Array of Hashes
|
@@ -105,9 +105,9 @@ module InventoryRefresh
|
|
105
105
|
raise "Nested lazy_relation of #{inventory_collection} is too deep, left processing: #{hash}" if depth > 20
|
106
106
|
|
107
107
|
hash.transform_values do |value|
|
108
|
-
if value.kind_of?(Hash) && value['
|
108
|
+
if value.kind_of?(Hash) && value['inventory_collection_name']
|
109
109
|
hash_to_lazy_relation(value, available_inventory_collections, depth)
|
110
|
-
elsif value.kind_of?(Array) && value.first.kind_of?(Hash) && value.first['
|
110
|
+
elsif value.kind_of?(Array) && value.first.kind_of?(Hash) && value.first['inventory_collection_name']
|
111
111
|
# TODO(lsmola) do we need to compact it sooner? What if first element is nil? On the other hand, we want to
|
112
112
|
# deprecate this Vm HABTM assignment because it's not effective
|
113
113
|
value.compact.map { |x| hash_to_lazy_relation(x, available_inventory_collections, depth) }
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "active_support/core_ext/module/delegation"
|
2
|
+
|
3
|
+
module InventoryRefresh
|
4
|
+
class InventoryCollection
|
5
|
+
class UnconnectedEdge
|
6
|
+
attr_reader :inventory_object, :inventory_object_key, :inventory_object_lazy
|
7
|
+
|
8
|
+
# @param inventory_object [InventoryRefresh::InventoryObject] InventoryObject that couldn't connect the relation
|
9
|
+
# @param inventory_object_key [String] Relation name that couldn't be connected
|
10
|
+
# @param inventory_object_lazy [InventoryRefresh::InventoryObjectLazy] The lazy relation that failed to load
|
11
|
+
# this can happen only for relations with key, or pointing to DB only relations
|
12
|
+
def initialize(inventory_object, inventory_object_key, inventory_object_lazy)
|
13
|
+
@inventory_object = inventory_object
|
14
|
+
@inventory_object_key = inventory_object_key
|
15
|
+
@inventory_object_lazy = inventory_object_lazy
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|