forked from ManageIQ/manageiq-gems-pending
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmiq-module.rb
60 lines (48 loc) · 1.89 KB
/
miq-module.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
require 'sync'
$miq_cache_with_timeout = {}
$miq_cache_with_timeout_lock = Sync.new
class Module
def cache_with_timeout(method, timeout = nil, &block)
raise "no block given" if block.nil?
raise ArgumentError, "meth must be a Symbol" unless method.respond_to?(:to_sym)
method = method.to_sym
clear_cache_method = "#{method}_clear_cache".to_sym
cached_method = "#{method}_cached?".to_sym
key = "#{name}.#{method}".to_sym
$miq_cache_with_timeout_lock.synchronize(:EX) do
$miq_cache_with_timeout[key] = {}
end
# Defining class methods is done by defining instance methods on the singleton class
singleton_class = (class << self; self; end)
singleton_class.send(:define_method, method) do |*args|
force_reload = args.first
return $miq_cache_with_timeout_lock.synchronize(:EX) do
cache = $miq_cache_with_timeout[key]
old_timeout = cache[:timeout]
cache.clear if force_reload || (old_timeout && Time.now.utc > old_timeout)
break cache[:value] if cache.key?(:value)
new_timeout = timeout || 300 # 5 minutes
new_timeout = new_timeout.call if new_timeout.kind_of?(Proc)
new_timeout = Time.now.utc + new_timeout
new_value = block.call
cache[:timeout] = new_timeout
cache[:value] = new_value
end
end
singleton_class.send(:define_method, clear_cache_method) do |*_args|
$miq_cache_with_timeout_lock.synchronize(:EX) do
$miq_cache_with_timeout[key].clear
end
end
singleton_class.send(:define_method, cached_method) do |*_args|
$miq_cache_with_timeout_lock.synchronize(:EX) do
!$miq_cache_with_timeout[key].empty?
end
end
end
def self.clear_all_cache_with_timeout
$miq_cache_with_timeout_lock.synchronize(:EX) do
$miq_cache_with_timeout.each_value(&:clear)
end
end
end