inventory_refresh 0.1.2 → 0.2.3
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 +1 -0
- data/.gitignore +6 -0
- data/.travis.yml +3 -3
- data/Gemfile +4 -0
- data/inventory_refresh.gemspec +7 -5
- data/lib/inventory_refresh.rb +1 -0
- data/lib/inventory_refresh/inventory_collection.rb +114 -649
- 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.rb +6 -0
- 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/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_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
- metadata +73 -25
- data/lib/inventory_refresh/save_collection/recursive.rb +0 -52
- data/lib/inventory_refresh/save_collection/saver/concurrent_safe.rb +0 -71
@@ -0,0 +1,132 @@
|
|
1
|
+
require_relative "../helpers"
|
2
|
+
|
3
|
+
module InventoryRefresh
|
4
|
+
class InventoryCollection
|
5
|
+
module Helpers
|
6
|
+
module QuestionsHelper
|
7
|
+
# @return [Boolean] true means we want to call .changed? on every ActiveRecord object before saving it
|
8
|
+
def check_changed?
|
9
|
+
check_changed
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Boolean] true means we want to use ActiveRecord object for writing attributes and we want to perform
|
13
|
+
# casting on all columns
|
14
|
+
def use_ar_object?
|
15
|
+
use_ar_object
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Boolean] true means the data is not complete, leading to only creating and updating data
|
19
|
+
def complete?
|
20
|
+
complete
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Boolean] true means we want to only update data
|
24
|
+
def update_only?
|
25
|
+
update_only
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Boolean] true means we will delete/soft-delete data
|
29
|
+
def delete_allowed?
|
30
|
+
complete? && !update_only?
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Boolean] true means we will delete/soft-delete data
|
34
|
+
def create_allowed?
|
35
|
+
!update_only?
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [Boolean] true means that only create of new data is allowed
|
39
|
+
def create_only?
|
40
|
+
create_only
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Boolean] true if the whole InventoryCollection object has all data persisted
|
44
|
+
def saved?
|
45
|
+
saved
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Boolean] true if all dependencies have all data persisted
|
49
|
+
def saveable?
|
50
|
+
dependencies.all?(&:saved?)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Boolean] true if we are using a saver strategy that allows saving in parallel processes
|
54
|
+
def parallel_safe?
|
55
|
+
@parallel_safe_cache ||= %i(concurrent_safe concurrent_safe_batch).include?(saver_strategy)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Boolean] true if the model_class supports STI
|
59
|
+
def supports_sti?
|
60
|
+
@supports_sti_cache = model_class.column_names.include?("type") if @supports_sti_cache.nil?
|
61
|
+
@supports_sti_cache
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param column_name [Symbol, String]
|
65
|
+
# @return [Boolean] true if the model_class supports given column
|
66
|
+
def supports_column?(column_name)
|
67
|
+
@supported_cols_cache ||= {}
|
68
|
+
return @supported_cols_cache[column_name.to_sym] unless @supported_cols_cache[column_name.to_sym].nil?
|
69
|
+
|
70
|
+
include_col = model_class.column_names.include?(column_name.to_s)
|
71
|
+
if %w(created_on created_at updated_on updated_at).include?(column_name.to_s)
|
72
|
+
include_col &&= ActiveRecord::Base.record_timestamps
|
73
|
+
end
|
74
|
+
|
75
|
+
@supported_cols_cache[column_name.to_sym] = include_col
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [Boolean] true if no more data will be added to this InventoryCollection object, that usually happens
|
79
|
+
# after the parsing step is finished
|
80
|
+
def data_collection_finalized?
|
81
|
+
data_collection_finalized
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Boolean] true is processing of this InventoryCollection will be in targeted mode
|
85
|
+
def targeted?
|
86
|
+
targeted
|
87
|
+
end
|
88
|
+
|
89
|
+
# True if processing of this InventoryCollection object would lead to no operations. Then we use this marker to
|
90
|
+
# stop processing of the InventoryCollector object very soon, to avoid a lot of unnecessary Db queries, etc.
|
91
|
+
#
|
92
|
+
# @return [Boolean] true if processing of this InventoryCollection object would lead to no operations.
|
93
|
+
def noop?
|
94
|
+
# If this InventoryCollection doesn't do anything. it can easily happen for targeted/batched strategies.
|
95
|
+
saving_noop? && delete_complement_noop?
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [Boolean] true if processing InventoryCollection will not lead to any created/updated/deleted record
|
99
|
+
def saving_noop?
|
100
|
+
saving_targeted_parent_collection_noop? || saving_targeted_child_collection_noop? || saving_full_collection_noop?
|
101
|
+
end
|
102
|
+
|
103
|
+
# @return true if processing InventoryCollection will not lead to deleting the complement of passed ids
|
104
|
+
def delete_complement_noop?
|
105
|
+
all_manager_uuids.nil?
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
# @return true if it's a noop parent targeted InventoryCollection
|
111
|
+
def saving_targeted_parent_collection_noop?
|
112
|
+
targeted_noop_condition && parent_inventory_collections.blank? && targeted_scope.primary_references.blank?
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return true if it's a noop child targeted InventoryCollection
|
116
|
+
def saving_targeted_child_collection_noop?
|
117
|
+
targeted_noop_condition && parent_inventory_collections.present? &&
|
118
|
+
parent_inventory_collections.all? { |x| x.targeted_scope.primary_references.blank? }
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return true if it's a noop full InventoryCollection refresh
|
122
|
+
def saving_full_collection_noop?
|
123
|
+
!targeted? && data.blank? && !delete_allowed? && skeletal_primary_index.blank?
|
124
|
+
end
|
125
|
+
|
126
|
+
def targeted_noop_condition
|
127
|
+
targeted? && custom_save_block.nil? && skeletal_primary_index.blank?
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -87,19 +87,19 @@ module InventoryRefresh
|
|
87
87
|
#
|
88
88
|
# @param attributes [Hash] Attributes we want to extend with version related attributes
|
89
89
|
def fill_versions!(attributes)
|
90
|
-
if inventory_collection.
|
90
|
+
if inventory_collection.supports_column?(:resource_timestamps_max) && attributes[:resource_timestamp]
|
91
91
|
fill_specific_version_attr(:resource_timestamps, :resource_timestamp, attributes)
|
92
|
-
elsif inventory_collection.
|
93
|
-
fill_specific_version_attr(:
|
92
|
+
elsif inventory_collection.supports_column?(:resource_counters_max) && attributes[:resource_counter]
|
93
|
+
fill_specific_version_attr(:resource_counters, :resource_counter, attributes)
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
97
|
# Add specific versions columns into the passed attributes
|
98
98
|
#
|
99
99
|
# @param partial_row_version_attr [Symbol] Attr name for partial rows, allowed values are
|
100
|
-
# [:resource_timestamps, :
|
100
|
+
# [:resource_timestamps, :resource_counters]
|
101
101
|
# @param full_row_version_attr [Symbol] Attr name for full rows, allowed values are
|
102
|
-
# [:resource_timestamp, :
|
102
|
+
# [:resource_timestamp, :resource_counter]
|
103
103
|
# @param attributes [Hash] Attributes we want to extend with version related attributes
|
104
104
|
def fill_specific_version_attr(partial_row_version_attr, full_row_version_attr, attributes)
|
105
105
|
# We have to symbolize, since serializing persistor makes these strings
|
@@ -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
|
@@ -25,8 +25,13 @@ module InventoryRefresh
|
|
25
25
|
reference.stringified_reference
|
26
26
|
end
|
27
27
|
|
28
|
+
# @return [Hash] hash reference having :manager_ref keys, which can uniquely identity entity under a manager
|
29
|
+
def uuid
|
30
|
+
reference.full_reference.slice(*reference.keys).stringify_keys!
|
31
|
+
end
|
32
|
+
|
28
33
|
# @return [InventoryRefresh::InventoryObject] returns self
|
29
|
-
def load
|
34
|
+
def load(*_args)
|
30
35
|
self
|
31
36
|
end
|
32
37
|
|
@@ -92,8 +97,9 @@ module InventoryRefresh
|
|
92
97
|
#
|
93
98
|
# @param inventory_collection_scope [InventoryRefresh::InventoryCollection] parent InventoryCollection object
|
94
99
|
# @param all_attribute_keys [Array<Symbol>] Attribute keys we will modify based on object's data
|
100
|
+
# @param inventory_object [InventoryRefresh::InventoryObject] InventoryObject object owning these attributes
|
95
101
|
# @return [Hash] Data in DB format
|
96
|
-
def attributes_with_keys(inventory_collection_scope = nil, all_attribute_keys = [])
|
102
|
+
def attributes_with_keys(inventory_collection_scope = nil, all_attribute_keys = [], inventory_object = nil)
|
97
103
|
# We should explicitly pass a scope, since the inventory_object can be mapped to more InventoryCollections with
|
98
104
|
# different blacklist and whitelist. The generic code always passes a scope.
|
99
105
|
inventory_collection_scope ||= inventory_collection
|
@@ -106,7 +112,7 @@ module InventoryRefresh
|
|
106
112
|
elsif loadable?(value) || inventory_collection_scope.association_to_foreign_key_mapping[key]
|
107
113
|
# Lets fill also the original data, so other InventoryObject referring to this attribute gets the right
|
108
114
|
# result
|
109
|
-
data[key] = value.load if value.respond_to?(:load)
|
115
|
+
data[key] = value.load(inventory_object, key) if value.respond_to?(:load)
|
110
116
|
if (foreign_key = inventory_collection_scope.association_to_foreign_key_mapping[key])
|
111
117
|
# We have an association to fill, lets fill also the :key, cause some other InventoryObject can refer to it
|
112
118
|
record_id = data[key].try(:id)
|
@@ -143,12 +149,12 @@ module InventoryRefresh
|
|
143
149
|
attributes.each do |k, v|
|
144
150
|
# We don't want timestamps or resource versions to be overwritten here, since those are driving the conditions
|
145
151
|
next if %i(resource_timestamps resource_timestamps_max resource_timestamp).include?(k)
|
146
|
-
next if %i(
|
152
|
+
next if %i(resource_counters resource_counters_max resource_counter).include?(k)
|
147
153
|
|
148
154
|
if data[:resource_timestamp] && attributes[:resource_timestamp]
|
149
155
|
assign_only_newest(:resource_timestamp, :resource_timestamps, attributes, data, k, v)
|
150
|
-
elsif data[:
|
151
|
-
assign_only_newest(:
|
156
|
+
elsif data[:resource_counter] && attributes[:resource_counter]
|
157
|
+
assign_only_newest(:resource_counter, :resource_counters, attributes, data, k, v)
|
152
158
|
else
|
153
159
|
public_send("#{k}=", v)
|
154
160
|
end
|
@@ -156,8 +162,8 @@ module InventoryRefresh
|
|
156
162
|
|
157
163
|
if attributes[:resource_timestamp]
|
158
164
|
assign_full_row_version_attr(:resource_timestamp, attributes, data)
|
159
|
-
elsif attributes[:
|
160
|
-
assign_full_row_version_attr(:
|
165
|
+
elsif attributes[:resource_counter]
|
166
|
+
assign_full_row_version_attr(:resource_counter, attributes, data)
|
161
167
|
end
|
162
168
|
|
163
169
|
self
|
@@ -206,9 +212,9 @@ module InventoryRefresh
|
|
206
212
|
# newer than existing attribute.
|
207
213
|
#
|
208
214
|
# @param full_row_version_attr [Symbol] Attr name for full rows, allowed values are
|
209
|
-
# [:resource_timestamp, :
|
215
|
+
# [:resource_timestamp, :resource_counter]
|
210
216
|
# @param partial_row_version_attr [Symbol] Attr name for partial rows, allowed values are
|
211
|
-
# [:resource_timestamps, :
|
217
|
+
# [:resource_timestamps, :resource_counters]
|
212
218
|
# @param attributes [Hash] New attributes we are assigning
|
213
219
|
# @param data [Hash] Existing attributes of the InventoryObject
|
214
220
|
# @param k [Symbol] Name of the attribute we are assigning
|
@@ -247,7 +253,7 @@ module InventoryRefresh
|
|
247
253
|
# Assigns attribute representing version of the whole row
|
248
254
|
#
|
249
255
|
# @param full_row_version_attr [Symbol] Attr name for full rows, allowed values are
|
250
|
-
# [:resource_timestamp, :
|
256
|
+
# [:resource_timestamp, :resource_counter]
|
251
257
|
# @param attributes [Hash] New attributes we are assigning
|
252
258
|
# @param data [Hash] Existing attributes of the InventoryObject
|
253
259
|
def assign_full_row_version_attr(full_row_version_attr, attributes, data)
|