Class: Currency::Exchange::Rate::Source::TimedCache

Inherits:
Base
  • Object
show all
Defined in:
lib/currency/exchange/rate/source/timed_cache.rb

Overview

A timed cache for rate sources.

This class should be used at the top-level of a rate source change, to correctly check rate dates.

Instance Attribute Summary collapse

Attributes inherited from Base

#pivot_currency, #time_quantitizer, #verbose

Instance Method Summary collapse

Methods inherited from Base

#__subclass_responsibility, #clear_rate, #convert, #currencies, #get_rate_base, #get_rates, #new_rate, #normalize_time, #to_s

Constructor Details

#initialize(*opt) ⇒ TimedCache

Returns a new instance of TimedCache.



43
44
45
46
47
48
49
50
51
52
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 43

def initialize(*opt)
  self.time_to_live = 600
  self.time_to_live_fudge = 30
  @rate_load_time = nil
  @rate_reload_time = nil
  @processing_rates = false
  @cached_rates = { }
  @cached_rates_old = nil
  super(*opt)
end

Instance Attribute Details

#rate_load_timeObject (readonly)

Returns the time of the last load.



30
31
32
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 30

def rate_load_time
  @rate_load_time
end

#rate_reload_timeObject (readonly)

Returns the time of the next load.



34
35
36
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 34

def rate_reload_time
  @rate_reload_time
end

#sourceObject

The rate source.



13
14
15
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 13

def source
  @source
end

#time_to_liveObject

Defines the number of seconds rates until rates become invalid, causing a request of new rates.

Defaults to 600 seconds.



19
20
21
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 19

def time_to_live
  @time_to_live
end

#time_to_live_fudgeObject

Defines the number of random seconds to add before rates become invalid.

Defaults to 30 seconds.



26
27
28
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 26

def time_to_live_fudge
  @time_to_live_fudge
end

Instance Method Details

#_calc_rate_reload_timeObject



147
148
149
150
151
152
153
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 147

def _calc_rate_reload_time
  if @time_to_live && @rate_load_time
    @rate_reload_time = @rate_load_time + (@time_to_live + (@time_to_live_fudge || 0))
    $stderr.puts "#{self}: rates expire on #{@rate_reload_time}" if @verbose
  end

end

#_load_rates_from_source(time = nil) ⇒ Object

:nodoc:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 157

def _load_rates_from_source(time = nil) # :nodoc:
  rates = nil

  begin
    # Do not allow re-entrancy
    raise Currency::Exception::InvalidReentrancy, "Reentry!" if @processing_rates
    
    # Begin processing new rate request.
    @processing_rates = true

    # Clear cached Rates.
    clear_rates

    # Load rates from the source.
    rates = source.load_rates(time)
    
    # Compute new rate timestamp.
    @rate_load_time = Time.now

    # STDERR.puts "rate_load_time = #{@rate_load_time}"
  ensure
    # End processsing new rate request.
    @processing_rates = false
  
  end

  # STDERR.puts "_load_rates => #{rates.inspect}"

  rates
end

#available?(time = nil) ⇒ Boolean

Returns true if the underlying rate provider is available.

Returns:

  • (Boolean)


190
191
192
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 190

def available?(time = nil)
  source.available?(time)
end

#clear_ratesObject

Clears current rates.



56
57
58
59
60
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 56

def clear_rates
  @cached_rates = { }
  @source.clear_rates
  super
end

#expired?Boolean

Returns true if the cache of Rates is expired.

Returns:

  • (Boolean)


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 65

def expired?
  if @time_to_live &&
      @rate_reload_time &&
      (Time.now > @rate_reload_time)
    
    if @cached_rates 
      $stderr.puts "#{self}: rates expired on #{@rate_reload_time}" if @verbose
      
      @cached_rates_old = @cached_rates
    end

    clear_rates
    
    true
  else
    false
  end
end

#get_rate(c1, c2, time) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 94

def get_rate(c1, c2, time)
  # STDERR.puts "get_rate #{c1} #{c2} #{time}"
  rates = load_rates(time)
  # STDERR.puts "rates = #{rates.inspect}"
  rate = rates && (rates.select{|x| x.c1 == c1 && x.c2 == c2}[0])
  # STDERR.puts "rate = #{rate.inspect}"
  rate
end

#load_rates(time = nil) ⇒ Object

Returns an array of all the cached Rates.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 111

def load_rates(time = nil)
  # Check expiration.
  expired?
  
  # Return rates, if cached.
  return rates if rates = @cached_rates["#{time}"]
  
  # Force load of rates.
  rates = @cached_rates["#{time}"] = _load_rates_from_source(time)
  
  # Update expiration.
  _calc_rate_reload_time

  return nil unless rates

  # Flush old rates.
  @cached_rates_old = nil
      
  rates
end

#nameObject

Returns source’s name.



38
39
40
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 38

def name
  source.name
end

#rate(c1, c2, time) ⇒ Object

Check expired? before returning a Rate.



86
87
88
89
90
91
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 86

def rate(c1, c2, time)
  if expired?
    clear_rates
  end
  super(c1, c2, time)
end

#rates(time = nil) ⇒ Object

Returns an array of all the cached Rates.



105
106
107
# File 'lib/currency/exchange/rate/source/timed_cache.rb', line 105

def rates(time = nil)
  load_rates(time)
end