inventory_refresh 0.3.6 → 1.0.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/.codeclimate.yml +25 -30
- data/.github/workflows/ci.yaml +47 -0
- data/.rubocop.yml +3 -3
- data/.rubocop_cc.yml +3 -4
- data/.rubocop_local.yml +5 -2
- data/.whitesource +3 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +10 -4
- data/README.md +1 -2
- data/Rakefile +2 -2
- data/inventory_refresh.gemspec +8 -9
- data/lib/inventory_refresh/application_record_iterator.rb +25 -12
- data/lib/inventory_refresh/graph/topological_sort.rb +24 -26
- data/lib/inventory_refresh/graph.rb +2 -2
- data/lib/inventory_refresh/inventory_collection/builder.rb +37 -15
- data/lib/inventory_refresh/inventory_collection/data_storage.rb +9 -0
- data/lib/inventory_refresh/inventory_collection/helpers/initialize_helper.rb +147 -38
- data/lib/inventory_refresh/inventory_collection/helpers/questions_helper.rb +48 -4
- data/lib/inventory_refresh/inventory_collection/index/proxy.rb +35 -3
- data/lib/inventory_refresh/inventory_collection/index/type/base.rb +8 -0
- data/lib/inventory_refresh/inventory_collection/index/type/local_db.rb +2 -0
- data/lib/inventory_refresh/inventory_collection/index/type/skeletal.rb +1 -0
- data/lib/inventory_refresh/inventory_collection/reference.rb +1 -0
- data/lib/inventory_refresh/inventory_collection/references_storage.rb +17 -0
- data/lib/inventory_refresh/inventory_collection/scanner.rb +91 -3
- data/lib/inventory_refresh/inventory_collection/serialization.rb +16 -10
- data/lib/inventory_refresh/inventory_collection.rb +122 -64
- data/lib/inventory_refresh/inventory_object.rb +74 -40
- data/lib/inventory_refresh/inventory_object_lazy.rb +17 -10
- data/lib/inventory_refresh/null_logger.rb +2 -2
- data/lib/inventory_refresh/persister.rb +43 -93
- data/lib/inventory_refresh/save_collection/base.rb +4 -2
- data/lib/inventory_refresh/save_collection/saver/base.rb +114 -15
- data/lib/inventory_refresh/save_collection/saver/batch.rb +17 -0
- data/lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb +129 -51
- data/lib/inventory_refresh/save_collection/saver/default.rb +57 -0
- data/lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb +2 -19
- data/lib/inventory_refresh/save_collection/saver/retention_helper.rb +68 -3
- data/lib/inventory_refresh/save_collection/saver/sql_helper.rb +125 -0
- data/lib/inventory_refresh/save_collection/saver/sql_helper_update.rb +10 -6
- data/lib/inventory_refresh/save_collection/saver/sql_helper_upsert.rb +28 -16
- data/lib/inventory_refresh/save_collection/sweeper.rb +17 -93
- data/lib/inventory_refresh/save_collection/topological_sort.rb +5 -5
- data/lib/inventory_refresh/save_inventory.rb +5 -12
- data/lib/inventory_refresh/target.rb +73 -0
- data/lib/inventory_refresh/target_collection.rb +92 -0
- data/lib/inventory_refresh/version.rb +1 -1
- data/lib/inventory_refresh.rb +2 -0
- metadata +34 -37
- data/.travis.yml +0 -23
- data/lib/inventory_refresh/exception.rb +0 -8
@@ -42,12 +42,64 @@ module InventoryRefresh
|
|
42
42
|
# Transforms InventoryObject object data into hash format with keys that are column names and resolves correct
|
43
43
|
# values of the foreign keys (even the polymorphic ones)
|
44
44
|
#
|
45
|
-
# @param
|
45
|
+
# @param inventory_collection_scope [InventoryRefresh::InventoryCollection] parent InventoryCollection object
|
46
|
+
# @return [Hash] Data in DB format
|
47
|
+
def attributes(inventory_collection_scope = nil)
|
48
|
+
# We should explicitly pass a scope, since the inventory_object can be mapped to more InventoryCollections with
|
49
|
+
# different blacklist and whitelist. The generic code always passes a scope.
|
50
|
+
inventory_collection_scope ||= inventory_collection
|
51
|
+
|
52
|
+
attributes_for_saving = {}
|
53
|
+
# First transform the values
|
54
|
+
data.each do |key, value|
|
55
|
+
if !allowed?(inventory_collection_scope, key)
|
56
|
+
next
|
57
|
+
elsif value.kind_of?(Array) && value.any? { |x| loadable?(x) }
|
58
|
+
# Lets fill also the original data, so other InventoryObject referring to this attribute gets the right
|
59
|
+
# result
|
60
|
+
data[key] = value.compact.map(&:load).compact
|
61
|
+
# We can use built in _ids methods to assign array of ids into has_many relations. So e.g. the :key_pairs=
|
62
|
+
# relation setter will become :key_pair_ids=
|
63
|
+
attributes_for_saving["#{key.to_s.singularize}_ids".to_sym] = data[key].map(&:id).compact.uniq
|
64
|
+
elsif loadable?(value) || inventory_collection_scope.association_to_foreign_key_mapping[key]
|
65
|
+
# Lets fill also the original data, so other InventoryObject referring to this attribute gets the right
|
66
|
+
# result
|
67
|
+
data[key] = value.load if value.respond_to?(:load)
|
68
|
+
if (foreign_key = inventory_collection_scope.association_to_foreign_key_mapping[key])
|
69
|
+
# We have an association to fill, lets fill also the :key, cause some other InventoryObject can refer to it
|
70
|
+
record_id = data[key].try(:id)
|
71
|
+
attributes_for_saving[foreign_key.to_sym] = record_id
|
72
|
+
|
73
|
+
if (foreign_type = inventory_collection_scope.association_to_foreign_type_mapping[key])
|
74
|
+
# If we have a polymorphic association, we need to also fill a base class name, but we want to nullify it
|
75
|
+
# if record_id is missing
|
76
|
+
base_class = data[key].try(:base_class_name) || data[key].class.try(:base_class).try(:name)
|
77
|
+
attributes_for_saving[foreign_type.to_sym] = record_id ? base_class : nil
|
78
|
+
end
|
79
|
+
elsif data[key].kind_of?(::InventoryRefresh::InventoryObject)
|
80
|
+
# We have an association to fill but not an Activerecord association, so e.g. Ancestry, lets just load
|
81
|
+
# it here. This way of storing ancestry is ineffective in DB call count, but RAM friendly
|
82
|
+
attributes_for_saving[key.to_sym] = data[key].base_class_name.constantize.find_by(:id => data[key].id)
|
83
|
+
else
|
84
|
+
# We have a normal attribute to fill
|
85
|
+
attributes_for_saving[key.to_sym] = data[key]
|
86
|
+
end
|
87
|
+
else
|
88
|
+
attributes_for_saving[key.to_sym] = value
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
attributes_for_saving
|
93
|
+
end
|
94
|
+
|
95
|
+
# Transforms InventoryObject object data into hash format with keys that are column names and resolves correct
|
96
|
+
# values of the foreign keys (even the polymorphic ones)
|
97
|
+
#
|
46
98
|
# @param inventory_collection_scope [InventoryRefresh::InventoryCollection] parent InventoryCollection object
|
47
99
|
# @param all_attribute_keys [Array<Symbol>] Attribute keys we will modify based on object's data
|
48
100
|
# @param inventory_object [InventoryRefresh::InventoryObject] InventoryObject object owning these attributes
|
49
101
|
# @return [Hash] Data in DB format
|
50
|
-
def
|
102
|
+
def attributes_with_keys(inventory_collection_scope = nil, all_attribute_keys = [], inventory_object = nil)
|
51
103
|
# We should explicitly pass a scope, since the inventory_object can be mapped to more InventoryCollections with
|
52
104
|
# different blacklist and whitelist. The generic code always passes a scope.
|
53
105
|
inventory_collection_scope ||= inventory_collection
|
@@ -96,8 +148,8 @@ module InventoryRefresh
|
|
96
148
|
def assign_attributes(attributes)
|
97
149
|
attributes.each do |k, v|
|
98
150
|
# We don't want timestamps or resource versions to be overwritten here, since those are driving the conditions
|
99
|
-
next if %i
|
100
|
-
next if %i
|
151
|
+
next if %i[resource_timestamps resource_timestamps_max resource_timestamp].include?(k)
|
152
|
+
next if %i[resource_counters resource_counters_max resource_counter].include?(k)
|
101
153
|
|
102
154
|
if data[:resource_timestamp] && attributes[:resource_timestamp]
|
103
155
|
assign_only_newest(:resource_timestamp, :resource_timestamps, attributes, data, k, v)
|
@@ -146,44 +198,14 @@ module InventoryRefresh
|
|
146
198
|
end
|
147
199
|
end
|
148
200
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
201
|
+
next if defined_methods.include?(attr.to_sym)
|
202
|
+
|
203
|
+
define_method(attr) do
|
204
|
+
data[attr]
|
153
205
|
end
|
154
206
|
end
|
155
207
|
end
|
156
208
|
|
157
|
-
# Return true if the attribute is allowed to be saved into the DB
|
158
|
-
#
|
159
|
-
# @param inventory_collection_scope [InventoryRefresh::InventoryCollection] InventoryCollection object owning the
|
160
|
-
# attribute
|
161
|
-
# @param key [Symbol] attribute name
|
162
|
-
# @return true if the attribute is allowed to be saved into the DB
|
163
|
-
def self.allowed?(inventory_collection_scope, key)
|
164
|
-
foreign_to_association = (inventory_collection_scope.foreign_key_to_association_mapping[key] ||
|
165
|
-
inventory_collection_scope.foreign_type_to_association_mapping[key])
|
166
|
-
|
167
|
-
return false if inventory_collection_scope.attributes_blacklist.present? &&
|
168
|
-
(inventory_collection_scope.attributes_blacklist.include?(key) ||
|
169
|
-
(foreign_to_association && inventory_collection_scope.attributes_blacklist.include?(foreign_to_association)))
|
170
|
-
|
171
|
-
return false if inventory_collection_scope.attributes_whitelist.present? &&
|
172
|
-
(!inventory_collection_scope.attributes_whitelist.include?(key) &&
|
173
|
-
(!foreign_to_association || (foreign_to_association && inventory_collection_scope.attributes_whitelist.include?(foreign_to_association))))
|
174
|
-
|
175
|
-
true
|
176
|
-
end
|
177
|
-
|
178
|
-
# Return true if the object is loadable, which we determine by a list of loadable classes.
|
179
|
-
#
|
180
|
-
# @param value [Object] object we test
|
181
|
-
# @return true if the object is loadable
|
182
|
-
def self.loadable?(value)
|
183
|
-
value.kind_of?(::InventoryRefresh::InventoryObjectLazy) || value.kind_of?(::InventoryRefresh::InventoryObject) ||
|
184
|
-
value.kind_of?(::InventoryRefresh::ApplicationRecordReference)
|
185
|
-
end
|
186
|
-
|
187
209
|
private
|
188
210
|
|
189
211
|
# Assigns value based on the version attributes. If versions are specified, it asigns attribute only if it's
|
@@ -261,7 +283,18 @@ module InventoryRefresh
|
|
261
283
|
# @param key [Symbol] attribute name
|
262
284
|
# @return true if the attribute is allowed to be saved into the DB
|
263
285
|
def allowed?(inventory_collection_scope, key)
|
264
|
-
|
286
|
+
foreign_to_association = inventory_collection_scope.foreign_key_to_association_mapping[key] ||
|
287
|
+
inventory_collection_scope.foreign_type_to_association_mapping[key]
|
288
|
+
|
289
|
+
return false if inventory_collection_scope.attributes_blacklist.present? &&
|
290
|
+
(inventory_collection_scope.attributes_blacklist.include?(key) ||
|
291
|
+
(foreign_to_association && inventory_collection_scope.attributes_blacklist.include?(foreign_to_association)))
|
292
|
+
|
293
|
+
return false if inventory_collection_scope.attributes_whitelist.present? &&
|
294
|
+
(!inventory_collection_scope.attributes_whitelist.include?(key) &&
|
295
|
+
(!foreign_to_association || (foreign_to_association && inventory_collection_scope.attributes_whitelist.include?(foreign_to_association))))
|
296
|
+
|
297
|
+
true
|
265
298
|
end
|
266
299
|
|
267
300
|
# Return true if the object is loadable, which we determine by a list of loadable classes.
|
@@ -269,7 +302,8 @@ module InventoryRefresh
|
|
269
302
|
# @param value [Object] object we test
|
270
303
|
# @return true if the object is loadable
|
271
304
|
def loadable?(value)
|
272
|
-
|
305
|
+
value.kind_of?(::InventoryRefresh::InventoryObjectLazy) || value.kind_of?(::InventoryRefresh::InventoryObject) ||
|
306
|
+
value.kind_of?(::InventoryRefresh::ApplicationRecordReference)
|
273
307
|
end
|
274
308
|
end
|
275
309
|
end
|
@@ -30,6 +30,7 @@ module InventoryRefresh
|
|
30
30
|
|
31
31
|
# @return [String] stringified reference
|
32
32
|
def to_s
|
33
|
+
# TODO(lsmola) do we need this method?
|
33
34
|
stringified_reference
|
34
35
|
end
|
35
36
|
|
@@ -70,6 +71,10 @@ module InventoryRefresh
|
|
70
71
|
|
71
72
|
# @return [Boolean] true if the key is an association on inventory_collection_scope model class
|
72
73
|
def association?(key)
|
74
|
+
# TODO(lsmola) remove this if there will be better dependency scan, probably with transitive dependencies filled
|
75
|
+
# in a second pass, then we can get rid of this hardcoded symbols. Right now we are not able to introspect these.
|
76
|
+
return true if [:parent, :genealogy_parent].include?(key)
|
77
|
+
|
73
78
|
inventory_collection.dependency_attributes.key?(key) ||
|
74
79
|
!inventory_collection.association_to_foreign_key_mapping[key].nil?
|
75
80
|
end
|
@@ -95,7 +100,7 @@ module InventoryRefresh
|
|
95
100
|
|
96
101
|
private
|
97
102
|
|
98
|
-
delegate :saved?, :saver_strategy, :skeletal_primary_index, :to => :inventory_collection
|
103
|
+
delegate :parallel_safe?, :saved?, :saver_strategy, :skeletal_primary_index, :targeted?, :to => :inventory_collection
|
99
104
|
delegate :nested_secondary_index?, :primary?, :full_reference, :keys, :primary?, :to => :reference
|
100
105
|
|
101
106
|
attr_writer :reference
|
@@ -107,18 +112,20 @@ module InventoryRefresh
|
|
107
112
|
#
|
108
113
|
# @return [InventoryRefresh::InventoryObject, NilClass] Returns pre-created InventoryObject or nil
|
109
114
|
def skeletal_precreate!
|
115
|
+
# We can do skeletal pre-create only for strategies using unique indexes. Since this can build records out of
|
116
|
+
# the given :arel scope, we will always attempt to create the recod, so we need unique index to avoid duplication
|
117
|
+
# of records.
|
118
|
+
return unless parallel_safe?
|
110
119
|
# Pre-create only for strategies that will be persisting data, i.e. are not saved already
|
111
120
|
return if saved?
|
112
121
|
# We can only do skeletal pre-create for primary index reference, since that is needed to create DB unique index
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
#
|
118
|
-
#
|
119
|
-
|
120
|
-
# smartly, since having nil means we will need to use different unique index for the upsert/update query.
|
121
|
-
return if keys.any? { |x| full_reference[x].nil? }
|
122
|
+
return unless primary?
|
123
|
+
# Full reference must be present
|
124
|
+
return if full_reference.blank?
|
125
|
+
|
126
|
+
# To avoid pre-creating invalid records all fields of a primary key must have value
|
127
|
+
# TODO(lsmola) for composite keys, it's still valid to have one of the keys nil, figure out how to allow this
|
128
|
+
return if keys.any? { |x| full_reference[x].blank? }
|
122
129
|
|
123
130
|
skeletal_primary_index.build(full_reference)
|
124
131
|
end
|
@@ -3,21 +3,18 @@ module InventoryRefresh
|
|
3
3
|
require 'json'
|
4
4
|
require 'yaml'
|
5
5
|
|
6
|
-
attr_reader :manager, :collections
|
6
|
+
attr_reader :manager, :target, :collections
|
7
7
|
|
8
|
-
attr_accessor :refresh_state_uuid, :refresh_state_part_uuid, :
|
9
|
-
attr_accessor :persister_started_at, :persister_finished_at,
|
10
|
-
:refresh_state_part_collected_at, :refresh_state_part_sent_at,
|
11
|
-
:refresh_state_started_at, :refresh_state_sent_at, :ingress_api_sent_at
|
8
|
+
attr_accessor :refresh_state_uuid, :refresh_state_part_uuid, :total_parts, :sweep_scope, :retry_count, :retry_max
|
12
9
|
|
13
10
|
# @param manager [ManageIQ::Providers::BaseManager] A manager object
|
14
|
-
|
11
|
+
# @param target [Object] A refresh Target object
|
12
|
+
def initialize(manager, target = nil)
|
15
13
|
@manager = manager
|
14
|
+
@target = target
|
16
15
|
|
17
16
|
@collections = {}
|
18
17
|
|
19
|
-
self.persister_started_at = Time.now.utc.to_datetime.to_s
|
20
|
-
|
21
18
|
initialize_inventory_collections
|
22
19
|
end
|
23
20
|
|
@@ -48,6 +45,9 @@ module InventoryRefresh
|
|
48
45
|
&block)
|
49
46
|
|
50
47
|
builder.add_properties(extra_properties) if extra_properties.present?
|
48
|
+
|
49
|
+
builder.add_properties({:manager_uuids => target.try(:references, collection_name) || []}, :if_missing) if targeted?
|
50
|
+
|
51
51
|
builder.evaluate_lambdas!(self)
|
52
52
|
|
53
53
|
collections[collection_name] = builder.to_inventory_collection
|
@@ -66,7 +66,7 @@ module InventoryRefresh
|
|
66
66
|
# @return [InventoryRefresh::InventoryCollection] returns a defined InventoryCollection or undefined method
|
67
67
|
def method_missing(method_name, *arguments, &block)
|
68
68
|
if inventory_collections_names.include?(method_name)
|
69
|
-
|
69
|
+
define_collections_reader(method_name)
|
70
70
|
send(method_name)
|
71
71
|
else
|
72
72
|
super
|
@@ -96,7 +96,7 @@ module InventoryRefresh
|
|
96
96
|
|
97
97
|
# Returns serialized Persisted object to JSON
|
98
98
|
# @return [String] serialized Persisted object to JSON
|
99
|
-
def to_json
|
99
|
+
def to_json(*_args)
|
100
100
|
JSON.dump(to_hash)
|
101
101
|
end
|
102
102
|
|
@@ -104,25 +104,21 @@ module InventoryRefresh
|
|
104
104
|
def to_hash
|
105
105
|
collections_data = collections.map do |_, collection|
|
106
106
|
next if collection.data.blank? &&
|
107
|
+
collection.targeted_scope.primary_references.blank? &&
|
108
|
+
collection.all_manager_uuids.nil? &&
|
107
109
|
collection.skeletal_primary_index.index_data.blank?
|
108
110
|
|
109
111
|
collection.to_hash
|
110
112
|
end.compact
|
111
113
|
|
112
114
|
{
|
113
|
-
:refresh_state_uuid
|
114
|
-
:refresh_state_part_uuid
|
115
|
-
:
|
116
|
-
:
|
117
|
-
:
|
118
|
-
:
|
119
|
-
:
|
120
|
-
:refresh_time_tracking => refresh_time_tracking,
|
121
|
-
:retry_count => retry_count,
|
122
|
-
:retry_max => retry_max,
|
123
|
-
:total_parts => total_parts,
|
124
|
-
:sweep_scope => sweep_scope_to_hash(sweep_scope),
|
125
|
-
:collections => collections_data,
|
115
|
+
:refresh_state_uuid => refresh_state_uuid,
|
116
|
+
:refresh_state_part_uuid => refresh_state_part_uuid,
|
117
|
+
:retry_count => retry_count,
|
118
|
+
:retry_max => retry_max,
|
119
|
+
:total_parts => total_parts,
|
120
|
+
:sweep_scope => sweep_scope,
|
121
|
+
:collections => collections_data,
|
126
122
|
}
|
127
123
|
end
|
128
124
|
|
@@ -131,70 +127,33 @@ module InventoryRefresh
|
|
131
127
|
#
|
132
128
|
# @param json_data [String] input JSON data
|
133
129
|
# @return [ManageIQ::Providers::Inventory::Persister] Persister object loaded from a passed JSON
|
134
|
-
def from_json(json_data, manager)
|
135
|
-
from_hash(JSON.parse(json_data), manager)
|
130
|
+
def from_json(json_data, manager, target = nil)
|
131
|
+
from_hash(JSON.parse(json_data), manager, target)
|
136
132
|
end
|
137
133
|
|
138
134
|
# Returns Persister object built from serialized data
|
139
135
|
#
|
140
136
|
# @param persister_data [Hash] serialized Persister object in hash
|
141
137
|
# @return [ManageIQ::Providers::Inventory::Persister] Persister object built from serialized data
|
142
|
-
def from_hash(persister_data, manager)
|
143
|
-
|
138
|
+
def from_hash(persister_data, manager, target = nil)
|
139
|
+
# TODO(lsmola) we need to pass serialized targeted scope here
|
140
|
+
target ||= InventoryRefresh::TargetCollection.new(:manager => manager)
|
141
|
+
|
142
|
+
new(manager, target).tap do |persister|
|
144
143
|
persister_data['collections'].each do |collection|
|
145
144
|
inventory_collection = persister.collections[collection['name'].try(:to_sym)]
|
146
|
-
raise "Unrecognized InventoryCollection name: #{
|
145
|
+
raise "Unrecognized InventoryCollection name: #{inventory_collection}" if inventory_collection.blank?
|
147
146
|
|
148
147
|
inventory_collection.from_hash(collection, persister.collections)
|
149
148
|
end
|
150
149
|
|
151
|
-
persister.refresh_state_uuid
|
152
|
-
persister.refresh_state_part_uuid
|
153
|
-
persister.
|
154
|
-
persister.
|
155
|
-
persister.
|
156
|
-
persister.
|
157
|
-
persister.ingress_api_sent_at = persister_data['ingress_api_sent_at']
|
158
|
-
persister.retry_count = persister_data['retry_count']
|
159
|
-
persister.retry_max = persister_data['retry_max']
|
160
|
-
persister.total_parts = persister_data['total_parts']
|
161
|
-
persister.sweep_scope = sweep_scope_from_hash(persister_data['sweep_scope'], persister.collections)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
private
|
166
|
-
|
167
|
-
def assert_sweep_scope!(sweep_scope)
|
168
|
-
return unless sweep_scope
|
169
|
-
|
170
|
-
allowed_format_message = "Allowed format of sweep scope is Array<String> or Hash{String => Hash}, got #{sweep_scope}"
|
171
|
-
|
172
|
-
if sweep_scope.kind_of?(Array)
|
173
|
-
return if sweep_scope.all? { |x| x.kind_of?(String) || x.kind_of?(Symbol) }
|
174
|
-
|
175
|
-
raise InventoryRefresh::Exception::SweeperScopeBadFormat, allowed_format_message
|
176
|
-
elsif sweep_scope.kind_of?(Hash)
|
177
|
-
return if sweep_scope.values.all? { |x| x.kind_of?(Array) }
|
178
|
-
|
179
|
-
raise InventoryRefresh::Exception::SweeperScopeBadFormat, allowed_format_message
|
150
|
+
persister.refresh_state_uuid = persister_data['refresh_state_uuid']
|
151
|
+
persister.refresh_state_part_uuid = persister_data['refresh_state_part_uuid']
|
152
|
+
persister.retry_count = persister_data['retry_count']
|
153
|
+
persister.retry_max = persister_data['retry_max']
|
154
|
+
persister.total_parts = persister_data['total_parts']
|
155
|
+
persister.sweep_scope = persister_data['sweep_scope']
|
180
156
|
end
|
181
|
-
|
182
|
-
raise InventoryRefresh::Exception::SweeperScopeBadFormat, allowed_format_message
|
183
|
-
end
|
184
|
-
|
185
|
-
def sweep_scope_from_hash(sweep_scope, available_inventory_collections)
|
186
|
-
assert_sweep_scope!(sweep_scope)
|
187
|
-
|
188
|
-
return sweep_scope unless sweep_scope.kind_of?(Hash)
|
189
|
-
|
190
|
-
sweep_scope.each_with_object({}) do |(k, v), obj|
|
191
|
-
inventory_collection = available_inventory_collections[k.try(:to_sym)]
|
192
|
-
raise "Unrecognized InventoryCollection name: #{k}" if inventory_collection.blank?
|
193
|
-
|
194
|
-
serializer = InventoryRefresh::InventoryCollection::Serialization.new(inventory_collection)
|
195
|
-
|
196
|
-
obj[k] = serializer.sweep_scope_from_hash(v, available_inventory_collections)
|
197
|
-
end.symbolize_keys!
|
198
157
|
end
|
199
158
|
end
|
200
159
|
|
@@ -226,37 +185,28 @@ module InventoryRefresh
|
|
226
185
|
nil
|
227
186
|
end
|
228
187
|
|
229
|
-
def
|
188
|
+
def saver_strategy
|
189
|
+
:default
|
190
|
+
end
|
191
|
+
|
192
|
+
# Persisters for targeted refresh can override to true
|
193
|
+
def targeted?
|
230
194
|
false
|
231
195
|
end
|
232
196
|
|
233
|
-
def
|
234
|
-
|
197
|
+
def assert_graph_integrity?
|
198
|
+
false
|
235
199
|
end
|
236
200
|
|
237
201
|
# @return [Hash] kwargs shared for all InventoryCollection objects
|
238
202
|
def shared_options
|
239
203
|
{
|
204
|
+
:saver_strategy => saver_strategy,
|
240
205
|
:strategy => strategy,
|
206
|
+
:targeted => targeted?,
|
241
207
|
:parent => manager.presence,
|
242
208
|
:assert_graph_integrity => assert_graph_integrity?,
|
243
|
-
:use_ar_object => use_ar_object?,
|
244
209
|
}
|
245
210
|
end
|
246
|
-
|
247
|
-
private
|
248
|
-
|
249
|
-
def sweep_scope_to_hash(sweep_scope)
|
250
|
-
return sweep_scope unless sweep_scope.kind_of?(Hash)
|
251
|
-
|
252
|
-
sweep_scope.each_with_object({}) do |(k, v), obj|
|
253
|
-
inventory_collection = collections[k.try(:to_sym)]
|
254
|
-
raise "Unrecognized InventoryCollection name: #{k}" if inventory_collection.blank?
|
255
|
-
|
256
|
-
serializer = InventoryRefresh::InventoryCollection::Serialization.new(inventory_collection)
|
257
|
-
|
258
|
-
obj[k] = serializer.sweep_scope_to_hash(v)
|
259
|
-
end
|
260
|
-
end
|
261
211
|
end
|
262
212
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require "inventory_refresh/logging"
|
2
|
+
require "inventory_refresh/save_collection/saver/batch"
|
2
3
|
require "inventory_refresh/save_collection/saver/concurrent_safe_batch"
|
4
|
+
require "inventory_refresh/save_collection/saver/default"
|
3
5
|
|
4
6
|
module InventoryRefresh::SaveCollection
|
5
7
|
class Base
|
@@ -14,7 +16,7 @@ module InventoryRefresh::SaveCollection
|
|
14
16
|
return if skip?(inventory_collection)
|
15
17
|
|
16
18
|
logger.debug("----- BEGIN ----- Saving collection #{inventory_collection} of size #{inventory_collection.size} to"\
|
17
|
-
" the database, for the manager: '#{ems.
|
19
|
+
" the database, for the manager: '#{ems.name}'...")
|
18
20
|
|
19
21
|
if inventory_collection.custom_save_block.present?
|
20
22
|
logger.debug("Saving collection #{inventory_collection} using a custom save block")
|
@@ -22,7 +24,7 @@ module InventoryRefresh::SaveCollection
|
|
22
24
|
else
|
23
25
|
save_inventory(inventory_collection)
|
24
26
|
end
|
25
|
-
logger.debug("----- END ----- Saving collection #{inventory_collection}, for the manager: '#{ems.
|
27
|
+
logger.debug("----- END ----- Saving collection #{inventory_collection}, for the manager: '#{ems.name}'...Complete")
|
26
28
|
inventory_collection.saved = true
|
27
29
|
end
|
28
30
|
|