inventory_refresh 0.2.2 → 0.3.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 +0 -1
- data/.travis.yml +6 -8
- data/inventory_refresh.gemspec +2 -4
- data/lib/inventory_refresh.rb +0 -2
- data/lib/inventory_refresh/application_record_iterator.rb +9 -26
- data/lib/inventory_refresh/exception.rb +8 -0
- data/lib/inventory_refresh/inventory_collection.rb +36 -110
- data/lib/inventory_refresh/inventory_collection/builder.rb +6 -6
- data/lib/inventory_refresh/inventory_collection/data_storage.rb +0 -9
- data/lib/inventory_refresh/inventory_collection/helpers/initialize_helper.rb +34 -143
- data/lib/inventory_refresh/inventory_collection/helpers/questions_helper.rb +1 -44
- data/lib/inventory_refresh/inventory_collection/index/proxy.rb +6 -34
- data/lib/inventory_refresh/inventory_collection/index/type/base.rb +0 -8
- data/lib/inventory_refresh/inventory_collection/references_storage.rb +0 -17
- data/lib/inventory_refresh/inventory_collection/scanner.rb +1 -87
- data/lib/inventory_refresh/inventory_collection/serialization.rb +10 -16
- data/lib/inventory_refresh/inventory_object.rb +34 -68
- data/lib/inventory_refresh/inventory_object_lazy.rb +10 -17
- data/lib/inventory_refresh/persister.rb +63 -29
- data/lib/inventory_refresh/save_collection/base.rb +2 -4
- data/lib/inventory_refresh/save_collection/saver/base.rb +8 -108
- data/lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb +48 -126
- data/lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb +19 -1
- data/lib/inventory_refresh/save_collection/saver/retention_helper.rb +3 -68
- data/lib/inventory_refresh/save_collection/saver/sql_helper.rb +0 -125
- data/lib/inventory_refresh/save_collection/saver/sql_helper_update.rb +5 -9
- data/lib/inventory_refresh/save_collection/saver/sql_helper_upsert.rb +9 -17
- data/lib/inventory_refresh/save_collection/sweeper.rb +91 -18
- data/lib/inventory_refresh/save_collection/topological_sort.rb +5 -5
- data/lib/inventory_refresh/save_inventory.rb +12 -5
- data/lib/inventory_refresh/version.rb +1 -1
- metadata +9 -45
- data/lib/inventory_refresh/save_collection/saver/batch.rb +0 -17
- data/lib/inventory_refresh/save_collection/saver/default.rb +0 -57
- data/lib/inventory_refresh/target.rb +0 -73
- data/lib/inventory_refresh/target_collection.rb +0 -92
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 666554cf2d3928670cd6772706360d2c2523fc0475b63f2aead1e7e2bec675d7
         | 
| 4 | 
            +
              data.tar.gz: 992aa863fdd2d020878f3bd18e0c83d7bf37aa79d6363814e10fdc5cd311a35a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1ce760c31989eaa2ec3d230031c176007953b9d5790d7d5e0c85d7b62e43f6d7d45cbe88651a70df3ca77c11f4d7b5587348e2ba0d951add5d8d76a90ba9d0e0
         | 
| 7 | 
            +
              data.tar.gz: 4084a11ccd8ab92142e44399159290d5b14be05aa111f5c681571c6ba034a4ecb55587f0d3c2dda9d0ef765e4c5aefa9f2ea9e4183c27b81d4547b3719ae8393
         | 
    
        data/.codeclimate.yml
    CHANGED
    
    
    
        data/.travis.yml
    CHANGED
    
    | @@ -1,12 +1,12 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            dist: xenial
         | 
| 2 2 | 
             
            sudo: false
         | 
| 3 3 | 
             
            language: ruby
         | 
| 4 4 | 
             
            cache: bundler
         | 
| 5 5 | 
             
            rvm:
         | 
| 6 | 
            -
            - 2. | 
| 7 | 
            -
            - 2.6 | 
| 6 | 
            +
            - 2.4.4
         | 
| 7 | 
            +
            - 2.3.6
         | 
| 8 8 | 
             
            addons:
         | 
| 9 | 
            -
              postgresql: ' | 
| 9 | 
            +
              postgresql: '10'
         | 
| 10 10 | 
             
            env:
         | 
| 11 11 | 
             
              global:
         | 
| 12 12 | 
             
              - CC_TEST_REPORTER_ID=1ef1a3a3d007395b11083d634a6fdac1e3d979b6428c39d2cd8d58556cdd68f7
         | 
| @@ -14,12 +14,10 @@ before_install: | |
| 14 14 | 
             
            - gem install bundler -v 2.0.1
         | 
| 15 15 | 
             
            - psql -c "CREATE USER root SUPERUSER PASSWORD 'smartvm';" -U postgres
         | 
| 16 16 | 
             
            before_script:
         | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 17 | 
            +
            - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
         | 
| 18 | 
            +
              > ./cc-test-reporter
         | 
| 19 19 | 
             
            - chmod +x ./cc-test-reporter
         | 
| 20 20 | 
             
            - "./cc-test-reporter before-build"
         | 
| 21 | 
            -
            # inventory_refresh
         | 
| 22 21 | 
             
            - bundle exec rake spec:setup
         | 
| 23 22 | 
             
            after_script:
         | 
| 24 | 
            -
            # Code Climate
         | 
| 25 23 | 
             
            - "./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
         | 
    
        data/inventory_refresh.gemspec
    CHANGED
    
    | @@ -23,15 +23,13 @@ Gem::Specification.new do |spec| | |
| 23 23 | 
             
              spec.require_paths = ["lib"]
         | 
| 24 24 |  | 
| 25 25 | 
             
              spec.add_dependency "activerecord", "~> 5.0"
         | 
| 26 | 
            -
              spec.add_dependency "more_core_extensions", " | 
| 26 | 
            +
              spec.add_dependency "more_core_extensions", "~> 3.5"
         | 
| 27 27 | 
             
              spec.add_dependency "pg", "> 0"
         | 
| 28 28 |  | 
| 29 29 | 
             
              spec.add_development_dependency "ancestry"
         | 
| 30 | 
            -
              spec.add_development_dependency "bundler", "~> 2.0"
         | 
| 30 | 
            +
              spec.add_development_dependency "bundler", "~> 2.0.1"
         | 
| 31 31 | 
             
              spec.add_development_dependency "factory_bot", "~> 4.11.1"
         | 
| 32 32 | 
             
              spec.add_development_dependency "rake", "~> 10.0"
         | 
| 33 33 | 
             
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 34 | 
            -
              spec.add_development_dependency "rubocop"
         | 
| 35 | 
            -
              spec.add_development_dependency "rubocop-performance"
         | 
| 36 34 | 
             
              spec.add_development_dependency "simplecov"
         | 
| 37 35 | 
             
            end
         | 
    
        data/lib/inventory_refresh.rb
    CHANGED
    
    | @@ -6,6 +6,4 @@ require "inventory_refresh/logging" | |
| 6 6 | 
             
            require "inventory_refresh/null_logger"
         | 
| 7 7 | 
             
            require "inventory_refresh/persister"
         | 
| 8 8 | 
             
            require "inventory_refresh/save_inventory"
         | 
| 9 | 
            -
            require "inventory_refresh/target"
         | 
| 10 | 
            -
            require "inventory_refresh/target_collection"
         | 
| 11 9 | 
             
            require "inventory_refresh/version"
         | 
| @@ -1,20 +1,12 @@ | |
| 1 1 | 
             
            module InventoryRefresh
         | 
| 2 2 | 
             
              class ApplicationRecordIterator
         | 
| 3 | 
            -
                attr_reader :inventory_collection | 
| 3 | 
            +
                attr_reader :inventory_collection
         | 
| 4 4 |  | 
| 5 | 
            -
                # An iterator that can fetch batches of the AR objects based on a set of  | 
| 6 | 
            -
                # when given an iterator. Or given query, acts as iterator by selecting batches.
         | 
| 5 | 
            +
                # An iterator that can fetch batches of the AR objects based on a set of attribute_indexes
         | 
| 7 6 | 
             
                #
         | 
| 8 7 | 
             
                # @param inventory_collection [InventoryRefresh::InventoryCollection] Inventory collection owning the iterator
         | 
| 9 | 
            -
                 | 
| 10 | 
            -
                #        fetch from the DB
         | 
| 11 | 
            -
                # @param iterator [Proc] Block based iterator
         | 
| 12 | 
            -
                # @query query [ActiveRecord::Relation] Existing query we want to use for querying the db
         | 
| 13 | 
            -
                def initialize(inventory_collection: nil, manager_uuids_set: nil, iterator: nil, query: nil)
         | 
| 8 | 
            +
                def initialize(inventory_collection: nil)
         | 
| 14 9 | 
             
                  @inventory_collection = inventory_collection
         | 
| 15 | 
            -
                  @manager_uuids_set    = manager_uuids_set
         | 
| 16 | 
            -
                  @iterator             = iterator
         | 
| 17 | 
            -
                  @query                = query
         | 
| 18 10 | 
             
                end
         | 
| 19 11 |  | 
| 20 12 | 
             
                # Iterator that mimics find_in_batches of ActiveRecord::Relation. This iterator serves for making more optimized query
         | 
| @@ -25,28 +17,19 @@ module InventoryRefresh | |
| 25 17 | 
             
                # and relation.where(:id => 500ids)
         | 
| 26 18 | 
             
                #
         | 
| 27 19 | 
             
                # @param batch_size [Integer] A batch size we want to fetch from DB
         | 
| 20 | 
            +
                # @param attributes_index [Hash{String => Hash}] Indexed hash with data we will be saving
         | 
| 28 21 | 
             
                # @yield Code processing the batches
         | 
| 29 | 
            -
                def find_in_batches(batch_size: 1000)
         | 
| 30 | 
            -
                   | 
| 31 | 
            -
                     | 
| 32 | 
            -
                      yield(batch)
         | 
| 33 | 
            -
                    end
         | 
| 34 | 
            -
                  elsif query
         | 
| 35 | 
            -
                    manager_uuids_set.each_slice(batch_size) do |batch|
         | 
| 36 | 
            -
                      yield(query.where(inventory_collection.targeted_selection_for(batch)))
         | 
| 37 | 
            -
                    end
         | 
| 38 | 
            -
                  else
         | 
| 39 | 
            -
                    manager_uuids_set.each_slice(batch_size) do |batch|
         | 
| 40 | 
            -
                      yield(inventory_collection.db_collection_for_comparison_for(batch))
         | 
| 41 | 
            -
                    end
         | 
| 22 | 
            +
                def find_in_batches(batch_size: 1000, attributes_index: {})
         | 
| 23 | 
            +
                  attributes_index.each_slice(batch_size) do |batch|
         | 
| 24 | 
            +
                    yield(inventory_collection.db_collection_for_comparison_for(batch))
         | 
| 42 25 | 
             
                  end
         | 
| 43 26 | 
             
                end
         | 
| 44 27 |  | 
| 45 28 | 
             
                # Iterator that mimics find_each of ActiveRecord::Relation using find_in_batches (see #find_in_batches)
         | 
| 46 29 | 
             
                #
         | 
| 47 30 | 
             
                # @yield Code processing the batches
         | 
| 48 | 
            -
                def find_each
         | 
| 49 | 
            -
                  find_in_batches do |batch|
         | 
| 31 | 
            +
                def find_each(attributes_index: {})
         | 
| 32 | 
            +
                  find_in_batches(:attributes_index => attributes_index) do |batch|
         | 
| 50 33 | 
             
                    batch.each do |item|
         | 
| 51 34 | 
             
                      yield(item)
         | 
| 52 35 | 
             
                    end
         | 
| @@ -0,0 +1,8 @@ | |
| 1 | 
            +
            module InventoryRefresh
         | 
| 2 | 
            +
              module Exception
         | 
| 3 | 
            +
                class SweeperError < StandardError; end
         | 
| 4 | 
            +
                class SweeperNonExistentScopeKeyFoundError < SweeperError; end
         | 
| 5 | 
            +
                class SweeperNonUniformScopeKeyFoundError < SweeperError; end
         | 
| 6 | 
            +
                class SweeperScopeBadFormat < SweeperError; end
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
            end
         | 
| @@ -71,32 +71,14 @@ module InventoryRefresh | |
| 71 71 | 
             
                #   InventoryCollection, since it is already persisted into the DB.
         | 
| 72 72 | 
             
                attr_accessor :saved
         | 
| 73 73 |  | 
| 74 | 
            -
                # If present, InventoryCollection switches into delete_complement mode, where it will
         | 
| 75 | 
            -
                # delete every record from the DB, that is not present in this list. This is used for the batch processing,
         | 
| 76 | 
            -
                # where we don't know which InventoryObject should be deleted, but we know all manager_uuids of all
         | 
| 77 | 
            -
                # InventoryObject objects that exists in the provider.
         | 
| 78 | 
            -
                #
         | 
| 79 | 
            -
                # @return [Array, nil] nil or a list of all :manager_uuids that are present in the Provider's InventoryCollection.
         | 
| 80 | 
            -
                attr_accessor :all_manager_uuids
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                # @return [Array, nil] Scope for applying :all_manager_uuids
         | 
| 83 | 
            -
                attr_accessor :all_manager_uuids_scope
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                # @return [String] Timestamp in UTC before fetching :all_manager_uuids
         | 
| 86 | 
            -
                attr_accessor :all_manager_uuids_timestamp
         | 
| 87 | 
            -
             | 
| 88 74 | 
             
                # @return [Set] A set of InventoryCollection objects that depends on this InventoryCollection object.
         | 
| 89 75 | 
             
                attr_accessor :dependees
         | 
| 90 76 |  | 
| 91 | 
            -
                # @return [Array<Symbol>] @see #parent_inventory_collections documentation of InventoryCollection.new's initialize_ic_relations()
         | 
| 92 | 
            -
                #   parameters
         | 
| 93 | 
            -
                attr_accessor :parent_inventory_collections
         | 
| 94 | 
            -
             | 
| 95 77 | 
             
                attr_reader :model_class, :strategy, :attributes_blacklist, :attributes_whitelist, :custom_save_block, :parent,
         | 
| 96 | 
            -
                            :internal_attributes, : | 
| 78 | 
            +
                            :internal_attributes, :dependency_attributes, :manager_ref, :secondary_refs, :create_only,
         | 
| 97 79 | 
             
                            :association, :complete, :update_only, :transitive_dependency_attributes, :check_changed, :arel,
         | 
| 98 | 
            -
                            :inventory_object_attributes, :name, :saver_strategy, : | 
| 99 | 
            -
                            : | 
| 80 | 
            +
                            :inventory_object_attributes, :name, :saver_strategy, :default_values,
         | 
| 81 | 
            +
                            :manager_ref_allowed_nil, :use_ar_object,
         | 
| 100 82 | 
             
                            :created_records, :updated_records, :deleted_records, :retention_strategy,
         | 
| 101 83 | 
             
                            :custom_reconnect_block, :batch_extra_attributes, :references_storage, :unconnected_edges,
         | 
| 102 84 | 
             
                            :assert_graph_integrity
         | 
| @@ -130,7 +112,6 @@ module InventoryRefresh | |
| 130 112 | 
             
                         :lazy_find_by,
         | 
| 131 113 | 
             
                         :named_ref,
         | 
| 132 114 | 
             
                         :primary_index,
         | 
| 133 | 
            -
                         :reindex_secondary_indexes!,
         | 
| 134 115 | 
             
                         :skeletal_primary_index,
         | 
| 135 116 | 
             
                         :to => :index_proxy
         | 
| 136 117 |  | 
| @@ -153,28 +134,18 @@ module InventoryRefresh | |
| 153 134 | 
             
                             properties[:check_changed],
         | 
| 154 135 | 
             
                             properties[:update_only],
         | 
| 155 136 | 
             
                             properties[:use_ar_object],
         | 
| 156 | 
            -
                             properties[:targeted],
         | 
| 157 137 | 
             
                             properties[:assert_graph_integrity])
         | 
| 158 138 |  | 
| 159 139 | 
             
                  init_strategies(properties[:strategy],
         | 
| 160 | 
            -
                                  properties[: | 
| 161 | 
            -
                                  properties[:retention_strategy],
         | 
| 162 | 
            -
                                  properties[:delete_method])
         | 
| 140 | 
            +
                                  properties[:retention_strategy])
         | 
| 163 141 |  | 
| 164 142 | 
             
                  init_references(properties[:manager_ref],
         | 
| 165 143 | 
             
                                  properties[:manager_ref_allowed_nil],
         | 
| 166 | 
            -
                                  properties[:secondary_refs] | 
| 167 | 
            -
                                  properties[:manager_uuids])
         | 
| 144 | 
            +
                                  properties[:secondary_refs])
         | 
| 168 145 |  | 
| 169 | 
            -
                   | 
| 170 | 
            -
                                         properties[:all_manager_uuids_scope],
         | 
| 171 | 
            -
                                         properties[:all_manager_uuids_timestamp])
         | 
| 146 | 
            +
                  init_ic_relations(properties[:dependency_attributes])
         | 
| 172 147 |  | 
| 173 | 
            -
                   | 
| 174 | 
            -
                                    properties[:parent_inventory_collections])
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                  init_arels(properties[:arel],
         | 
| 177 | 
            -
                             properties[:targeted_arel])
         | 
| 148 | 
            +
                  init_arels(properties[:arel])
         | 
| 178 149 |  | 
| 179 150 | 
             
                  init_custom_procs(properties[:custom_save_block],
         | 
| 180 151 | 
             
                                    properties[:custom_reconnect_block])
         | 
| @@ -311,6 +282,11 @@ module InventoryRefresh | |
| 311 282 | 
             
                  @base_columns ||= (unique_index_columns + internal_columns + not_null_columns).uniq
         | 
| 312 283 | 
             
                end
         | 
| 313 284 |  | 
| 285 | 
            +
                # @return [Array<Symbol>] Array of all column names on the InventoryCollection
         | 
| 286 | 
            +
                def all_column_names
         | 
| 287 | 
            +
                  @all_column_names ||= model_class.columns.map { |x| x.name.to_sym }
         | 
| 288 | 
            +
                end
         | 
| 289 | 
            +
             | 
| 314 290 | 
             
                # @param value [Object] Object we want to test
         | 
| 315 291 | 
             
                # @return [Boolean] true is value is kind of InventoryRefresh::InventoryObject
         | 
| 316 292 | 
             
                def inventory_object?(value)
         | 
| @@ -335,7 +311,7 @@ module InventoryRefresh | |
| 335 311 |  | 
| 336 312 | 
             
                # Convert manager_ref list of attributes to list of DB columns
         | 
| 337 313 | 
             
                #
         | 
| 338 | 
            -
                # @return [Array<String>]  | 
| 314 | 
            +
                # @return [Array<String>] Converted manager_ref list of attributes to list of DB columns
         | 
| 339 315 | 
             
                def manager_ref_to_cols
         | 
| 340 316 | 
             
                  # TODO(lsmola) this should contain the polymorphic _type, otherwise the IC with polymorphic unique key will get
         | 
| 341 317 | 
             
                  # conflicts
         | 
| @@ -434,7 +410,6 @@ module InventoryRefresh | |
| 434 410 | 
             
                                          :parent                => parent,
         | 
| 435 411 | 
             
                                          :arel                  => arel,
         | 
| 436 412 | 
             
                                          :strategy              => strategy,
         | 
| 437 | 
            -
                                          :saver_strategy        => saver_strategy,
         | 
| 438 413 | 
             
                                          :custom_save_block     => custom_save_block,
         | 
| 439 414 | 
             
                                          # We want cloned IC to be update only, since this is used for cycle resolution
         | 
| 440 415 | 
             
                                          :update_only           => true,
         | 
| @@ -472,78 +447,31 @@ module InventoryRefresh | |
| 472 447 |  | 
| 473 448 | 
             
                # @return [Integer] default batch size for talking to the DB
         | 
| 474 449 | 
             
                def batch_size
         | 
| 475 | 
            -
                  # TODO(lsmola) mode to the settings
         | 
| 476 450 | 
             
                  1000
         | 
| 477 451 | 
             
                end
         | 
| 478 452 |  | 
| 479 453 | 
             
                # @return [Integer] default batch size for talking to the DB if not using ApplicationRecord objects
         | 
| 480 454 | 
             
                def batch_size_pure_sql
         | 
| 481 | 
            -
                  # TODO(lsmola) mode to the settings
         | 
| 482 455 | 
             
                  10_000
         | 
| 483 456 | 
             
                end
         | 
| 484 457 |  | 
| 485 | 
            -
                # Returns a list of stringified uuids of all scoped InventoryObjects, which is used for scoping in targeted mode
         | 
| 486 | 
            -
                #
         | 
| 487 | 
            -
                # @return [Array<String>] list of stringified uuids of all scoped InventoryObjects
         | 
| 488 | 
            -
                def manager_uuids
         | 
| 489 | 
            -
                  # TODO(lsmola) LEGACY: this is still being used by :targetel_arel definitions and it expects array of strings
         | 
| 490 | 
            -
                  raise "This works only for :manager_ref size 1" if manager_ref.size > 1
         | 
| 491 | 
            -
                  key = manager_ref.first
         | 
| 492 | 
            -
                  transform_references_to_hashes(targeted_scope.primary_references).map { |x| x[key] }
         | 
| 493 | 
            -
                end
         | 
| 494 | 
            -
             | 
| 495 458 | 
             
                # Builds a multiselection conditions like (table1.a = a1 AND table2.b = b1) OR (table1.a = a2 AND table2.b = b2)
         | 
| 496 459 | 
             
                #
         | 
| 497 460 | 
             
                # @param hashes [Array<Hash>] data we want to use for the query
         | 
| 498 461 | 
             
                # @param keys [Array<Symbol>] keys of attributes involved
         | 
| 499 462 | 
             
                # @return [String] A condition usable in .where of an ActiveRecord relation
         | 
| 500 | 
            -
                def build_multi_selection_condition(hashes, keys =  | 
| 463 | 
            +
                def build_multi_selection_condition(hashes, keys = unique_index_keys)
         | 
| 501 464 | 
             
                  arel_table = model_class.arel_table
         | 
| 502 465 | 
             
                  # We do pure SQL OR, since Arel is nesting every .or into another parentheses, otherwise this would be just
         | 
| 503 466 | 
             
                  # inject(:or) instead of to_sql with .join(" OR ")
         | 
| 504 467 | 
             
                  hashes.map { |hash| "(#{keys.map { |key| arel_table[key].eq(hash[key]) }.inject(:and).to_sql})" }.join(" OR ")
         | 
| 505 468 | 
             
                end
         | 
| 506 469 |  | 
| 507 | 
            -
                #  | 
| 508 | 
            -
                def db_collection_for_comparison
         | 
| 509 | 
            -
                  if targeted?
         | 
| 510 | 
            -
                    if targeted_arel.respond_to?(:call)
         | 
| 511 | 
            -
                      targeted_arel.call(self)
         | 
| 512 | 
            -
                    elsif parent_inventory_collections.present?
         | 
| 513 | 
            -
                      targeted_arel_default
         | 
| 514 | 
            -
                    else
         | 
| 515 | 
            -
                      targeted_iterator_for(targeted_scope.primary_references)
         | 
| 516 | 
            -
                    end
         | 
| 517 | 
            -
                  else
         | 
| 518 | 
            -
                    full_collection_for_comparison
         | 
| 519 | 
            -
                  end
         | 
| 520 | 
            -
                end
         | 
| 521 | 
            -
             | 
| 522 | 
            -
                # Builds targeted query limiting the results by the :references defined in parent_inventory_collections
         | 
| 523 | 
            -
                #
         | 
| 524 | 
            -
                # @return [InventoryRefresh::ApplicationRecordIterator] an iterator for default targeted arel
         | 
| 525 | 
            -
                def targeted_arel_default
         | 
| 526 | 
            -
                  if parent_inventory_collections.collect { |x| x.model_class.base_class }.uniq.count > 1
         | 
| 527 | 
            -
                    raise "Multiple :parent_inventory_collections with different base class are not supported by default. Write "\
         | 
| 528 | 
            -
                          ":targeted_arel manually, or separate [#{self}] into 2 InventoryCollection objects."
         | 
| 529 | 
            -
                  end
         | 
| 530 | 
            -
                  parent_collection = parent_inventory_collections.first
         | 
| 531 | 
            -
                  references        = parent_inventory_collections.map { |x| x.targeted_scope.primary_references }.reduce({}, :merge!)
         | 
| 532 | 
            -
             | 
| 533 | 
            -
                  parent_collection.targeted_iterator_for(references, full_collection_for_comparison)
         | 
| 534 | 
            -
                end
         | 
| 535 | 
            -
             | 
| 536 | 
            -
                # Gets targeted references and transforms them into list of hashes
         | 
| 470 | 
            +
                # Returns iterator for the passed references and a query
         | 
| 537 471 | 
             
                #
         | 
| 538 | 
            -
                # @ | 
| 539 | 
            -
                 | 
| 540 | 
            -
             | 
| 541 | 
            -
                  if references.kind_of?(Array)
         | 
| 542 | 
            -
                    # Sliced InventoryRefresh::InventoryCollection::TargetedScope
         | 
| 543 | 
            -
                    references.map { |x| x.second.full_reference }
         | 
| 544 | 
            -
                  else
         | 
| 545 | 
            -
                    references.values.map(&:full_reference)
         | 
| 546 | 
            -
                  end
         | 
| 472 | 
            +
                # @return [InventoryRefresh::ApplicationRecordIterator] Iterator for the references and query
         | 
| 473 | 
            +
                def db_collection_for_comparison
         | 
| 474 | 
            +
                  InventoryRefresh::ApplicationRecordIterator.new(:inventory_collection => self)
         | 
| 547 475 | 
             
                end
         | 
| 548 476 |  | 
| 549 477 | 
             
                # Builds a multiselection conditions like (table1.a = a1 AND table2.b = b1) OR (table1.a = a2 AND table2.b = b2)
         | 
| @@ -552,20 +480,20 @@ module InventoryRefresh | |
| 552 480 | 
             
                # @param references [Hash{String => InventoryRefresh::InventoryCollection::Reference}] passed references
         | 
| 553 481 | 
             
                # @return [String] A condition usable in .where of an ActiveRecord relation
         | 
| 554 482 | 
             
                def targeted_selection_for(references)
         | 
| 555 | 
            -
                  build_multi_selection_condition( | 
| 483 | 
            +
                  build_multi_selection_condition(references.map(&:second))
         | 
| 556 484 | 
             
                end
         | 
| 557 485 |  | 
| 558 | 
            -
                 | 
| 559 | 
            -
             | 
| 560 | 
            -
                 | 
| 561 | 
            -
             | 
| 562 | 
            -
                # @return [ | 
| 563 | 
            -
                def  | 
| 564 | 
            -
                   | 
| 565 | 
            -
             | 
| 566 | 
            -
             | 
| 567 | 
            -
             | 
| 568 | 
            -
                   | 
| 486 | 
            +
                def select_keys
         | 
| 487 | 
            +
                  @select_keys ||= [@model_class.primary_key] + manager_ref_to_cols.map(&:to_s) + internal_columns.map(&:to_s)
         | 
| 488 | 
            +
                end
         | 
| 489 | 
            +
             | 
| 490 | 
            +
                # @return [ActiveRecord::ConnectionAdapters::AbstractAdapter] ActiveRecord connection
         | 
| 491 | 
            +
                def get_connection
         | 
| 492 | 
            +
                  ActiveRecord::Base.connection
         | 
| 493 | 
            +
                end
         | 
| 494 | 
            +
             | 
| 495 | 
            +
                def pure_sql_record_fetching?
         | 
| 496 | 
            +
                  !use_ar_object?
         | 
| 569 497 | 
             
                end
         | 
| 570 498 |  | 
| 571 499 | 
             
                # Builds an ActiveRecord::Relation that can fetch all the references from the DB
         | 
| @@ -573,14 +501,18 @@ module InventoryRefresh | |
| 573 501 | 
             
                # @param references [Hash{String => InventoryRefresh::InventoryCollection::Reference}] passed references
         | 
| 574 502 | 
             
                # @return [ActiveRecord::Relation] relation that can fetch all the references from the DB
         | 
| 575 503 | 
             
                def db_collection_for_comparison_for(references)
         | 
| 576 | 
            -
                  full_collection_for_comparison.where(targeted_selection_for(references))
         | 
| 504 | 
            +
                  query = full_collection_for_comparison.where(targeted_selection_for(references))
         | 
| 505 | 
            +
                  if pure_sql_record_fetching?
         | 
| 506 | 
            +
                    return get_connection.query(query.select(*select_keys).to_sql)
         | 
| 507 | 
            +
                  end
         | 
| 508 | 
            +
             | 
| 509 | 
            +
                  query
         | 
| 577 510 | 
             
                end
         | 
| 578 511 |  | 
| 579 512 | 
             
                # @return [ActiveRecord::Relation] relation that can fetch all the references from the DB
         | 
| 580 513 | 
             
                def full_collection_for_comparison
         | 
| 581 514 | 
             
                  return arel unless arel.nil?
         | 
| 582 515 | 
             
                  rel = parent.send(association)
         | 
| 583 | 
            -
                  rel = rel.active if rel && supports_column?(:archived_at) && retention_strategy == :archive
         | 
| 584 516 | 
             
                  rel
         | 
| 585 517 | 
             
                end
         | 
| 586 518 |  | 
| @@ -634,11 +566,5 @@ module InventoryRefresh | |
| 634 566 | 
             
                    :id => identity
         | 
| 635 567 | 
             
                  }
         | 
| 636 568 | 
             
                end
         | 
| 637 | 
            -
             | 
| 638 | 
            -
                # TODO: Not used!
         | 
| 639 | 
            -
                # @return [Array<Symbol>] all association attributes and foreign keys of the model class
         | 
| 640 | 
            -
                def association_attributes
         | 
| 641 | 
            -
                  model_class.reflect_on_all_associations.map { |x| [x.name, x.foreign_key] }.flatten.compact.map(&:to_sym)
         | 
| 642 | 
            -
                end
         | 
| 643 569 | 
             
              end
         | 
| 644 570 | 
             
            end
         | 
| @@ -4,16 +4,16 @@ module InventoryRefresh | |
| 4 4 | 
             
                  class MissingModelClassError < StandardError; end
         | 
| 5 5 |  | 
| 6 6 | 
             
                  def self.allowed_properties
         | 
| 7 | 
            -
                    %i( | 
| 7 | 
            +
                    %i(arel                         association
         | 
| 8 8 | 
             
                       attributes_blacklist         attributes_whitelist    batch_extra_attributes
         | 
| 9 9 | 
             
                       complete                     create_only             custom_save_block
         | 
| 10 | 
            -
                       custom_reconnect_block       default_values | 
| 10 | 
            +
                       custom_reconnect_block       default_values
         | 
| 11 11 | 
             
                       dependency_attributes        check_changed           inventory_object_attributes
         | 
| 12 | 
            -
                       manager_ref                  manager_ref_allowed_nil | 
| 12 | 
            +
                       manager_ref                  manager_ref_allowed_nil
         | 
| 13 13 | 
             
                       model_class                  name                    parent
         | 
| 14 | 
            -
                        | 
| 15 | 
            -
                        | 
| 16 | 
            -
                        | 
| 14 | 
            +
                       retention_strategy           strategy
         | 
| 15 | 
            +
                       secondary_refs
         | 
| 16 | 
            +
                       update_only                  use_ar_object
         | 
| 17 17 | 
             
                       assert_graph_integrity).to_set
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| @@ -70,15 +70,6 @@ module InventoryRefresh | |
| 70 70 | 
             
                    build(hash)
         | 
| 71 71 | 
             
                  end
         | 
| 72 72 |  | 
| 73 | 
            -
                  # Finds InventoryObject.
         | 
| 74 | 
            -
                  #
         | 
| 75 | 
            -
                  # @param hash [Hash] Hash that needs to contain attributes defined in :manager_ref of the InventoryCollection
         | 
| 76 | 
            -
                  # @return [InventoryRefresh::InventoryObject] Found or built InventoryObject object
         | 
| 77 | 
            -
                  def find_in_data(hash)
         | 
| 78 | 
            -
                    _hash, _uuid, inventory_object = primary_index_scan(hash)
         | 
| 79 | 
            -
                    inventory_object
         | 
| 80 | 
            -
                  end
         | 
| 81 | 
            -
             | 
| 82 73 | 
             
                  # Finds of builds a new InventoryObject. By building it, we also put in into the InventoryCollection's storage.
         | 
| 83 74 | 
             
                  #
         | 
| 84 75 | 
             
                  # @param hash [Hash] Hash that needs to contain attributes defined in :manager_ref of the
         | 
| @@ -35,26 +35,14 @@ module InventoryRefresh | |
| 35 35 | 
             
                    #         - :local_db_find_missing_references => InventoryObject objects of the InventoryCollection will be saved to
         | 
| 36 36 | 
             
                    #                                                the DB. Then if we reference an object that is not present, it will
         | 
| 37 37 | 
             
                    #                                                load them from the db using :local_db_find_references strategy.
         | 
| 38 | 
            -
                    # @param saver_strategy [Symbol] A strategy that will be used for InventoryCollection persisting into the DB.
         | 
| 39 | 
            -
                    #        Allowed saver strategies are:
         | 
| 40 | 
            -
                    #        - :default => Using Rails saving methods, this way is not safe to run in multiple workers concurrently,
         | 
| 41 | 
            -
                    #          since it will lead to non consistent data.
         | 
| 42 | 
            -
                    #        - :batch => Using batch SQL queries, this way is not safe to run in multiple workers
         | 
| 43 | 
            -
                    #          concurrently, since it will lead to non consistent data.
         | 
| 44 | 
            -
                    #        - :concurrent_safe_batch => It uses atomic upsert to avoid data duplication and it uses timestamp based
         | 
| 45 | 
            -
                    #          atomic checks to avoid new data being overwritten by the the old data. The upsert/update queries are
         | 
| 46 | 
            -
                    #          executed as batched SQL queries, instead of sending 1 query per record.
         | 
| 47 38 | 
             
                    # @param retention_strategy [Symbol] A retention strategy for this collection. Allowed values are:
         | 
| 48 39 | 
             
                    #        - :destroy => Will destroy the inactive records.
         | 
| 49 40 | 
             
                    #        - :archive => Will archive the inactive records by setting :archived_at timestamp.
         | 
| 50 | 
            -
                     | 
| 51 | 
            -
             | 
| 52 | 
            -
                    #        :model_class.
         | 
| 53 | 
            -
                    def init_strategies(strategy, saver_strategy, retention_strategy, delete_method)
         | 
| 54 | 
            -
                      @saver_strategy     = process_saver_strategy(saver_strategy)
         | 
| 41 | 
            +
                    def init_strategies(strategy, retention_strategy)
         | 
| 42 | 
            +
                      @saver_strategy     = :concurrent_safe_batch
         | 
| 55 43 | 
             
                      @strategy           = process_strategy(strategy)
         | 
| 44 | 
            +
                      # TODO(lsmola) why don't we just set this strategy based on :archived_at column? Lets do that
         | 
| 56 45 | 
             
                      @retention_strategy = process_retention_strategy(retention_strategy)
         | 
| 57 | 
            -
                      @delete_method      = delete_method || :destroy
         | 
| 58 46 | 
             
                    end
         | 
| 59 47 |  | 
| 60 48 | 
             
                    # @param manager_ref [Array] Array of Symbols, that are keys of the InventoryObject's data, inserted into this
         | 
| @@ -67,42 +55,10 @@ module InventoryRefresh | |
| 67 55 | 
             
                    #        avoid this usecase by a proper modeling.
         | 
| 68 56 | 
             
                    #        Note that InventoryObject's data has to be build with <foreign_key> => nil, it means that key cannot be missing!
         | 
| 69 57 | 
             
                    # @param secondary_refs [Hash] TODO
         | 
| 70 | 
            -
                     | 
| 71 | 
            -
                    #        this attribute, the db_collection_for_comparison will be automatically limited by the manager_uuids, in a
         | 
| 72 | 
            -
                    #        case of a simple relation. In a case of a complex relation, we can leverage :manager_uuids in a
         | 
| 73 | 
            -
                    #        custom :targeted_arel. We can pass also lambda, for lazy_evaluation.
         | 
| 74 | 
            -
                    def init_references(manager_ref, manager_ref_allowed_nil, secondary_refs,  manager_uuids)
         | 
| 58 | 
            +
                    def init_references(manager_ref, manager_ref_allowed_nil, secondary_refs)
         | 
| 75 59 | 
             
                      @manager_ref             = manager_ref || %i(ems_ref)
         | 
| 76 60 | 
             
                      @manager_ref_allowed_nil = manager_ref_allowed_nil || []
         | 
| 77 61 | 
             
                      @secondary_refs          = secondary_refs || {}
         | 
| 78 | 
            -
                      @manager_uuids           = manager_uuids || []
         | 
| 79 | 
            -
                    end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                    # @param all_manager_uuids [Array] Array of all manager_uuids of the InventoryObjects. With the :targeted true,
         | 
| 82 | 
            -
                    #        having this parameter defined will invoke only :delete_method on a complement of this set, making sure
         | 
| 83 | 
            -
                    #        the DB has only this set of data after. This :attribute serves for deleting of top level
         | 
| 84 | 
            -
                    #        InventoryCollections, i.e. InventoryCollections having parent_inventory_collections nil. The deleting of
         | 
| 85 | 
            -
                    #        child collections is already handled by the scope of the parent_inventory_collections and using Rails
         | 
| 86 | 
            -
                    #        :dependent => :destroy,
         | 
| 87 | 
            -
                    # @param all_manager_uuids_scope [Array] A scope limiting the :all_manager_uuids parameter. E.g. we can send
         | 
| 88 | 
            -
                    #        all_manager_uuids for 1 region, leading to delete a complement of the entities just under that 1
         | 
| 89 | 
            -
                    #        region.
         | 
| 90 | 
            -
                    #        If all_manager_uuids_scope is used with :all_manager_uuids => nil, it will do delete_complement of the
         | 
| 91 | 
            -
                    #        scope itself. E.g. sending a list of all active regions, we will delete complement entities not
         | 
| 92 | 
            -
                    #        belonging to those regions.
         | 
| 93 | 
            -
                    #        Example:
         | 
| 94 | 
            -
                    #          :all_manager_uuids       => [{:source_ref => x}, {:source_ref => y}],
         | 
| 95 | 
            -
                    #          :all_manager_uuids_scope => [{:region => regions.lazy_find(X)}, {:region => regions.lazy_find(Y)}]
         | 
| 96 | 
            -
                    #
         | 
| 97 | 
            -
                    #        Will cause deletion/archival or all entities that don't have source_ref "x" or "y", but only under
         | 
| 98 | 
            -
                    #        regions X and Y.
         | 
| 99 | 
            -
                    # @param all_manager_uuids_timestamp [String] A timestamp in UTC marking a time before we collected all of the
         | 
| 100 | 
            -
                    #        all_manager_uuids. Meaning we won't be archiving any newer entities.
         | 
| 101 | 
            -
                    def init_all_manager_uuids(all_manager_uuids, all_manager_uuids_scope, all_manager_uuids_timestamp)
         | 
| 102 | 
            -
                      # TODO(lsmola) Should we refactor this to use references too?
         | 
| 103 | 
            -
                      @all_manager_uuids           = all_manager_uuids
         | 
| 104 | 
            -
                      @all_manager_uuids_scope     = all_manager_uuids_scope
         | 
| 105 | 
            -
                      @all_manager_uuids_timestamp = all_manager_uuids_timestamp
         | 
| 106 62 | 
             
                    end
         | 
| 107 63 |  | 
| 108 64 | 
             
                    # @param dependency_attributes [Hash] Manually defined dependencies of this InventoryCollection. We can use this
         | 
| @@ -119,48 +75,9 @@ module InventoryRefresh | |
| 119 75 | 
             
                    #        This example is used in Example2 of the <param custom_save_block> and it means that our :custom_save_block
         | 
| 120 76 | 
             
                    #        will be invoked after the InventoryCollection :orchestration_stacks and :orchestration_stacks_resources
         | 
| 121 77 | 
             
                    #        are saved.
         | 
| 122 | 
            -
                     | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
                    #
         | 
| 126 | 
            -
                    #        Example:
         | 
| 127 | 
            -
                    #          taking inventory collections :vms and :disks (local disks), if we write that:
         | 
| 128 | 
            -
                    #          inventory_collection = InventoryCollection.new({
         | 
| 129 | 
            -
                    #                       :model_class                 => ::Disk,
         | 
| 130 | 
            -
                    #                       :association                 => :disks,
         | 
| 131 | 
            -
                    #                       :manager_ref                 => [:vm, :location]
         | 
| 132 | 
            -
                    #                       :parent_inventory_collection => [:vms],
         | 
| 133 | 
            -
                    #                     })
         | 
| 134 | 
            -
                    #
         | 
| 135 | 
            -
                    #          Then the decision for having :parent_inventory_collection => [:vms] was probably driven by these
         | 
| 136 | 
            -
                    #          points:
         | 
| 137 | 
            -
                    #          1. We can get list of all disks only by doing SQL query through the parent object (so there will be join
         | 
| 138 | 
            -
                    #             from vms to disks table).
         | 
| 139 | 
            -
                    #          2. There is no API query for getting all disks from the provider API, we get them inside VM data, or as
         | 
| 140 | 
            -
                    #             a Vm subquery
         | 
| 141 | 
            -
                    #          3. Part of the manager_ref of the IC is the VM object (foreign key), so the disk's location is unique
         | 
| 142 | 
            -
                    #             only under 1 Vm. (In current models, this modeled going through Hardware model)
         | 
| 143 | 
            -
                    #          4. In targeted refresh, we always expect that each Vm will be saved with all its disks.
         | 
| 144 | 
            -
                    #
         | 
| 145 | 
            -
                    #          Then having the above points, adding :parent_inventory_collection => [:vms], will bring these
         | 
| 146 | 
            -
                    #          implications:
         | 
| 147 | 
            -
                    #          1. By archiving/deleting Vm, we can no longer see the disk, because those were owned by the Vm. Any
         | 
| 148 | 
            -
                    #             archival/deletion of the Disk model, must be then done by cascade delete/hooks logic.
         | 
| 149 | 
            -
                    #          2. Having Vm as a parent ensures we always process it first. So e.g. when providing no Vms for saving
         | 
| 150 | 
            -
                    #             we would have no graph dependency (no data --> no edges --> no dependencies) and Disk could be
         | 
| 151 | 
            -
                    #             archived/removed before the Vm, while we always want to archive the VM first.
         | 
| 152 | 
            -
                    #          3. For targeted refresh, we always expect that all disks are saved with a VM. So for targeting :disks,
         | 
| 153 | 
            -
                    #             we are not using #manager_uuids attribute, since the scope is "all disks of all targeted VMs", so we
         | 
| 154 | 
            -
                    #             always use #manager_uuids of the parent. (that is why :parent_inventory_collections and
         | 
| 155 | 
            -
                    #             :manager_uuids are mutually exclusive attributes)
         | 
| 156 | 
            -
                    #          4. For automatically building the #targeted_arel query, we need the parent to know what is the root node.
         | 
| 157 | 
            -
                    #             While this information can be introspected from the data, it creates a scope for create&update&delete,
         | 
| 158 | 
            -
                    #             which means it has to work with no data provided (causing delete all). So with no data we cannot
         | 
| 159 | 
            -
                    #             introspect anything.
         | 
| 160 | 
            -
                    def init_ic_relations(dependency_attributes, parent_inventory_collections = nil)
         | 
| 161 | 
            -
                      @dependency_attributes        = dependency_attributes || {}
         | 
| 162 | 
            -
                      @dependees                    = Set.new
         | 
| 163 | 
            -
                      @parent_inventory_collections = parent_inventory_collections
         | 
| 78 | 
            +
                    def init_ic_relations(dependency_attributes)
         | 
| 79 | 
            +
                      @dependency_attributes = dependency_attributes || {}
         | 
| 80 | 
            +
                      @dependees             = Set.new
         | 
| 164 81 | 
             
                    end
         | 
| 165 82 |  | 
| 166 83 | 
             
                    # @param complete [Boolean] By default true, :complete is marking we are sending a complete dataset and therefore
         | 
| @@ -175,18 +92,13 @@ module InventoryRefresh | |
| 175 92 | 
             
                    # @param use_ar_object [Boolean] True or False. Whether we need to initialize AR object as part of the saving
         | 
| 176 93 | 
             
                    #        it's needed if the model have special setters, serialize of columns, etc. This setting is relevant only
         | 
| 177 94 | 
             
                    #        for the batch saver strategy.
         | 
| 178 | 
            -
                     | 
| 179 | 
            -
                    #        :parent_inventory_collections and :targeted_arel to save a subgraph of a data.
         | 
| 180 | 
            -
                    def init_flags(complete, create_only, check_changed,
         | 
| 181 | 
            -
                                   update_only, use_ar_object, targeted,
         | 
| 182 | 
            -
                                   assert_graph_integrity)
         | 
| 95 | 
            +
                    def init_flags(complete, create_only, check_changed, update_only, use_ar_object, assert_graph_integrity)
         | 
| 183 96 | 
             
                      @complete               = complete.nil? ? true : complete
         | 
| 184 97 | 
             
                      @create_only            = create_only.nil? ? false : create_only
         | 
| 185 98 | 
             
                      @check_changed          = check_changed.nil? ? true : check_changed
         | 
| 186 99 | 
             
                      @saved                  = false
         | 
| 187 100 | 
             
                      @update_only            = update_only.nil? ? false : update_only
         | 
| 188 101 | 
             
                      @use_ar_object          = use_ar_object || false
         | 
| 189 | 
            -
                      @targeted               = !!targeted
         | 
| 190 102 | 
             
                      @assert_graph_integrity = assert_graph_integrity.nil? ? true : assert_graph_integrity
         | 
| 191 103 | 
             
                    end
         | 
| 192 104 |  | 
| @@ -230,7 +142,7 @@ module InventoryRefresh | |
| 230 142 | 
             
                      @attributes_whitelist             = Set.new
         | 
| 231 143 | 
             
                      @batch_extra_attributes           = batch_extra_attributes || []
         | 
| 232 144 | 
             
                      @inventory_object_attributes      = inventory_object_attributes
         | 
| 233 | 
            -
                      @internal_attributes              = %i(__feedback_edge_set_parent | 
| 145 | 
            +
                      @internal_attributes              = %i(__feedback_edge_set_parent)
         | 
| 234 146 | 
             
                      @transitive_dependency_attributes = Set.new
         | 
| 235 147 |  | 
| 236 148 | 
             
                      blacklist_attributes!(attributes_blacklist) if attributes_blacklist.present?
         | 
| @@ -240,7 +152,6 @@ module InventoryRefresh | |
| 240 152 | 
             
                    def init_storages
         | 
| 241 153 | 
             
                      @data_storage       = ::InventoryRefresh::InventoryCollection::DataStorage.new(self, @secondary_refs)
         | 
| 242 154 | 
             
                      @references_storage = ::InventoryRefresh::InventoryCollection::ReferencesStorage.new(index_proxy)
         | 
| 243 | 
            -
                      @targeted_scope     = ::InventoryRefresh::InventoryCollection::ReferencesStorage.new(index_proxy).merge!(@manager_uuids)
         | 
| 244 155 | 
             
                    end
         | 
| 245 156 |  | 
| 246 157 | 
             
                    # @param arel [ActiveRecord::Associations::CollectionProxy|Arel::SelectManager] Instead of :parent and :association
         | 
| @@ -248,35 +159,18 @@ module InventoryRefresh | |
| 248 159 | 
             
                    #        doing create/update/delete.
         | 
| 249 160 | 
             
                    #
         | 
| 250 161 | 
             
                    #        Example:
         | 
| 251 | 
            -
                    # | 
| 252 | 
            -
                    # | 
| 253 | 
            -
                    # | 
| 254 | 
            -
                    # | 
| 255 | 
            -
                    # | 
| 256 | 
            -
                    # | 
| 257 | 
            -
                    # | 
| 258 | 
            -
                    # | 
| 259 | 
            -
                    # @param targeted_arel [Proc] A callable block that receives this InventoryCollection as a first argument. In there
         | 
| 260 | 
            -
                    #        we can leverage a :parent_inventory_collections or :manager_uuids to limit the query based on the
         | 
| 261 | 
            -
                    #        manager_uuids available.
         | 
| 262 | 
            -
                    #        Example:
         | 
| 263 | 
            -
                    #          targeted_arel = lambda do |inventory_collection|
         | 
| 264 | 
            -
                    #            # Getting ems_refs of parent :vms and :miq_templates
         | 
| 265 | 
            -
                    #            manager_uuids = inventory_collection.parent_inventory_collections.collect(&:manager_uuids).flatten
         | 
| 266 | 
            -
                    #            inventory_collection.db_collection_for_comparison.hardwares.joins(:vm_or_template).where(
         | 
| 267 | 
            -
                    #              'vms' => {:ems_ref => manager_uuids}
         | 
| 162 | 
            +
                    #          add_collection(:cross_link_vms) do |builder|
         | 
| 163 | 
            +
                    #            builder.add_properties(
         | 
| 164 | 
            +
                    #              :arel        => Vm.where(:tenant => manager.tenant),
         | 
| 165 | 
            +
                    #              :association => nil,
         | 
| 166 | 
            +
                    #              :model_class => Vm,
         | 
| 167 | 
            +
                    #              :name        => :cross_link_vms,
         | 
| 168 | 
            +
                    #              :manager_ref => [:uid_ems],
         | 
| 169 | 
            +
                    #              :strategy    => :local_db_find_references,
         | 
| 268 170 | 
             
                    #            )
         | 
| 269 171 | 
             
                    #          end
         | 
| 270 | 
            -
                     | 
| 271 | 
            -
             | 
| 272 | 
            -
                    #                                   :model_class                 => ::Hardware,
         | 
| 273 | 
            -
                    #                                   :association                 => :hardwares,
         | 
| 274 | 
            -
                    #                                   :parent_inventory_collection => [:vms, :miq_templates],
         | 
| 275 | 
            -
                    #                                   :targeted_arel               => targeted_arel,
         | 
| 276 | 
            -
                    #                                 })
         | 
| 277 | 
            -
                    def init_arels(arel, targeted_arel)
         | 
| 278 | 
            -
                      @arel                   = arel
         | 
| 279 | 
            -
                      @targeted_arel          = targeted_arel
         | 
| 172 | 
            +
                    def init_arels(arel)
         | 
| 173 | 
            +
                      @arel = arel
         | 
| 280 174 | 
             
                    end
         | 
| 281 175 |  | 
| 282 176 | 
             
                    # @param custom_save_block [Proc] A custom lambda/proc for persisting in the DB, for cases where it's not enough
         | 
| @@ -392,23 +286,6 @@ module InventoryRefresh | |
| 392 286 | 
             
                      @deleted_records = []
         | 
| 393 287 | 
             
                    end
         | 
| 394 288 |  | 
| 395 | 
            -
                    # Processes passed saver strategy
         | 
| 396 | 
            -
                    #
         | 
| 397 | 
            -
                    # @param saver_strategy [Symbol] Passed saver strategy
         | 
| 398 | 
            -
                    # @return [Symbol] Returns back the passed strategy if supported, or raises exception
         | 
| 399 | 
            -
                    def process_saver_strategy(saver_strategy)
         | 
| 400 | 
            -
                      return :default unless saver_strategy
         | 
| 401 | 
            -
             | 
| 402 | 
            -
                      saver_strategy = saver_strategy.to_sym
         | 
| 403 | 
            -
                      case saver_strategy
         | 
| 404 | 
            -
                      when :default, :batch, :concurrent_safe_batch
         | 
| 405 | 
            -
                        saver_strategy
         | 
| 406 | 
            -
                      else
         | 
| 407 | 
            -
                        raise "Unknown InventoryCollection saver strategy: :#{saver_strategy}, allowed strategies are "\
         | 
| 408 | 
            -
                          ":default, :batch and :concurrent_safe_batch"
         | 
| 409 | 
            -
                      end
         | 
| 410 | 
            -
                    end
         | 
| 411 | 
            -
             | 
| 412 289 | 
             
                    # Processes passed strategy, modifies :data_collection_finalized and :saved attributes for db only strategies
         | 
| 413 290 | 
             
                    #
         | 
| 414 291 | 
             
                    # @param strategy_name [Symbol] Passed saver strategy
         | 
| @@ -434,12 +311,26 @@ module InventoryRefresh | |
| 434 311 | 
             
                      strategy_name
         | 
| 435 312 | 
             
                    end
         | 
| 436 313 |  | 
| 314 | 
            +
                    # Saves passed strategy, modifies :data_collection_finalized and :saved attributes for db only strategies
         | 
| 315 | 
            +
                    #
         | 
| 316 | 
            +
                    # @param strategy [Symbol] Passed saver strategy
         | 
| 317 | 
            +
                    # @return [Symbol] Returns back the passed strategy if supported, or raises exception
         | 
| 318 | 
            +
                    def strategy=(strategy)
         | 
| 319 | 
            +
                      @strategy = process_strategy(strategy)
         | 
| 320 | 
            +
                    end
         | 
| 321 | 
            +
             | 
| 437 322 | 
             
                    # Processes passed retention strategy
         | 
| 438 323 | 
             
                    #
         | 
| 439 324 | 
             
                    # @param retention_strategy [Symbol] Passed retention strategy
         | 
| 440 325 | 
             
                    # @return [Symbol] Returns back the passed strategy if supported, or raises exception
         | 
| 441 326 | 
             
                    def process_retention_strategy(retention_strategy)
         | 
| 442 | 
            -
                       | 
| 327 | 
            +
                      unless retention_strategy
         | 
| 328 | 
            +
                        if supports_column?(:archived_at)
         | 
| 329 | 
            +
                          return :archive
         | 
| 330 | 
            +
                        else
         | 
| 331 | 
            +
                          return :destroy
         | 
| 332 | 
            +
                        end
         | 
| 333 | 
            +
                      end
         | 
| 443 334 |  | 
| 444 335 | 
             
                      retention_strategy = retention_strategy.to_sym
         | 
| 445 336 | 
             
                      case retention_strategy
         |