Class: A4Tools::CachingClient
Class Attribute Summary collapse
Instance Attribute Summary collapse
Attributes inherited from AcresClient
#connect_time, #connected, #history, #password, #ready, #server_info, #start_time, #token, #uri, #username, #version
Class Method Summary
collapse
Instance Method Summary
collapse
Methods inherited from AcresClient
#add_message_to_history, #app_info, #attempt_snoop, #authenticate, #authenticate_if_needed, #connect, #connect_if_needed, #device_info, #disconnect, #empty_query, #inject_token, #jsonrpc_message, #make_password, #next_msg_id, #response_body, #send_message, #snoop_token, #transport_connect, #wrapped_message
#on, #passthrough, #signal
Constructor Details
#initialize(destination, username = nil, password = nil, timeout = 300) ⇒ CachingClient
Returns a new instance of CachingClient.
30
31
32
33
34
35
36
37
|
# File 'lib/clients/caching_client.rb', line 30
def initialize(destination, username=nil, password=nil, timeout=300)
super(destination, username, password)
@timeout = timeout
@query_cache = {}
@cache = {}
@update_thread = nil
@query_methods = self.class.query_methods.clone rescue {}
end
|
Class Attribute Details
.cache_methods ⇒ Object
Returns the value of attribute cache_methods.
12
13
14
|
# File 'lib/clients/caching_client.rb', line 12
def cache_methods
@cache_methods
end
|
.query_methods ⇒ Object
Returns the value of attribute query_methods.
12
13
14
|
# File 'lib/clients/caching_client.rb', line 12
def query_methods
@query_methods
end
|
Instance Attribute Details
#timeout ⇒ Object
Returns the value of attribute timeout.
9
10
11
|
# File 'lib/clients/caching_client.rb', line 9
def timeout
@timeout
end
|
Class Method Details
.cache(name, params = {}, &blk) ⇒ Object
13
14
15
16
17
18
19
|
# File 'lib/clients/caching_client.rb', line 13
def cache(name, params={}, &blk)
@cache_methods ||= {}
@cache_methods[name] = {
params:params,
block:blk
}
end
|
.query(name, params = {}, &blk) ⇒ Object
21
22
23
24
25
26
27
|
# File 'lib/clients/caching_client.rb', line 21
def query(name, params={}, &blk)
@query_methods ||= {}
@query_methods[name] = {
params:params,
block:blk
}
end
|
Instance Method Details
#[](key) ⇒ Object
74
75
76
|
# File 'lib/clients/caching_client.rb', line 74
def [](key)
cache(key)
end
|
#cache(key, sync = false) ⇒ Object
78
79
80
81
82
83
84
85
86
|
# File 'lib/clients/caching_client.rb', line 78
def cache(key, sync=false)
if sync then
refresh unless fresh? else
refresh_async unless fresh? end
@cache[key]
end
|
#dirty ⇒ Object
Force a cache update next time someone makes a request
109
110
111
112
|
# File 'lib/clients/caching_client.rb', line 109
def dirty
@cache_update_ts = nil
@query_methods.each { |method, defn| defn[:update] = nil }
end
|
#ensure_fresh ⇒ Object
114
115
116
|
# File 'lib/clients/caching_client.rb', line 114
def ensure_fresh
refresh unless fresh?
end
|
#fresh? ⇒ Boolean
118
119
120
|
# File 'lib/clients/caching_client.rb', line 118
def fresh?
not timestamp_expired?(@cache_update_ts)
end
|
#query(method, *args) ⇒ Object
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# File 'lib/clients/caching_client.rb', line 88
def query(method, *args)
defn = @query_methods[method]
raise UpdateError, "#{method}: Unsupported method" if defn.nil?
if defn[:params][:authenticate] then
raise(AuthenticationError, "Unable to authenticate as #{username}") unless authenticate_if_needed
end
@query_cache[method] ||= {}
item = @query_cache[method] || {}
return item[:cache] unless timestamp_expired?(item[:update])
request = defn[:block].nil? ? nil : defn[:block].call(*args)
result = update_from_method(method, request)
item[:update] = Time.now
item[:cache] = result
@query_cache[method] = item
result
end
|
#refresh ⇒ Object
138
139
140
141
142
143
144
145
146
147
148
149
|
# File 'lib/clients/caching_client.rb', line 138
def refresh
unless @update_thread.nil? then
@update_thread.join unless @update_thread == Thread.current
return @cache
end
@update_thread = Thread.current
@cache = send_update_request
@cache_update_ts = Time.now
@update_thread = nil
end
|
#refresh_async ⇒ Object
126
127
128
129
130
131
132
133
134
135
136
|
# File 'lib/clients/caching_client.rb', line 126
def refresh_async
if @update_thread.nil? then
begin
Thread.new { refresh }
rescue AuthenticationError, UpdateError => exc
signal(:error, exc.message)
end
end
nil
end
|
#send_update_request ⇒ Object
39
40
41
42
43
44
45
46
47
48
49
50
51
|
# File 'lib/clients/caching_client.rb', line 39
def send_update_request
new_cache = {}
return {} if self.class.cache_methods.nil?
self.class.cache_methods.each do |method, defn|
if defn[:params][:authenticate] then
raise(AuthenticationError, "Unable to authenticate") unless authenticate_if_needed
end
request = defn[:block].nil? ? nil : defn[:block].call
new_cache[method] = update_from_method(method, request)
end
new_cache
end
|
#timestamp_expired?(ts) ⇒ Boolean
122
123
124
|
# File 'lib/clients/caching_client.rb', line 122
def timestamp_expired?(ts)
ts.nil? or (Time.now - ts) > @timeout
end
|
#update_from_method(method, request, type = nil) ⇒ Object
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'lib/clients/caching_client.rb', line 53
def update_from_method(method, request, type=nil)
type ||= talk.expand_name(talk.method_named(method.to_s)[0][:request])
inject_token(request, false, type)
body = request.nil? ? empty_query(method) : wrapped_message(method.to_s, type, request)
result = send_message(body)
begin
parsed = symbolify(JSON.parse(result.body))
raise(UpdateError, "#{method}: #{parsed[:error][:code]} #{parsed[:error][:message]}") unless parsed[:error].nil?
raise(UpdateError, "#{method}: Server did not include a response field") if parsed[:result].nil?
toplevel = parsed[:result]
if toplevel.has_key?(:body) and toplevel.has_key?(:className) then
toplevel = toplevel[:body]
toplevel[:__class] = parsed[:result][:className] end
toplevel
rescue JSON::ParserError
truncated = result.body.length > 100 ? result.body[0..99] + "..." : result.body
raise(UpdateError, "#{method}: Server returned non-JSON response: (#{result.body.length} bytes) '#{truncated}'")
end
end
|