diff options
author | Luke Kanies <luke@madstop.com> | 2008-04-07 23:47:01 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2008-04-08 11:33:49 -0500 |
commit | c6729d134b6b0479e091928ee68abb9008d0f71d (patch) | |
tree | 0fc97c75dbd946d18d8c72d3006b10bf38054ee8 /lib/puppet | |
parent | 8e1e06ff1c65bc5d8162fce41776e31b9f00d1bf (diff) | |
download | puppet-c6729d134b6b0479e091928ee68abb9008d0f71d.tar.gz puppet-c6729d134b6b0479e091928ee68abb9008d0f71d.tar.xz puppet-c6729d134b6b0479e091928ee68abb9008d0f71d.zip |
Reworking the caching layer to use TTLs instead of versions
based on timestamps. This just modifies the indirection class
itself, there is still some work to do to remove version code
from other classes.
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/indirector/indirection.rb | 96 |
1 files changed, 77 insertions, 19 deletions
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb index d47433c60..91cc42b17 100644 --- a/lib/puppet/indirector/indirection.rb +++ b/lib/puppet/indirector/indirection.rb @@ -1,4 +1,5 @@ require 'puppet/util/docs' +require 'puppet/indirector/envelope' # The class that connects functional classes with their different collection # back-ends. Each indirection has a set of associated terminus classes, @@ -28,8 +29,7 @@ class Puppet::Indirector::Indirection # Find an indirected model by name. This is provided so that Terminus classes # can specifically hook up with the indirections they are associated with. def self.model(name) - match = @@indirections.find { |i| i.name == name } - return nil unless match + return nil unless match = @@indirections.find { |i| i.name == name } match.model end @@ -65,6 +65,25 @@ class Puppet::Indirector::Indirection @@indirections.delete(self) if @@indirections.include?(self) end + # Set the time-to-live for instances created through this indirection. + def ttl=(value) + raise ArgumentError, "Indirection TTL must be an integer" unless value.is_a?(Fixnum) + @ttl = value + end + + # Default to the runinterval for the ttl. + def ttl + unless defined?(@ttl) + @ttl = Puppet[:runinterval].to_i + end + @ttl + end + + # Calculate the expiration date for a returned instance. + def expiration + Time.now + ttl + end + # Generate the full doc string. def doc text = "" @@ -106,6 +125,12 @@ class Puppet::Indirector::Indirection end end + # Set the options that can be passed on to the terminus instances. + attr_reader :option_struct + def options=(options) + @option_struct = Struct.new(*options) + end + # Return the singleton terminus for this indirection. def terminus(terminus_name = nil) # Get the name of the terminus. @@ -161,29 +186,41 @@ class Puppet::Indirector::Indirection check_authorization(:find, terminus_name, ([key] + args)) # See if our instance is in the cache and up to date. - if cache? and cache.has_most_recent?(key, terminus(terminus_name).version(key)) - Puppet.debug "Using cached %s %s" % [self.name, key] - return cache.find(key, *args) + if cache? and cached = cache.find(key, *args) + if cached.expired? + Puppet.info "Cached %s %s expired at %s; not using" % [self.name, key, cached.expiration] + else + Puppet.debug "Using cached %s %s" % [self.name, key] + return cached + end end # Otherwise, return the result from the terminus, caching if appropriate. if result = terminus(terminus_name).find(key, *args) - result.version ||= Time.now.utc + # Include the envelope module, so we can set the expiration. + result.extend(Puppet::Indirector::Envelope) + result.expiration ||= self.expiration if cache? Puppet.info "Caching %s %s" % [self.name, key] cache.save(result, *args) end - terminus(terminus_name).post_find(result) if terminus(terminus_name).respond_to?(:post_find) - return result end + + return nil end - def destroy(*args) - check_authorization(:destroy, terminus_class, args) + def destroy(key, *args) + check_authorization(:destroy, terminus_class, ([key] + args)) + + terminus.destroy(key, *args) + + if cache? and cached = cache.find(key, *args) + cache.destroy(key, *args) + end - terminus.destroy(*args) + nil end def search(*args) @@ -191,21 +228,22 @@ class Puppet::Indirector::Indirection result = terminus.search(*args) - terminus().post_search(result) if terminus().respond_to?(:post_search) - result end # these become instance methods def save(instance, *args) - check_authorization(:save, terminus_class, ([instance] + args)) + if respond_to?(:select_terminus) + terminus_name = select_terminus(instance.name, *args) + else + terminus_name = terminus_class + end - instance.version ||= Time.now.utc - dest = cache? ? cache : terminus - return if dest.has_most_recent?(instance.name, instance.version) - Puppet.info "Caching %s %s" % [self.name, instance.name] if cache? + check_authorization(:save, terminus_name, ([instance] + args)) + + # If caching is enabled, save our document there, do cache.save(instance, *args) if cache? - terminus.save(instance, *args) + terminus(terminus_class).save(instance, *args) end def version(*args) @@ -226,6 +264,20 @@ class Puppet::Indirector::Indirection end end + # Handle a given indirected call. + def prepare_call(method, arguments) + raise ArgumentError, "Options must be a hash" unless arguments.is_a?(Hash) + + # Set any terminus options. + options = option_struct ? set_options(option_struct, arguments) : nil + + tclass = choose_terminus(options) + + check_authorization(method, tclass, options) + + return terminus(tclass), options + end + # Create a new terminus instance. def make_terminus(terminus_class) # Load our terminus class. @@ -234,4 +286,10 @@ class Puppet::Indirector::Indirection end return klass.new end + + # Create a struct instance with all of the appropriate options set + # from the provided hash. + def set_options(struct, arguments) + struct.new(struct.members.inject([]) { |array, param| arguments[param.to_sym]; array } ) + end end |