class Berkshelf::API::CacheManager
Constants
- SAVE_INTERVAL
Attributes
cache[R]
@return [DependencyCache]
Public Class Methods
cache_file()
click to toggle source
@return [String]
# File lib/berkshelf/api/cache_manager.rb, line 5 def cache_file File.join(Application.home_path, "cerch") end
new()
click to toggle source
# File lib/berkshelf/api/cache_manager.rb, line 25 def initialize log.info "#{self} starting..." @cache = DependencyCache.new load_save if File.exist?(self.class.cache_file) every(SAVE_INTERVAL) { save } end
Public Instance Methods
add(cookbook, metadata)
click to toggle source
@param [RemoteCookbook] cookbook @param [Ridley::Chef::Cookbook::Metadata] metadata
@return [Hash]
# File lib/berkshelf/api/cache_manager.rb, line 36 def add(cookbook, metadata) log.debug "#{self} adding (#{cookbook.name}, #{cookbook.version})" cache.add(cookbook, metadata) end
has_cookbook?(name, version)
click to toggle source
Check if the cache knows about the given cookbook version
@param [#to_s] name @param [#to_s] version
@return [Boolean]
# File lib/berkshelf/api/cache_manager.rb, line 117 def has_cookbook?(name, version) @cache.has_cookbook?(name, version) end
load_save()
click to toggle source
# File lib/berkshelf/api/cache_manager.rb, line 121 def load_save log.info "Loading save from #{self.class.cache_file}" @cache = DependencyCache.from_file(self.class.cache_file) log.info "Cache contains #{@cache.cookbooks.size} items" end
process_worker(worker)
click to toggle source
@param [CacheBuilder::Worker::Base] worker
# File lib/berkshelf/api/cache_manager.rb, line 81 def process_worker(worker) log.info "Processing #{worker}" remote_cookbooks = worker.cookbooks log.info "Found #{remote_cookbooks.size} cookbooks from #{worker}" created_cookbooks, deleted_cookbooks = diff(remote_cookbooks, worker.priority) log.debug "#{created_cookbooks.size} cookbooks to be added to the cache from #{worker}" log.debug "#{deleted_cookbooks.size} cookbooks to be removed from the cache from #{worker}" # Process metadata in chunks - Ridley cookbook resource uses a # task_class TaskThread, which means each future gets its own # thread. If we have many (>2000) cookbooks we can easily # exhaust the available threads on the system. created_cookbooks_with_metadata = [] until created_cookbooks.empty? work = created_cookbooks.slice!(0,500) log.info "Processing metadata for #{work.size} cookbooks with #{created_cookbooks.size} remaining on #{worker}" work.map! do |remote| [ remote, worker.future(:metadata, remote) ] end.map! do |remote, metadata| metadata.value ? [remote, metadata.value] : nil end created_cookbooks_with_metadata += work.compact end log.info "About to merge cookbooks" merge(created_cookbooks_with_metadata, deleted_cookbooks) log.info "#{self} cache updated." end
process_workers(workers)
click to toggle source
Loops through a list of workers and merges their cookbook sets into the cache
@param [Array<CacheBuilder::Worker::Base>] workers
The workers for this cache
@return [Boolean]
# File lib/berkshelf/api/cache_manager.rb, line 58 def process_workers(workers) # If the cache has been warmed already, we want to spawn # workers for all the endpoints concurrently. However, if the # cache is cold we want to run sequentially, so higher priority # endpoints can work before lower priority, avoiding duplicate # downloads. # We don't want crashing workers to crash the CacheManager. # Crashes are logged so just ignore the exceptions if warmed? Array(workers).flatten.collect do |worker| self.future(:process_worker, worker) end.each do |f| f.value rescue nil end else Array(workers).flatten.each do |worker| process_worker(worker) rescue nil end end self.set_warmed end
remove(name, version)
click to toggle source
Remove the cached item matching the given name and version
@param [#to_s] name @param [#to_s] version
@return [DependencyCache]
# File lib/berkshelf/api/cache_manager.rb, line 47 def remove(name, version) log.debug "#{self} removing (#{name}, #{version})" cache.remove(name, version) end
to_s()
click to toggle source
@return [String]
# File lib/berkshelf/api/cache_manager.rb, line 128 def to_s "Cache manager" end
Private Instance Methods
diff(cookbooks, worker_priority)
click to toggle source
@param [Array<RemoteCookbook>] cookbooks
An array of RemoteCookbooks representing all the cookbooks on the indexed site
@param [Integer] worker_priority
The priority/ID of the endpoint that is running
@return [Array(Array<RemoteCookbook>, Array<RemoteCookbook>)]
A tuple of Arrays of RemoteCookbooks The first array contains items not in the cache The second array contains items in the cache, but not in the cookbooks parameter
# File lib/berkshelf/api/cache_manager.rb, line 164 def diff(cookbooks, worker_priority) known_cookbooks = cache.cookbooks.select { |c| c.priority <= worker_priority } created_cookbooks = cookbooks - known_cookbooks deleted_cookbooks = (known_cookbooks - cookbooks).select { |c| c.priority == worker_priority } [ created_cookbooks, deleted_cookbooks ] end
finalize_callback()
click to toggle source
# File lib/berkshelf/api/cache_manager.rb, line 171 def finalize_callback log.info "Cache Manager shutting down..." save end
merge(created_cookbooks, deleted_cookbooks)
click to toggle source
# File lib/berkshelf/api/cache_manager.rb, line 134 def merge(created_cookbooks, deleted_cookbooks) log.info "#{self} adding (#{created_cookbooks.length}) items..." created_cookbooks.each do |remote_with_metadata| remote, metadata = remote_with_metadata add(remote, metadata) end log.info "#{self} removing (#{deleted_cookbooks.length}) items..." deleted_cookbooks.each { |remote| remove(remote.name, remote.version) } log.info "#{self} cache updated." save end
save()
click to toggle source
# File lib/berkshelf/api/cache_manager.rb, line 148 def save if warmed? log.info "Saving the cache to: #{self.class.cache_file}" cache.save(self.class.cache_file) log.info "Cache saved!" end end