inventory_refresh 0.1.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|