3
3
module Puppet::Util::Cacher
7
# Cause all cached values to be considered expired.
12
# Is the provided timestamp earlier than our expiration timestamp?
13
# If it is, then the associated value is expired.
14
def dependent_data_expired?(ts)
15
return false unless timestamp
23
4
# Our module has been extended in a class; we can only add the Instance methods,
24
5
# which become *class* methods in the class.
25
6
def self.extended(other)
40
21
module ClassMethods
41
22
# Provide a means of defining an attribute whose value will be cached.
42
23
# Must provide a block capable of defining the value if it's flushed..
43
def cached_attr(name, options = {}, &block)
24
def cached_attr(name, ttl, &block)
44
25
init_method = "init_#{name}"
45
26
define_method(init_method, &block)
28
set_attr_ttl(name, ttl)
47
30
define_method(name) do
51
34
define_method(name.to_s + "=") do |value|
52
35
# Make sure the cache timestamp is set
54
value_cache.synchronize { value_cache[name] = value }
57
if ttl = options[:ttl]
58
set_attr_ttl(name, ttl)
36
value_cache.synchronize do
37
value_cache[name] = value
63
return nil unless @attr_ttls
73
53
# Methods that get added to instances.
74
54
module InstanceMethods
77
# Only expire if we have an expirer. This is
78
# mostly so that we can comfortably handle cases
79
# like Puppet::Type instances, which use their
80
# catalog as their expirer, and they often don't
94
@cache_timestamp ||= Time.now
97
57
def cached_value(name)
98
58
value_cache.synchronize do
99
# Allow a nil expirer, in which case we regenerate the value every time.
100
if expired_by_expirer?(name)
102
@cache_timestamp = Time.now
103
elsif expired_by_ttl?(name)
104
value_cache.delete(name)
59
if value_cache[name].nil? or expired_by_ttl?(name)
60
value_cache[name] = send("init_#{name}")
106
value_cache[name] = send("init_#{name}") unless value_cache.include?(name)
111
def expired_by_expirer?(name)
113
return true unless self.class.attr_ttl(name)
115
expirer.dependent_data_expired?(cache_timestamp)
118
67
def expired_by_ttl?(name)
119
return false unless self.class.respond_to?(:attr_ttl)
120
return false unless ttl = self.class.attr_ttl(name)
122
@ttl_timestamps ||= {}
123
@ttl_timestamps[name] ||= Time.now
125
(Time.now - @ttl_timestamps[name]) > ttl
68
@attr_expirations[name] < Time.now
71
def set_expiration(name)
72
@attr_expirations ||= {}
73
@attr_expirations[name] = Time.now + self.class.attr_ttl(name)