class Cachext::Multi::FindByIds

Attributes

ids[R]
multi[R]

Public Class Methods

new(multi, ids, lookup) click to toggle source
# File lib/cachext/multi.rb, line 49
def initialize multi, ids, lookup
  @multi = multi
  @ids = ids
  @lookup = lookup
end

Public Instance Methods

records() click to toggle source
# File lib/cachext/multi.rb, line 55
def records
  fresh_cached.merge(direct).reverse_merge(stale)
end

Private Instance Methods

delete_backups(ids) click to toggle source
# File lib/cachext/multi.rb, line 120
def delete_backups ids
  return if ids.blank?

  ids.each do |id|
    key = Key.new(multi.key(id))
    key.delete_backup
  end
end
direct() click to toggle source
# File lib/cachext/multi.rb, line 70
def direct
  @direct ||= if uncached_or_stale_ids.length > 0
    with_lock uncached_or_stale_ids do
      records = uncached_where uncached_or_stale_ids
      write_cache records
      records
    end
  else
    {}
  end
rescue Features::Lock::TimeoutWaitingForLock => e
  config.error_logger.call e if config.log_errors?
  {}
end
fresh_cached() click to toggle source
# File lib/cachext/multi.rb, line 61
def fresh_cached
  @fresh_cached ||= cache.read_multi(*ids.map { |id| multi.key(id) }).
    transform_keys { |key| key.last }
end
lock_key_from_ids(ids) click to toggle source
# File lib/cachext/multi.rb, line 107
def lock_key_from_ids(ids)
  key = Key.new multi.key_base + ids
  key.lock_key
end
obtain_lock(ids) click to toggle source
# File lib/cachext/multi.rb, line 92
def obtain_lock ids
  lock_key = lock_key_from_ids ids

  start_time = Time.now

  until lock_info = lock_manager.lock(lock_key, (heartbeat_expires * 1000).ceil)
    if Time.now - start_time > max_lock_wait
      raise Features::Lock::TimeoutWaitingForLock
    end
    sleep rand
  end

  lock_info
end
stale() click to toggle source
# File lib/cachext/multi.rb, line 129
def stale
  cache.read_multi(*(uncached_or_stale_ids - direct.keys).map { |id| [:backup_cache] + multi.key(id) }).
    transform_keys { |key| key.last }
end
uncached_or_stale_ids() click to toggle source
# File lib/cachext/multi.rb, line 66
def uncached_or_stale_ids
  ids - fresh_cached.keys
end
uncached_where(ids) click to toggle source
# File lib/cachext/multi.rb, line 134
def uncached_where ids
  with_heartbeat_extender lock_key_from_ids(ids) do
    records = @lookup.call ids

    if records.is_a?(Array)
      records = records.each_with_object({}) do |record, acc|
        acc[record.id] = record
      end
    end

    delete_backups ids - records.keys
    records
  end
rescue *config.default_errors => e
  config.error_logger.call e if config.log_errors?
  {}
end
with_heartbeat_extender(lock_key, &block) click to toggle source
# File lib/cachext/multi.rb, line 152
def with_heartbeat_extender lock_key, &block
  done = false
  heartbeat_frequency = heartbeat_expires / 2

  Thread.new do
    loop do
      break if done
      sleep heartbeat_frequency
      break if done
      lock_manager.lock lock_key, (heartbeat_expires * 1000).ceil, extend: @lock_info
    end
  end

  block.call
ensure
  lock_manager.unlock @lock_info
  done = true
end
with_lock(ids, &block) click to toggle source
# File lib/cachext/multi.rb, line 85
def with_lock ids, &block
  @lock_info = obtain_lock ids
  block.call
ensure
  lock_manager.unlock @lock_info if @lock_info
end
write_cache(records) click to toggle source
# File lib/cachext/multi.rb, line 112
def write_cache records
  records.each do |id, record|
    key = Key.new(multi.key(id))
    key.write record, expires_in: multi.expires_in
    key.write_backup record
  end
end