class InventoryRefresh::SaveCollection::Sweeper

Attributes

inventory_collection[R]
model_class[R]
primary_key[R]
refresh_state[R]
sweep_scope[R]

Public Class Methods

build_scope_set(sweep_scope) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 37
def build_scope_set(sweep_scope)
  return [] unless sweep_scope

  if sweep_scope.kind_of?(Array)
    sweep_scope.map(&:to_sym).to_set
  elsif sweep_scope.kind_of?(Hash)
    sweep_scope.keys.map(&:to_sym).to_set
  end
end
in_scope?(inventory_collection, scope_set) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 33
def in_scope?(inventory_collection, scope_set)
  scope_set.include?(inventory_collection&.name)
end
new(inventory_collection, refresh_state, sweep_scope) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 56
def initialize(inventory_collection, refresh_state, sweep_scope)
  @inventory_collection = inventory_collection

  @refresh_state = refresh_state
  @sweep_scope   = sweep_scope

  @model_class = inventory_collection.model_class
  @primary_key = @model_class.primary_key
end
sweep(_ems, inventory_collections, sweep_scope, refresh_state) click to toggle source

Sweeps inactive records based on :last_seen_on and :refresh_start timestamps. All records having :last_seen_on lower than :refresh_start or nil will be archived/deleted.

@param _ems [ActiveRecord] Manager owning the inventory_collections @param inventory_collections [Array<InventoryRefresh::InventoryCollection>] Array of InventoryCollection objects

for sweeping

@param sweep_scope [Array<String, Symbol, Hash>] Array of inventory collection names marking sweep. Or for

targeted sweeping it's array of hashes, where key is inventory collection name pointing to an array of
identifiers of inventory objects we want to target for sweeping.

@param refresh_state [ActiveRecord] Record of :refresh_states

# File lib/inventory_refresh/save_collection/sweeper.rb, line 19
def sweep(_ems, inventory_collections, sweep_scope, refresh_state)
  scope_set = build_scope_set(sweep_scope)

  inventory_collections.each do |inventory_collection|
    next unless sweep_possible?(inventory_collection, scope_set)

    new(inventory_collection, refresh_state, sweep_scope).sweep
  end
end
sweep_possible?(inventory_collection, scope_set) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 29
def sweep_possible?(inventory_collection, scope_set)
  inventory_collection.supports_column?(:last_seen_at) && in_scope?(inventory_collection, scope_set)
end

Public Instance Methods

apply_targeted_sweep_scope(all_entities_query) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 66
def apply_targeted_sweep_scope(all_entities_query)
  if sweep_scope.kind_of?(Hash)
    scope = sweep_scope[inventory_collection.name]
    return all_entities_query if scope.nil? || scope.empty?

    # Scan the scope to find all references, so we can load them from DB in batches
    scan_sweep_scope!(scope)

    scope_keys = Set.new
    conditions = scope.map { |x| InventoryRefresh::InventoryObject.attributes_with_keys(x, inventory_collection, scope_keys) }
    assert_conditions!(conditions, scope_keys)

    all_entities_query.where(inventory_collection.build_multi_selection_condition(conditions, scope_keys))
  else
    all_entities_query
  end
end
assert_conditions!(conditions, scope_keys) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 99
def assert_conditions!(conditions, scope_keys)
  conditions.each do |cond|
    assert_uniform_keys!(cond, scope_keys)
    assert_non_existent_keys!(cond)
  end
end
assert_non_existent_keys!(cond) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 115
def assert_non_existent_keys!(cond)
  return if (diff = (cond.keys.to_set - inventory_collection.all_column_names)).empty?

  raise(InventoryRefresh::Exception::SweeperNonExistentScopeKeyFoundError,
        "Sweeping scope for #{inventory_collection} contained keys that are not columns: #{diff.to_a}")
end
assert_uniform_keys!(cond, scope_keys) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 106
def assert_uniform_keys!(cond, scope_keys)
  return if (diff = (scope_keys - cond.keys.to_set)).empty?

  raise(InventoryRefresh::Exception::SweeperNonUniformScopeKeyFoundError,
        "Sweeping scope for #{inventory_collection} contained non uniform keys. All keys for the"\
        "scope must be the same, it's possible to send multiple sweeps with different key set. Missing keys"\
        " for a scope were: #{diff.to_a}")
end
loadable?(value) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 84
def loadable?(value)
  inventory_object_lazy?(value) || inventory_object?(value)
end
scan_sweep_scope!(scope) click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 88
def scan_sweep_scope!(scope)
  scope.each do |sc|
    sc.each_value do |value|
      next unless loadable?(value)

      value_inventory_collection = value.inventory_collection
      value_inventory_collection.add_reference(value.reference, :key => value.key)
    end
  end
end
sweep() click to toggle source
# File lib/inventory_refresh/save_collection/sweeper.rb, line 122
def sweep
  refresh_start = refresh_state.created_at
  raise "Couldn't load :created_at out of RefreshState record: #{refresh_state}" unless refresh_start

  table       = model_class.arel_table
  date_field  = table[:last_seen_at]
  all_entities_query = inventory_collection.full_collection_for_comparison
  all_entities_query = all_entities_query.active if inventory_collection.retention_strategy == :archive && inventory_collection.supports_column?(:archived_at)

  all_entities_query = apply_targeted_sweep_scope(all_entities_query)

  query = all_entities_query
          .where(date_field.lt(refresh_start)).or(all_entities_query.where(:last_seen_at => nil))
          .select(table[:id])

  query.find_in_batches do |batch|
    destroy_records!(batch)
  end
end