inventory_refresh 0.3.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.codeclimate.yml +25 -30
- data/.github/workflows/ci.yaml +58 -0
- data/.rubocop.yml +3 -3
- data/.rubocop_cc.yml +3 -4
- data/.rubocop_local.yml +5 -2
- data/.whitesource +3 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +10 -4
- data/README.md +1 -2
- data/Rakefile +2 -2
- data/inventory_refresh.gemspec +9 -10
- data/lib/inventory_refresh/application_record_iterator.rb +25 -12
- data/lib/inventory_refresh/graph/topological_sort.rb +24 -26
- data/lib/inventory_refresh/graph.rb +2 -2
- data/lib/inventory_refresh/inventory_collection/builder.rb +37 -15
- data/lib/inventory_refresh/inventory_collection/data_storage.rb +9 -0
- data/lib/inventory_refresh/inventory_collection/helpers/initialize_helper.rb +147 -38
- data/lib/inventory_refresh/inventory_collection/helpers/questions_helper.rb +48 -4
- data/lib/inventory_refresh/inventory_collection/index/proxy.rb +35 -3
- data/lib/inventory_refresh/inventory_collection/index/type/base.rb +8 -0
- data/lib/inventory_refresh/inventory_collection/index/type/local_db.rb +2 -0
- data/lib/inventory_refresh/inventory_collection/index/type/skeletal.rb +1 -0
- data/lib/inventory_refresh/inventory_collection/reference.rb +1 -0
- data/lib/inventory_refresh/inventory_collection/references_storage.rb +17 -0
- data/lib/inventory_refresh/inventory_collection/scanner.rb +91 -3
- data/lib/inventory_refresh/inventory_collection/serialization.rb +16 -10
- data/lib/inventory_refresh/inventory_collection.rb +122 -64
- data/lib/inventory_refresh/inventory_object.rb +74 -40
- data/lib/inventory_refresh/inventory_object_lazy.rb +17 -10
- data/lib/inventory_refresh/null_logger.rb +2 -2
- data/lib/inventory_refresh/persister.rb +43 -93
- data/lib/inventory_refresh/save_collection/base.rb +4 -2
- data/lib/inventory_refresh/save_collection/saver/base.rb +114 -15
- data/lib/inventory_refresh/save_collection/saver/batch.rb +17 -0
- data/lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb +129 -51
- data/lib/inventory_refresh/save_collection/saver/default.rb +57 -0
- data/lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb +2 -19
- data/lib/inventory_refresh/save_collection/saver/retention_helper.rb +68 -3
- data/lib/inventory_refresh/save_collection/saver/sql_helper.rb +125 -0
- data/lib/inventory_refresh/save_collection/saver/sql_helper_update.rb +10 -6
- data/lib/inventory_refresh/save_collection/saver/sql_helper_upsert.rb +28 -16
- data/lib/inventory_refresh/save_collection/sweeper.rb +17 -93
- data/lib/inventory_refresh/save_collection/topological_sort.rb +5 -5
- data/lib/inventory_refresh/save_inventory.rb +5 -12
- data/lib/inventory_refresh/target.rb +73 -0
- data/lib/inventory_refresh/target_collection.rb +92 -0
- data/lib/inventory_refresh/version.rb +1 -1
- data/lib/inventory_refresh.rb +2 -0
- metadata +42 -39
- data/.travis.yml +0 -23
- data/lib/inventory_refresh/exception.rb +0 -8
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b3393dbd829d48263fc51a06fa2c659045239142f4f325a2c894296eb640045d
         | 
| 4 | 
            +
              data.tar.gz: eea18674f3145f38ead40f221d62cb158e66174860509c4bc669713a1b7f2bb7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: eb24a4daf33a937c914536dd93ad192aaf5a81fb7528888b3d22f12a46c2180634efa7d992a2f810a5c0479f341991080e9d54e115e8e5e7c58b5cc80a917e47
         | 
| 7 | 
            +
              data.tar.gz: 9a0d525bd2df33aa7892d75968c95ac41afcd0a974f5376025e94f2d328097b652e93acc57bba43ed5451c26dd39f8180f6c9429d16ed49a4c09fdb50ada21b1
         | 
    
        data/.codeclimate.yml
    CHANGED
    
    | @@ -1,18 +1,21 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
            -  | 
| 4 | 
            -
             | 
| 5 | 
            -
            -  | 
| 6 | 
            -
             | 
| 7 | 
            -
            -  | 
| 8 | 
            -
             | 
| 9 | 
            -
            -  | 
| 10 | 
            -
             | 
| 1 | 
            +
            prepare:
         | 
| 2 | 
            +
              fetch:
         | 
| 3 | 
            +
              - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_base.yml
         | 
| 4 | 
            +
                path: ".rubocop_base.yml"
         | 
| 5 | 
            +
              - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_cc_base.yml
         | 
| 6 | 
            +
                path: ".rubocop_cc_base.yml"
         | 
| 7 | 
            +
              - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/base.yml
         | 
| 8 | 
            +
                path: styles/base.yml
         | 
| 9 | 
            +
              - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/cc_base.yml
         | 
| 10 | 
            +
                path: styles/cc_base.yml
         | 
| 11 | 
            +
            plugins:
         | 
| 12 | 
            +
              rubocop:
         | 
| 13 | 
            +
                enabled: true
         | 
| 14 | 
            +
                config: ".rubocop_cc.yml"
         | 
| 15 | 
            +
                channel: rubocop-0-82
         | 
| 11 16 | 
             
              brakeman:
         | 
| 12 | 
            -
                # very slow :sad_panda:
         | 
| 13 17 | 
             
                enabled: false
         | 
| 14 18 | 
             
              bundler-audit:
         | 
| 15 | 
            -
                # requires Gemfile.lock
         | 
| 16 19 | 
             
                enabled: false
         | 
| 17 20 | 
             
              csslint:
         | 
| 18 21 | 
             
                enabled: false
         | 
| @@ -24,25 +27,17 @@ engines: | |
| 24 27 | 
             
                  - javascript
         | 
| 25 28 | 
             
              eslint:
         | 
| 26 29 | 
             
                enabled: false
         | 
| 27 | 
            -
                channel:  | 
| 30 | 
            +
                channel: eslint-3
         | 
| 28 31 | 
             
              fixme:
         | 
| 29 | 
            -
                # let's enable later
         | 
| 30 32 | 
             
                enabled: false
         | 
| 31 33 | 
             
              markdownlint:
         | 
| 32 | 
            -
                # let's enable later
         | 
| 33 34 | 
             
                enabled: false
         | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                path: ".rubocop_cc_base.yml"
         | 
| 44 | 
            -
            ratings:
         | 
| 45 | 
            -
              paths:
         | 
| 46 | 
            -
              - Gemfile.lock
         | 
| 47 | 
            -
              - "**.rake"
         | 
| 48 | 
            -
              - "**.rb"
         | 
| 35 | 
            +
            exclude_patterns:
         | 
| 36 | 
            +
            - ".git/"
         | 
| 37 | 
            +
            - "**.xml"
         | 
| 38 | 
            +
            - "**.yaml"
         | 
| 39 | 
            +
            - "**.yml"
         | 
| 40 | 
            +
            - locale/
         | 
| 41 | 
            +
            - spec/
         | 
| 42 | 
            +
            - tools/
         | 
| 43 | 
            +
            version: '2'
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            name: CI
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            on:
         | 
| 4 | 
            +
              push:
         | 
| 5 | 
            +
              pull_request:
         | 
| 6 | 
            +
              schedule:
         | 
| 7 | 
            +
              - cron: '0 0 * * 0'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            jobs:
         | 
| 10 | 
            +
              ci:
         | 
| 11 | 
            +
                runs-on: ubuntu-latest
         | 
| 12 | 
            +
                strategy:
         | 
| 13 | 
            +
                  matrix:
         | 
| 14 | 
            +
                    ruby-version:
         | 
| 15 | 
            +
                    - '2.7'
         | 
| 16 | 
            +
                    - '3.0'
         | 
| 17 | 
            +
                    rails-version:
         | 
| 18 | 
            +
                    # rails 6.1 supports ruby >= 2.5
         | 
| 19 | 
            +
                    - '6.1'
         | 
| 20 | 
            +
                    include:
         | 
| 21 | 
            +
                    # rails 5.2 (EOL 6/22) supports ruby < 2.7 (2.6 EOL 3/22)
         | 
| 22 | 
            +
                    - ruby-version: '2.5'
         | 
| 23 | 
            +
                      rails-version: '5.2'
         | 
| 24 | 
            +
                    # rails 6.0 (security EOL 6/23?) supports ruby < 2.8 (2.7 EOL 3/23?;)
         | 
| 25 | 
            +
                    - ruby-version: '2.6'
         | 
| 26 | 
            +
                      rails-version: '6.0'
         | 
| 27 | 
            +
                    - ruby-version: '2.7'
         | 
| 28 | 
            +
                      rails-version: '6.0'
         | 
| 29 | 
            +
                services:
         | 
| 30 | 
            +
                  postgres:
         | 
| 31 | 
            +
                    image: manageiq/postgresql:10
         | 
| 32 | 
            +
                    env:
         | 
| 33 | 
            +
                      POSTGRESQL_USER: root
         | 
| 34 | 
            +
                      POSTGRESQL_PASSWORD: smartvm
         | 
| 35 | 
            +
                      POSTGRESQL_DATABASE: inventory_refresh_dummy_test
         | 
| 36 | 
            +
                    options: --health-cmd pg_isready --health-interval 2s --health-timeout 5s --health-retries 5
         | 
| 37 | 
            +
                    ports:
         | 
| 38 | 
            +
                    - 5432:5432
         | 
| 39 | 
            +
                env:
         | 
| 40 | 
            +
                  TEST_RAILS_VERSION: ${{ matrix.rails-version }}
         | 
| 41 | 
            +
                  PGHOST: localhost
         | 
| 42 | 
            +
                  PGPASSWORD: smartvm
         | 
| 43 | 
            +
                  CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
         | 
| 44 | 
            +
                steps:
         | 
| 45 | 
            +
                - uses: actions/checkout@v2
         | 
| 46 | 
            +
                - name: Set up Ruby
         | 
| 47 | 
            +
                  uses: ruby/setup-ruby@v1
         | 
| 48 | 
            +
                  with:
         | 
| 49 | 
            +
                    ruby-version: ${{ matrix.ruby-version }}
         | 
| 50 | 
            +
                    bundler-cache: true
         | 
| 51 | 
            +
                - name: Prepare tests
         | 
| 52 | 
            +
                  run: bundle exec rake spec:setup
         | 
| 53 | 
            +
                - name: Run tests
         | 
| 54 | 
            +
                  run: bundle exec rake
         | 
| 55 | 
            +
                - name: Report code coverage
         | 
| 56 | 
            +
                  if: ${{ github.ref == 'refs/heads/master' && matrix.ruby-version == '2.7' && matrix.rails-version == '6.1' }}
         | 
| 57 | 
            +
                  continue-on-error: true
         | 
| 58 | 
            +
                  uses: paambaati/codeclimate-action@v3.0.0
         | 
    
        data/.rubocop.yml
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 1 | 
             
            inherit_from:
         | 
| 2 | 
            -
            -  | 
| 3 | 
            -
             | 
| 4 | 
            -
            - . | 
| 2 | 
            +
            - ".rubocop_local.yml"
         | 
| 3 | 
            +
            inherit_gem:
         | 
| 4 | 
            +
              manageiq-style: ".rubocop_base.yml"
         | 
    
        data/.rubocop_cc.yml
    CHANGED
    
    
    
        data/.rubocop_local.yml
    CHANGED
    
    
    
        data/.whitesource
    ADDED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            # Changelog
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            All notable changes to this project will be documented in this file.
         | 
| 4 | 
            +
            This project adheres to [Semantic Versioning](http://semver.org/).
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ## [Unreleased]
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ## [1.0.0] - 2022-02-09
         | 
| 9 | 
            +
            ### Changed
         | 
| 10 | 
            +
            - Run rubocop -A (#102)
         | 
| 11 | 
            +
            - Switch from travis to github actions (#104, #105)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            ### Added
         | 
| 14 | 
            +
            - **BREAKING** Add back support for non-concurrent-safe batch strategies (#101)
         | 
| 15 | 
            +
            - Add support for Rails 6.1 (#103)
         | 
| 16 | 
            +
            - Add bundler-inject (#106)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ### Fixed
         | 
| 19 | 
            +
            - Fix InventoryCollection missing cache returns (#107)
         | 
    
        data/Gemfile
    CHANGED
    
    | @@ -1,10 +1,16 @@ | |
| 1 1 | 
             
            source "https://rubygems.org"
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            plugin "bundler-inject", "~> 2.0"
         | 
| 4 | 
            +
            require File.join(Bundler::Plugin.index.load_paths("bundler-inject")[0], "bundler-inject") rescue nil
         | 
| 4 5 |  | 
| 5 6 | 
             
            # Specify your gem's dependencies in inventory_refresh.gemspec
         | 
| 6 7 | 
             
            gemspec
         | 
| 7 8 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 9 | 
            +
            case ENV['TEST_RAILS_VERSION']
         | 
| 10 | 
            +
            when "5.2"
         | 
| 11 | 
            +
              gem "activerecord", "~>5.2.6"
         | 
| 12 | 
            +
            when "6.0"
         | 
| 13 | 
            +
              gem "activerecord", "~>6.0.4"
         | 
| 14 | 
            +
            when "6.1"
         | 
| 15 | 
            +
              gem "activerecord", "~>6.1.4"
         | 
| 16 | 
            +
            end
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,10 +1,9 @@ | |
| 1 1 | 
             
            # InventoryRefresh
         | 
| 2 2 |  | 
| 3 3 | 
             
            [](http://badge.fury.io/rb/inventory_refresh)
         | 
| 4 | 
            -
            [](https://github.com/ManageIQ/inventory_refresh/actions/workflows/ci.yaml)
         | 
| 5 5 | 
             
            [](https://codeclimate.com/github/ManageIQ/inventory_refresh)
         | 
| 6 6 | 
             
            [](https://codeclimate.com/github/ManageIQ/inventory_refresh/coverage)
         | 
| 7 | 
            -
            [](https://hakiri.io/github/ManageIQ/inventory_refresh/master)
         | 
| 8 7 |  | 
| 9 8 | 
             
            [](https://gitter.im/ManageIQ/manageiq/providers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
         | 
| 10 9 |  | 
    
        data/Rakefile
    CHANGED
    
    | @@ -12,7 +12,7 @@ namespace :spec do | |
| 12 12 |  | 
| 13 13 | 
             
              task :db_load_schema do
         | 
| 14 14 | 
             
                require "active_record"
         | 
| 15 | 
            -
                with_connection(test_database_name) { load File.join(__dir__, %w | 
| 15 | 
            +
                with_connection(test_database_name) { load File.join(__dir__, %w[spec schema.rb]) }
         | 
| 16 16 | 
             
              end
         | 
| 17 17 |  | 
| 18 18 | 
             
              desc "Setup test database"
         | 
| @@ -20,7 +20,7 @@ namespace :spec do | |
| 20 20 |  | 
| 21 21 | 
             
              def connection_spec
         | 
| 22 22 | 
             
                require 'yaml'
         | 
| 23 | 
            -
                @connection_spec ||= YAML.load_file(File.join(__dir__, %w | 
| 23 | 
            +
                @connection_spec ||= YAML.load_file(File.join(__dir__, %w[config database.yml]))
         | 
| 24 24 | 
             
              end
         | 
| 25 25 |  | 
| 26 26 | 
             
              def test_database_name
         | 
    
        data/inventory_refresh.gemspec
    CHANGED
    
    | @@ -1,5 +1,4 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            lib = File.expand_path("../lib", __FILE__)
         | 
| 1 | 
            +
            lib = File.expand_path('lib', __dir__)
         | 
| 3 2 | 
             
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 4 3 | 
             
            require "inventory_refresh/version"
         | 
| 5 4 |  | 
| @@ -8,30 +7,30 @@ Gem::Specification.new do |spec| | |
| 8 7 | 
             
              spec.version       = InventoryRefresh::VERSION
         | 
| 9 8 | 
             
              spec.authors       = ["ManageIQ Developers"]
         | 
| 10 9 |  | 
| 11 | 
            -
              spec.summary       =  | 
| 12 | 
            -
              spec.description   =  | 
| 10 | 
            +
              spec.summary       = 'Topological Inventory Persister'
         | 
| 11 | 
            +
              spec.description   = 'Topological Inventory Persister'
         | 
| 13 12 | 
             
              spec.homepage      = "https://github.com/ManageIQ/inventory_refresh"
         | 
| 14 13 | 
             
              spec.licenses      = ["Apache-2.0"]
         | 
| 15 14 |  | 
| 16 15 | 
             
              # Specify which files should be added to the gem when it is released.
         | 
| 17 16 | 
             
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         | 
| 18 | 
            -
              spec.files         = Dir.chdir(File.expand_path( | 
| 17 | 
            +
              spec.files         = Dir.chdir(File.expand_path(__dir__)) do
         | 
| 19 18 | 
             
                `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
         | 
| 20 19 | 
             
              end
         | 
| 21 20 | 
             
              spec.bindir        = "exe"
         | 
| 22 21 | 
             
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 23 22 | 
             
              spec.require_paths = ["lib"]
         | 
| 23 | 
            +
              spec.metadata['rubygems_mfa_required'] = 'true'
         | 
| 24 24 |  | 
| 25 | 
            -
              spec.add_dependency "activerecord", " | 
| 26 | 
            -
              spec.add_dependency "more_core_extensions", " | 
| 25 | 
            +
              spec.add_dependency "activerecord", ">=5.0", "< 7.0"
         | 
| 26 | 
            +
              spec.add_dependency "more_core_extensions", ">=3.5", "< 5"
         | 
| 27 27 | 
             
              spec.add_dependency "pg", "> 0"
         | 
| 28 28 |  | 
| 29 29 | 
             
              spec.add_development_dependency "ancestry"
         | 
| 30 30 | 
             
              spec.add_development_dependency "bundler", "~> 2.0"
         | 
| 31 31 | 
             
              spec.add_development_dependency "factory_bot", "~> 4.11.1"
         | 
| 32 | 
            +
              spec.add_development_dependency "manageiq-style"
         | 
| 32 33 | 
             
              spec.add_development_dependency "rake", "~> 10.0"
         | 
| 33 34 | 
             
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 34 | 
            -
              spec.add_development_dependency " | 
| 35 | 
            -
              spec.add_development_dependency "rubocop-performance"
         | 
| 36 | 
            -
              spec.add_development_dependency "simplecov"
         | 
| 35 | 
            +
              spec.add_development_dependency "simplecov", ">= 0.21.2"
         | 
| 37 36 | 
             
            end
         | 
| @@ -1,12 +1,20 @@ | |
| 1 1 | 
             
            module InventoryRefresh
         | 
| 2 2 | 
             
              class ApplicationRecordIterator
         | 
| 3 | 
            -
                attr_reader :inventory_collection
         | 
| 3 | 
            +
                attr_reader :inventory_collection, :manager_uuids_set, :iterator, :query
         | 
| 4 4 |  | 
| 5 | 
            -
                # An iterator that can fetch batches of the AR objects based on a set of  | 
| 5 | 
            +
                # An iterator that can fetch batches of the AR objects based on a set of manager refs, or just mimics AR relation
         | 
| 6 | 
            +
                # when given an iterator. Or given query, acts as iterator by selecting batches.
         | 
| 6 7 | 
             
                #
         | 
| 7 8 | 
             
                # @param inventory_collection [InventoryRefresh::InventoryCollection] Inventory collection owning the iterator
         | 
| 8 | 
            -
                 | 
| 9 | 
            +
                # @param manager_uuids_set [Array<InventoryRefresh::InventoryCollection::Reference>] Array of references we want to
         | 
| 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)
         | 
| 9 14 | 
             
                  @inventory_collection = inventory_collection
         | 
| 15 | 
            +
                  @manager_uuids_set    = manager_uuids_set
         | 
| 16 | 
            +
                  @iterator             = iterator
         | 
| 17 | 
            +
                  @query                = query
         | 
| 10 18 | 
             
                end
         | 
| 11 19 |  | 
| 12 20 | 
             
                # Iterator that mimics find_in_batches of ActiveRecord::Relation. This iterator serves for making more optimized query
         | 
| @@ -17,22 +25,27 @@ module InventoryRefresh | |
| 17 25 | 
             
                # and relation.where(:id => 500ids)
         | 
| 18 26 | 
             
                #
         | 
| 19 27 | 
             
                # @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
         | 
| 21 28 | 
             
                # @yield Code processing the batches
         | 
| 22 | 
            -
                def find_in_batches(batch_size: 1000,  | 
| 23 | 
            -
                   | 
| 24 | 
            -
                     | 
| 29 | 
            +
                def find_in_batches(batch_size: 1000, &block)
         | 
| 30 | 
            +
                  if iterator
         | 
| 31 | 
            +
                    iterator.call(&block)
         | 
| 32 | 
            +
                  elsif query
         | 
| 33 | 
            +
                    manager_uuids_set.each_slice(batch_size) do |batch|
         | 
| 34 | 
            +
                      yield(query.where(inventory_collection.targeted_selection_for(batch)))
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  else
         | 
| 37 | 
            +
                    manager_uuids_set.each_slice(batch_size) do |batch|
         | 
| 38 | 
            +
                      yield(inventory_collection.db_collection_for_comparison_for(batch))
         | 
| 39 | 
            +
                    end
         | 
| 25 40 | 
             
                  end
         | 
| 26 41 | 
             
                end
         | 
| 27 42 |  | 
| 28 43 | 
             
                # Iterator that mimics find_each of ActiveRecord::Relation using find_in_batches (see #find_in_batches)
         | 
| 29 44 | 
             
                #
         | 
| 30 45 | 
             
                # @yield Code processing the batches
         | 
| 31 | 
            -
                def find_each( | 
| 32 | 
            -
                  find_in_batches | 
| 33 | 
            -
                    batch.each | 
| 34 | 
            -
                      yield(item)
         | 
| 35 | 
            -
                    end
         | 
| 46 | 
            +
                def find_each(&block)
         | 
| 47 | 
            +
                  find_in_batches do |batch|
         | 
| 48 | 
            +
                    batch.each(&block)
         | 
| 36 49 | 
             
                  end
         | 
| 37 50 | 
             
                end
         | 
| 38 51 | 
             
              end
         | 
| @@ -8,30 +8,30 @@ module InventoryRefresh | |
| 8 8 | 
             
                    @graph = graph
         | 
| 9 9 | 
             
                  end
         | 
| 10 10 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 11 | 
            +
                  ################################################################################################################
         | 
| 12 | 
            +
                  # Topological sort of the graph of the DTO collections to find the right order of saving DTO collections and
         | 
| 13 | 
            +
                  # identify what DTO collections can be saved in parallel.
         | 
| 14 | 
            +
                  # Does not mutate graph.
         | 
| 15 | 
            +
                  #
         | 
| 16 | 
            +
                  # @return [Array<Array>] Array of arrays(layers) of InventoryCollection objects
         | 
| 17 | 
            +
                  ################################################################################################################
         | 
| 18 | 
            +
                  # The expected input here is the directed acyclic Graph G (inventory_collections), consisting of Vertices(Nodes) V and
         | 
| 19 | 
            +
                  # Edges E:
         | 
| 20 | 
            +
                  # G = (V, E)
         | 
| 21 | 
            +
                  #
         | 
| 22 | 
            +
                  # The directed edge is defined as (u, v), where u is the dependency of v, i.e. arrow comes from u to v:
         | 
| 23 | 
            +
                  # (u, v) ∈ E and  u,v ∈ V
         | 
| 24 | 
            +
                  #
         | 
| 25 | 
            +
                  # S0 is a layer that has no dependencies:
         | 
| 26 | 
            +
                  # S0 = { v ∈ V ∣ ∀u ∈ V.(u,v) ∉ E}
         | 
| 27 | 
            +
                  #
         | 
| 28 | 
            +
                  # Si+1 is a layer whose dependencies are in the sum of the previous layers from i to 0, cannot write
         | 
| 29 | 
            +
                  # mathematical sum using U in text editor, so there is an alternative format using _(sum)
         | 
| 30 | 
            +
                  # Si+1 = { v ∈ V ∣ ∀u ∈ V.(u,v) ∈ E → u ∈ _(sum(S0..Si))_ }
         | 
| 31 | 
            +
                  #
         | 
| 32 | 
            +
                  # Then each Si can have their Vertices(DTO collections) processed in parallel. This algorithm cannot
         | 
| 33 | 
            +
                  # identify independent sub-graphs inside of the layers Si, so we can make the processing even more effective.
         | 
| 34 | 
            +
                  ################################################################################################################
         | 
| 35 35 | 
             
                  def topological_sort
         | 
| 36 36 | 
             
                    nodes          = graph.nodes.dup
         | 
| 37 37 | 
             
                    edges          = graph.edges
         | 
| @@ -45,14 +45,12 @@ module InventoryRefresh | |
| 45 45 | 
             
                      max_depth -= 1
         | 
| 46 46 | 
             
                      if max_depth <= 0
         | 
| 47 47 | 
             
                        message = "Max depth reached while doing topological sort, your graph probably contains a cycle"
         | 
| 48 | 
            -
                        #logger.error("#{message}:\n#{graph.to_graphviz}")
         | 
| 49 48 | 
             
                        raise "#{message} (see log)"
         | 
| 50 49 | 
             
                      end
         | 
| 51 50 |  | 
| 52 51 | 
             
                      set, nodes = nodes.partition { |v| edges.select { |e| e.second == v }.all? { |e| sets.flatten.include?(e.first) } }
         | 
| 53 52 | 
             
                      if set.blank?
         | 
| 54 53 | 
             
                        message = "Blank dependency set while doing topological sort, your graph probably contains a cycle"
         | 
| 55 | 
            -
                        #logger.error("#{message}:\n#{graph.to_graphviz}")
         | 
| 56 54 | 
             
                        raise "#{message} (see log)"
         | 
| 57 55 | 
             
                      end
         | 
| 58 56 |  | 
| @@ -37,7 +37,7 @@ module InventoryRefresh | |
| 37 37 | 
             
                    s << "  #{node_names[from]} -> #{node_names[to]};"
         | 
| 38 38 | 
             
                  end
         | 
| 39 39 | 
             
                  s << "}"
         | 
| 40 | 
            -
                  s.join("\n") | 
| 40 | 
            +
                  "#{s.join("\n")}\n"
         | 
| 41 41 | 
             
                end
         | 
| 42 42 |  | 
| 43 43 | 
             
                protected
         | 
| @@ -147,7 +147,7 @@ module InventoryRefresh | |
| 147 147 | 
             
                  nodes.group_by { |n| n.respond_to?(:name) ? n.name.to_s : n.to_s }.each do |base_name, ns|
         | 
| 148 148 | 
             
                    ns.each_with_index do |n, i|
         | 
| 149 149 | 
             
                      name = ns.size == 1 ? base_name : "#{base_name}_#{i}"
         | 
| 150 | 
            -
                      name =  | 
| 150 | 
            +
                      name = "\"#{name.gsub(/["\\]/) { |c| "\\#{c}" }}\"" unless /^[A-Za-z0-9_]+$/.match?(name)
         | 
| 151 151 | 
             
                      node_names[n] = name
         | 
| 152 152 | 
             
                    end
         | 
| 153 153 | 
             
                  end
         | 
| @@ -4,17 +4,39 @@ module InventoryRefresh | |
| 4 4 | 
             
                  class MissingModelClassError < StandardError; end
         | 
| 5 5 |  | 
| 6 6 | 
             
                  def self.allowed_properties
         | 
| 7 | 
            -
                    %i | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 7 | 
            +
                    %i[
         | 
| 8 | 
            +
                      all_manager_uuids
         | 
| 9 | 
            +
                      arel
         | 
| 10 | 
            +
                      association
         | 
| 11 | 
            +
                      attributes_blacklist
         | 
| 12 | 
            +
                      attributes_whitelist
         | 
| 13 | 
            +
                      batch_extra_attributes
         | 
| 14 | 
            +
                      complete
         | 
| 15 | 
            +
                      create_only
         | 
| 16 | 
            +
                      custom_save_block
         | 
| 17 | 
            +
                      custom_reconnect_block
         | 
| 18 | 
            +
                      default_values
         | 
| 19 | 
            +
                      delete_method
         | 
| 20 | 
            +
                      dependency_attributes
         | 
| 21 | 
            +
                      check_changed
         | 
| 22 | 
            +
                      inventory_object_attributes
         | 
| 23 | 
            +
                      manager_ref
         | 
| 24 | 
            +
                      manager_ref_allowed_nil
         | 
| 25 | 
            +
                      manager_uuids
         | 
| 26 | 
            +
                      model_class
         | 
| 27 | 
            +
                      name
         | 
| 28 | 
            +
                      parent
         | 
| 29 | 
            +
                      parent_inventory_collections
         | 
| 30 | 
            +
                      retention_strategy
         | 
| 31 | 
            +
                      strategy
         | 
| 32 | 
            +
                      saver_strategy
         | 
| 33 | 
            +
                      secondary_refs
         | 
| 34 | 
            +
                      targeted
         | 
| 35 | 
            +
                      targeted_arel
         | 
| 36 | 
            +
                      update_only
         | 
| 37 | 
            +
                      use_ar_object
         | 
| 38 | 
            +
                      assert_graph_integrity
         | 
| 39 | 
            +
                    ].to_set
         | 
| 18 40 | 
             
                  end
         | 
| 19 41 |  | 
| 20 42 | 
             
                  def allowed_properties
         | 
| @@ -76,8 +98,8 @@ module InventoryRefresh | |
| 76 98 |  | 
| 77 99 | 
             
                    send(@name.to_sym) if @name.respond_to?(:to_sym) && respond_to?(@name.to_sym)
         | 
| 78 100 |  | 
| 79 | 
            -
                    if @properties[:model_class].nil?
         | 
| 80 | 
            -
                      add_properties(:model_class => auto_model_class) | 
| 101 | 
            +
                    if @properties[:model_class].nil? && !(@options[:without_model_class])
         | 
| 102 | 
            +
                      add_properties(:model_class => auto_model_class)
         | 
| 81 103 | 
             
                    end
         | 
| 82 104 | 
             
                  end
         | 
| 83 105 |  | 
| @@ -177,7 +199,7 @@ module InventoryRefresh | |
| 177 199 |  | 
| 178 200 | 
             
                  def assert_allowed_property(name)
         | 
| 179 201 | 
             
                    unless allowed_properties.include?(name)
         | 
| 180 | 
            -
                      raise "InventoryCollection property :#{name} is not allowed. Allowed properties are:\n#{ | 
| 202 | 
            +
                      raise "InventoryCollection property :#{name} is not allowed. Allowed properties are:\n#{allowed_properties.to_a.map(&:to_s).join(', ')}"
         | 
| 181 203 | 
             
                    end
         | 
| 182 204 | 
             
                  end
         | 
| 183 205 |  | 
| @@ -216,7 +238,7 @@ module InventoryRefresh | |
| 216 238 | 
             
                  def auto_inventory_attributes
         | 
| 217 239 | 
             
                    return if @properties[:model_class].nil?
         | 
| 218 240 |  | 
| 219 | 
            -
                    (@properties[:model_class].new.methods - ar_base_class.methods).grep( | 
| 241 | 
            +
                    (@properties[:model_class].new.methods - ar_base_class.methods).grep(/^\w+?=$/).collect do |setter|
         | 
| 220 242 | 
             
                      setter.to_s[0..setter.length - 2].to_sym
         | 
| 221 243 | 
             
                    end
         | 
| 222 244 | 
             
                  end
         | 
| @@ -70,6 +70,15 @@ 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 | 
            +
             | 
| 73 82 | 
             
                  # Finds of builds a new InventoryObject. By building it, we also put in into the InventoryCollection's storage.
         | 
| 74 83 | 
             
                  #
         | 
| 75 84 | 
             
                  # @param hash [Hash] Hash that needs to contain attributes defined in :manager_ref of the
         |