inventory_refresh 0.3.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +25 -30
  3. data/.github/workflows/ci.yaml +47 -0
  4. data/.rubocop.yml +3 -3
  5. data/.rubocop_cc.yml +3 -4
  6. data/.rubocop_local.yml +5 -2
  7. data/.whitesource +3 -0
  8. data/CHANGELOG.md +19 -0
  9. data/Gemfile +10 -4
  10. data/README.md +1 -2
  11. data/Rakefile +2 -2
  12. data/inventory_refresh.gemspec +8 -9
  13. data/lib/inventory_refresh/application_record_iterator.rb +25 -12
  14. data/lib/inventory_refresh/graph/topological_sort.rb +24 -26
  15. data/lib/inventory_refresh/graph.rb +2 -2
  16. data/lib/inventory_refresh/inventory_collection/builder.rb +37 -15
  17. data/lib/inventory_refresh/inventory_collection/data_storage.rb +9 -0
  18. data/lib/inventory_refresh/inventory_collection/helpers/initialize_helper.rb +147 -38
  19. data/lib/inventory_refresh/inventory_collection/helpers/questions_helper.rb +48 -4
  20. data/lib/inventory_refresh/inventory_collection/index/proxy.rb +35 -3
  21. data/lib/inventory_refresh/inventory_collection/index/type/base.rb +8 -0
  22. data/lib/inventory_refresh/inventory_collection/index/type/local_db.rb +2 -0
  23. data/lib/inventory_refresh/inventory_collection/index/type/skeletal.rb +1 -0
  24. data/lib/inventory_refresh/inventory_collection/reference.rb +1 -0
  25. data/lib/inventory_refresh/inventory_collection/references_storage.rb +17 -0
  26. data/lib/inventory_refresh/inventory_collection/scanner.rb +91 -3
  27. data/lib/inventory_refresh/inventory_collection/serialization.rb +16 -10
  28. data/lib/inventory_refresh/inventory_collection.rb +122 -64
  29. data/lib/inventory_refresh/inventory_object.rb +74 -40
  30. data/lib/inventory_refresh/inventory_object_lazy.rb +17 -10
  31. data/lib/inventory_refresh/null_logger.rb +2 -2
  32. data/lib/inventory_refresh/persister.rb +43 -93
  33. data/lib/inventory_refresh/save_collection/base.rb +4 -2
  34. data/lib/inventory_refresh/save_collection/saver/base.rb +114 -15
  35. data/lib/inventory_refresh/save_collection/saver/batch.rb +17 -0
  36. data/lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb +129 -51
  37. data/lib/inventory_refresh/save_collection/saver/default.rb +57 -0
  38. data/lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb +2 -19
  39. data/lib/inventory_refresh/save_collection/saver/retention_helper.rb +68 -3
  40. data/lib/inventory_refresh/save_collection/saver/sql_helper.rb +125 -0
  41. data/lib/inventory_refresh/save_collection/saver/sql_helper_update.rb +10 -6
  42. data/lib/inventory_refresh/save_collection/saver/sql_helper_upsert.rb +28 -16
  43. data/lib/inventory_refresh/save_collection/sweeper.rb +17 -93
  44. data/lib/inventory_refresh/save_collection/topological_sort.rb +5 -5
  45. data/lib/inventory_refresh/save_inventory.rb +5 -12
  46. data/lib/inventory_refresh/target.rb +73 -0
  47. data/lib/inventory_refresh/target_collection.rb +92 -0
  48. data/lib/inventory_refresh/version.rb +1 -1
  49. data/lib/inventory_refresh.rb +2 -0
  50. metadata +34 -37
  51. data/.travis.yml +0 -23
  52. 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 data [Array<Object>] Array of objects that we want to map to DB table columns
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 self.attributes_with_keys(data, inventory_collection_scope = nil, all_attribute_keys = [], inventory_object = nil)
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(resource_timestamps resource_timestamps_max resource_timestamp).include?(k)
100
- next if %i(resource_counters resource_counters_max resource_counter).include?(k)
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
- unless defined_methods.include?(attr.to_sym)
150
- define_method(attr) do
151
- data[attr]
152
- end
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
- self.class.allowed?(inventory_collection_scope, key)
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
- self.class.loadable?(value)
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
- # and full reference must be present
114
- return if !primary? || full_reference.blank?
115
-
116
- # To avoid pre-creating invalid records all fields of a primary key must have non null value
117
- # TODO(lsmola) for composite keys, it's still valid to have one of the keys nil, figure out how to allow this. We
118
- # will need to scan the DB for NOT NULL constraint and allow it based on that. So we would move this check to
119
- # saving code, but this will require bigger change, since having the column nil means we will have to batch it
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,10 +3,10 @@ require "logger"
3
3
  module InventoryRefresh
4
4
  class NullLogger < Logger
5
5
  def initialize(*_args)
6
- end
6
+ end
7
7
 
8
8
  def add(*_args, &_block)
9
- end
9
+ end
10
10
 
11
11
  def debug?
12
12
  false
@@ -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, :refresh_time_tracking, :total_parts, :sweep_scope, :retry_count, :retry_max
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
- def initialize(manager)
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
- self.define_collections_reader(method_name)
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 => refresh_state_uuid,
114
- :refresh_state_part_uuid => refresh_state_part_uuid,
115
- :refresh_state_part_collected_at => refresh_state_part_collected_at,
116
- :refresh_state_part_sent_at => refresh_state_part_sent_at,
117
- :refresh_state_started_at => refresh_state_started_at,
118
- :refresh_state_sent_at => refresh_state_sent_at,
119
- :ingress_api_sent_at => ingress_api_sent_at,
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
- new(manager).tap do |persister|
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: #{collection['name']}" if inventory_collection.blank?
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 = persister_data['refresh_state_uuid']
152
- persister.refresh_state_part_uuid = persister_data['refresh_state_part_uuid']
153
- persister.refresh_state_part_collected_at = persister_data['refresh_state_part_collected_at']
154
- persister.refresh_state_part_sent_at = persister_data['refresh_state_part_sent_at']
155
- persister.refresh_state_started_at = persister_data['refresh_state_started_at']
156
- persister.refresh_state_sent_at = persister_data['refresh_state_sent_at']
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 assert_graph_integrity?
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 use_ar_object?
234
- true
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.id}'...")
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.id}'...Complete")
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