ruby_doozer 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/lib/ruby_doozer.rb +4 -0
- data/lib/ruby_doozer/cached_registry.rb +33 -28
- data/lib/ruby_doozer/json/deserializer.rb +62 -0
- data/lib/ruby_doozer/json/serializer.rb +53 -0
- data/lib/ruby_doozer/registry.rb +80 -76
- data/lib/ruby_doozer/version.rb +1 -1
- data/test/cached_registry_test.rb +19 -6
- data/test/registry_test.rb +8 -2
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb1a71fd888931d010aeffdf2a732c921672a28d
|
4
|
+
data.tar.gz: e31970bb09b093c59ee6e221dd302c4ce1a00d81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8a41f827035cf8a419c4eaa3f95965d6aa390660d6d0af404bd3971bbb7ffaaa0203ffd2bb5ad9e0ee770b9247d3c1425a5faebfe16e2279a63c55b7db46e81
|
7
|
+
data.tar.gz: 24666f05f96fda73696d672ff0d4b1a83b27d0e4ab5dca2248eb0bf3ea50aa2ee7dac854d446dccf1cc792c736231597fe4f4cb81ac2b7731484488523c51846
|
data/Rakefile
CHANGED
data/lib/ruby_doozer.rb
CHANGED
@@ -4,4 +4,8 @@ module RubyDoozer
|
|
4
4
|
autoload :Client, 'ruby_doozer/client'
|
5
5
|
autoload :Registry, 'ruby_doozer/registry'
|
6
6
|
autoload :CachedRegistry, 'ruby_doozer/cached_registry'
|
7
|
+
module Json
|
8
|
+
autoload :Serializer, 'ruby_doozer/json/serializer'
|
9
|
+
autoload :Deserializer, 'ruby_doozer/json/deserializer'
|
10
|
+
end
|
7
11
|
end
|
@@ -10,8 +10,8 @@ require 'semantic_logger'
|
|
10
10
|
#
|
11
11
|
# Notifies registered subscribers when information has changed
|
12
12
|
#
|
13
|
-
# All paths specified are relative to the root_path. As such the root
|
14
|
-
# is never returned, nor is it required when a
|
13
|
+
# All paths specified are relative to the root_path. As such the root key
|
14
|
+
# is never returned, nor is it required when a key is supplied as input.
|
15
15
|
# For example, with a root_path of /foo/bar, any paths passed in will leave
|
16
16
|
# out the root_path: host/name
|
17
17
|
#
|
@@ -23,7 +23,12 @@ module RubyDoozer
|
|
23
23
|
# Logging instance for this class
|
24
24
|
include SemanticLogger::Loggable
|
25
25
|
|
26
|
-
# Create a Registry instance to manage
|
26
|
+
# Create a Registry instance to manage information within doozer
|
27
|
+
# and keep a local cached copy of the data in doozer to support
|
28
|
+
# high-speed or frequent reads.
|
29
|
+
#
|
30
|
+
# Writes are sent to doozer and then replicate back to the local cache
|
31
|
+
# only once doozer has updated its store
|
27
32
|
#
|
28
33
|
# See RubyDoozer::Registry for complete list of options
|
29
34
|
#
|
@@ -31,12 +36,12 @@ module RubyDoozer
|
|
31
36
|
super
|
32
37
|
@cache = ThreadSafe::Hash.new
|
33
38
|
|
34
|
-
|
39
|
+
key = "#{@root}/**"
|
35
40
|
doozer_pool.with_connection do |doozer|
|
36
41
|
@current_revision = doozer.current_revision
|
37
42
|
# Fetch all the configuration information from Doozer and set the internal copy
|
38
|
-
doozer.walk(
|
39
|
-
set_cached_value(
|
43
|
+
doozer.walk(key, @current_revision) do |key, value, revision|
|
44
|
+
set_cached_value(relative_key(key), value)
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
@@ -44,9 +49,9 @@ module RubyDoozer
|
|
44
49
|
monitor_thread
|
45
50
|
end
|
46
51
|
|
47
|
-
# Retrieve the latest value from a specific
|
48
|
-
def [](
|
49
|
-
@cache[
|
52
|
+
# Retrieve the latest value from a specific key from the registry
|
53
|
+
def [](key)
|
54
|
+
@cache[key]
|
50
55
|
end
|
51
56
|
|
52
57
|
# Iterate over every key, value pair in the registry at the root_path
|
@@ -59,8 +64,8 @@ module RubyDoozer
|
|
59
64
|
@cache.dup.each_pair(&block)
|
60
65
|
end
|
61
66
|
|
62
|
-
# Returns [Array<String>] all
|
63
|
-
def
|
67
|
+
# Returns [Array<String>] all keys in the registry
|
68
|
+
def keys
|
64
69
|
@cache.keys
|
65
70
|
end
|
66
71
|
|
@@ -71,26 +76,26 @@ module RubyDoozer
|
|
71
76
|
|
72
77
|
# When an entry is created the block will be called
|
73
78
|
# Parameters
|
74
|
-
#
|
75
|
-
# The relative
|
79
|
+
# key
|
80
|
+
# The relative key to watch for changes
|
76
81
|
# block
|
77
82
|
# The block to be called
|
78
83
|
#
|
79
84
|
# Parameters passed to the block:
|
80
|
-
#
|
81
|
-
# The
|
82
|
-
# Supplying a
|
85
|
+
# key
|
86
|
+
# The key that was created
|
87
|
+
# Supplying a key of '*' means all paths
|
83
88
|
# Default: '*'
|
84
89
|
#
|
85
90
|
# value
|
86
91
|
# New value from doozer
|
87
92
|
#
|
88
93
|
# Example:
|
89
|
-
# registry.on_update do |
|
90
|
-
# puts "#{
|
94
|
+
# registry.on_update do |key, value, revision|
|
95
|
+
# puts "#{key} was created with #{value}"
|
91
96
|
# end
|
92
|
-
def on_create(
|
93
|
-
((@create_subscribers ||= ThreadSafe::Hash.new)[
|
97
|
+
def on_create(key='*', &block)
|
98
|
+
((@create_subscribers ||= ThreadSafe::Hash.new)[key] ||= ThreadSafe::Array.new) << block
|
94
99
|
end
|
95
100
|
|
96
101
|
############################
|
@@ -113,30 +118,30 @@ module RubyDoozer
|
|
113
118
|
@cache[doozer_path]
|
114
119
|
end
|
115
120
|
|
116
|
-
# The
|
117
|
-
def changed(
|
118
|
-
previous_value = get_cached_value(
|
121
|
+
# The key has been added or updated in the registry
|
122
|
+
def changed(key, value, revision)
|
123
|
+
previous_value = get_cached_value(key)
|
119
124
|
|
120
125
|
# Update in memory copy
|
121
|
-
set_cached_value(
|
126
|
+
set_cached_value(key, value)
|
122
127
|
|
123
128
|
# It is an update if we already have a value
|
124
129
|
if previous_value
|
125
130
|
# Call parent which will notify Updated Subscribers
|
126
131
|
super
|
127
132
|
else
|
128
|
-
logger.debug
|
133
|
+
logger.debug "Created: #{key}", value
|
129
134
|
|
130
135
|
return unless @create_subscribers
|
131
136
|
|
132
137
|
# Subscribers to specific paths
|
133
|
-
if subscribers = @create_subscribers[
|
134
|
-
subscribers.each{|subscriber| subscriber.call(
|
138
|
+
if subscribers = @create_subscribers[key]
|
139
|
+
subscribers.each{|subscriber| subscriber.call(key, value, revision)}
|
135
140
|
end
|
136
141
|
|
137
142
|
# Any subscribers for all events?
|
138
143
|
if all_subscribers = @create_subscribers['*']
|
139
|
-
all_subscribers.each{|subscriber| subscriber.call(
|
144
|
+
all_subscribers.each{|subscriber| subscriber.call(key, value, revision)}
|
140
145
|
end
|
141
146
|
end
|
142
147
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'multi_json'
|
3
|
+
module RubyDoozer
|
4
|
+
module Json
|
5
|
+
|
6
|
+
# Deserialize from JSON entries in Doozer
|
7
|
+
module Deserializer
|
8
|
+
def self.deserialize(value)
|
9
|
+
return nil unless value
|
10
|
+
|
11
|
+
if value.strip.start_with?('{') || value.strip.start_with?('[{')
|
12
|
+
symbolize(MultiJson.load(value))
|
13
|
+
else
|
14
|
+
symbolize_string(value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the supplied value symbolized
|
19
|
+
def self.symbolize(v)
|
20
|
+
if v.is_a?(Hash)
|
21
|
+
symbolize_hash(v)
|
22
|
+
elsif v.is_a?(Array)
|
23
|
+
symbolize_array(v)
|
24
|
+
elsif v.is_a?(String)
|
25
|
+
symbolize_string(v)
|
26
|
+
else
|
27
|
+
v
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a new hash updated with keys and values that are strings
|
32
|
+
# starting with ':' are turned into symbols
|
33
|
+
def self.symbolize_hash(hash)
|
34
|
+
h = hash.dup
|
35
|
+
hash.each_pair do |k, v|
|
36
|
+
# Convert values in the hash
|
37
|
+
h[k] = symbolize(v)
|
38
|
+
|
39
|
+
# Convert key to a symbol if it is a symbol string
|
40
|
+
h[k[1..-1].to_sym] = h.delete(k) if k.is_a?(String) && k.start_with?(':')
|
41
|
+
end
|
42
|
+
h
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a new Array with any symbols strings returned as symbols
|
46
|
+
def self.symbolize_array(a)
|
47
|
+
a.collect {|v| symbolize(v)}
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a new string with the string parsed and symbol string converted to a symbol
|
51
|
+
def self.symbolize_string(s)
|
52
|
+
# JSON Parser cannot parse non-hash/array values
|
53
|
+
value = YAML.load(s)
|
54
|
+
# Now check for symbols which are strings starting with ':'
|
55
|
+
value.is_a?(String) && value.start_with?(':') ? value[1..-1].to_sym : value
|
56
|
+
rescue Exception
|
57
|
+
s
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
module RubyDoozer
|
3
|
+
module Json
|
4
|
+
|
5
|
+
# Serialize to JSON for storing in Doozer
|
6
|
+
module Serializer
|
7
|
+
def self.serialize(value)
|
8
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
9
|
+
MultiJson.encode(desymbolize(value))
|
10
|
+
else
|
11
|
+
value.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the supplied value with symbols converted to a string prefixed
|
16
|
+
# with ':'
|
17
|
+
def self.desymbolize(v)
|
18
|
+
if v.is_a?(Hash)
|
19
|
+
desymbolize_hash(v)
|
20
|
+
elsif v.is_a?(Array)
|
21
|
+
desymbolize_array(v)
|
22
|
+
elsif v.is_a?(Symbol)
|
23
|
+
desymbolize_symbol(v)
|
24
|
+
else
|
25
|
+
v.to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a new hash with all symbol keys and values as strings starting with ':'
|
30
|
+
def self.desymbolize_hash(hash)
|
31
|
+
h = hash.dup
|
32
|
+
hash.each_pair do |k, v|
|
33
|
+
# Convert values in the hash
|
34
|
+
h[k] = desymbolize(v)
|
35
|
+
|
36
|
+
# Convert key to a string if it is a symbol
|
37
|
+
h[desymbolize_symbol(k)] = h.delete(k) if k.is_a?(Symbol)
|
38
|
+
end
|
39
|
+
h
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a new Array with any symbols returned as symbol strings
|
43
|
+
def self.desymbolize_array(a)
|
44
|
+
a.collect {|v| desymbolize(v)}
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.desymbolize_symbol(s)
|
48
|
+
":#{s}"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/ruby_doozer/registry.rb
CHANGED
@@ -2,6 +2,7 @@ require 'thread_safe'
|
|
2
2
|
require 'gene_pool'
|
3
3
|
require 'semantic_logger'
|
4
4
|
require 'sync_attr'
|
5
|
+
require 'ruby_doozer/json/deserializer'
|
5
6
|
|
6
7
|
#
|
7
8
|
# Registry
|
@@ -10,10 +11,10 @@ require 'sync_attr'
|
|
10
11
|
#
|
11
12
|
# Notifies registered subscribers when information has changed
|
12
13
|
#
|
13
|
-
# All paths specified are relative to the
|
14
|
-
# is never returned, nor is it required when a
|
15
|
-
# For example, with a
|
16
|
-
# out the
|
14
|
+
# All paths specified are relative to the root. As such the root key
|
15
|
+
# is never returned, nor is it required when a key is supplied as input.
|
16
|
+
# For example, with a root of /foo/bar, any paths passed in will leave
|
17
|
+
# out the root: host/name
|
17
18
|
#
|
18
19
|
module RubyDoozer
|
19
20
|
class Registry
|
@@ -21,13 +22,13 @@ module RubyDoozer
|
|
21
22
|
# Logging instance for this class
|
22
23
|
include SemanticLogger::Loggable
|
23
24
|
|
24
|
-
attr_reader :doozer_config, :doozer_pool, :current_revision, :
|
25
|
+
attr_reader :doozer_config, :doozer_pool, :current_revision, :root
|
25
26
|
|
26
|
-
# Create a Registry instance to manage a
|
27
|
+
# Create a Registry instance to manage a information within doozer
|
27
28
|
#
|
28
|
-
# :
|
29
|
-
# Root
|
30
|
-
# It is not recommended to set the
|
29
|
+
# :root [String]
|
30
|
+
# Root key to load and then monitor for changes
|
31
|
+
# It is not recommended to set the root to "/" as it will generate
|
31
32
|
# significant traffic since it will also monitor Doozer Admin changes
|
32
33
|
# Mandatory
|
33
34
|
#
|
@@ -84,15 +85,15 @@ module RubyDoozer
|
|
84
85
|
#
|
85
86
|
def initialize(params)
|
86
87
|
params = params.dup
|
87
|
-
@
|
88
|
-
raise "Missing mandatory parameter :
|
88
|
+
@root = params.delete(:root) || params.delete(:root_path)
|
89
|
+
raise "Missing mandatory parameter :root" unless @root
|
89
90
|
|
90
|
-
# Add leading '/' to
|
91
|
-
@
|
91
|
+
# Add leading '/' to root if missing
|
92
|
+
@root = "/#{@root}" unless @root.start_with?('/')
|
92
93
|
|
93
94
|
# Strip trailing '/' if supplied
|
94
|
-
@
|
95
|
-
@
|
95
|
+
@root = @root[0..-2] if @root.end_with?("/")
|
96
|
+
@root_with_trail = "#{@root}/"
|
96
97
|
|
97
98
|
@doozer_config = params.delete(:doozer) || {}
|
98
99
|
@doozer_config[:servers] ||= ['127.0.0.1:8046']
|
@@ -102,6 +103,10 @@ module RubyDoozer
|
|
102
103
|
@doozer_config[:connect_retry_count] ||= 10
|
103
104
|
@doozer_config[:server_selector] ||= :random
|
104
105
|
|
106
|
+
# Allow the serializer and deserializer implementations to be replaced
|
107
|
+
@serializer = params.delete(:serializer) || RubyDoozer::Json::Serializer
|
108
|
+
@deserializer = params.delete(:deserializer) || RubyDoozer::Json::Deserializer
|
109
|
+
|
105
110
|
# Connection pool settings
|
106
111
|
@doozer_pool = GenePool.new(
|
107
112
|
:name =>"Doozer Connection Pool",
|
@@ -125,27 +130,28 @@ module RubyDoozer
|
|
125
130
|
end
|
126
131
|
|
127
132
|
# Retrieve the latest value from a specific path from the registry
|
128
|
-
def [](
|
129
|
-
doozer_pool.with_connection do |doozer|
|
130
|
-
doozer[
|
133
|
+
def [](key)
|
134
|
+
value = doozer_pool.with_connection do |doozer|
|
135
|
+
doozer[full_key(key)]
|
131
136
|
end
|
137
|
+
@deserializer.deserialize(value)
|
132
138
|
end
|
133
139
|
|
134
|
-
# Replace the latest value at a specific
|
135
|
-
def []=(
|
140
|
+
# Replace the latest value at a specific key
|
141
|
+
def []=(key,value)
|
136
142
|
doozer_pool.with_connection do |doozer|
|
137
|
-
doozer[
|
143
|
+
doozer[full_key(key)] = @serializer.serialize(value)
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
141
|
-
# Delete the value at a specific
|
142
|
-
def delete(
|
147
|
+
# Delete the value at a specific key
|
148
|
+
def delete(key)
|
143
149
|
doozer_pool.with_connection do |doozer|
|
144
|
-
doozer.delete(
|
150
|
+
doozer.delete(full_key(key))
|
145
151
|
end
|
146
152
|
end
|
147
153
|
|
148
|
-
# Iterate over every key, value pair in the registry at the
|
154
|
+
# Iterate over every key, value pair in the registry at the root
|
149
155
|
#
|
150
156
|
# If :cache was set to false on the initializer this call will
|
151
157
|
# make network calls to doozer to retrieve the current values
|
@@ -154,19 +160,19 @@ module RubyDoozer
|
|
154
160
|
# Example:
|
155
161
|
# registry.each_pair {|k,v| puts "#{k} => #{v}"}
|
156
162
|
def each_pair(&block)
|
157
|
-
|
163
|
+
key = "#{@root}/**"
|
158
164
|
doozer_pool.with_connection do |doozer|
|
159
|
-
doozer.walk(
|
160
|
-
block.call(
|
165
|
+
doozer.walk(key) do |key, value, revision|
|
166
|
+
block.call(relative_key(key), @deserializer.deserialize(value))
|
161
167
|
end
|
162
168
|
end
|
163
169
|
end
|
164
170
|
|
165
|
-
# Returns [Array<String>] all
|
166
|
-
def
|
167
|
-
|
168
|
-
each_pair {|k,v|
|
169
|
-
|
171
|
+
# Returns [Array<String>] all keys in the registry
|
172
|
+
def keys
|
173
|
+
keys = []
|
174
|
+
each_pair {|k,v| keys << k}
|
175
|
+
keys
|
170
176
|
end
|
171
177
|
|
172
178
|
# Returns a copy of the registry as a Hash
|
@@ -189,103 +195,103 @@ module RubyDoozer
|
|
189
195
|
|
190
196
|
# When an entry is updated the block will be called
|
191
197
|
# Parameters
|
192
|
-
#
|
193
|
-
# The relative
|
198
|
+
# key
|
199
|
+
# The relative key to watch for changes
|
194
200
|
# block
|
195
201
|
# The block to be called
|
196
202
|
#
|
197
203
|
# Parameters passed to the block:
|
198
|
-
#
|
199
|
-
# The
|
200
|
-
# Supplying a
|
204
|
+
# key
|
205
|
+
# The key that was updated in doozer
|
206
|
+
# Supplying a key of '*' means all paths
|
201
207
|
# Default: '*'
|
202
208
|
#
|
203
209
|
# value
|
204
210
|
# New value from doozer
|
205
211
|
#
|
206
212
|
# Example:
|
207
|
-
# registry.on_update do |
|
208
|
-
# puts "#{
|
213
|
+
# registry.on_update do |key, value, revision|
|
214
|
+
# puts "#{key} was updated to #{value}"
|
209
215
|
# end
|
210
|
-
def on_update(
|
216
|
+
def on_update(key='*', &block)
|
211
217
|
# Start monitoring thread if not already started
|
212
218
|
monitor_thread
|
213
|
-
((@update_subscribers ||= ThreadSafe::Hash.new)[
|
219
|
+
((@update_subscribers ||= ThreadSafe::Hash.new)[key] ||= ThreadSafe::Array.new) << block
|
214
220
|
end
|
215
221
|
|
216
222
|
# When an entry is deleted the block will be called
|
217
223
|
# Parameters
|
218
|
-
#
|
219
|
-
# The relative
|
224
|
+
# key
|
225
|
+
# The relative key to watch for changes
|
220
226
|
# block
|
221
227
|
# The block to be called
|
222
228
|
#
|
223
229
|
# Parameters passed to the block:
|
224
|
-
#
|
225
|
-
# The
|
226
|
-
# Supplying a
|
230
|
+
# key
|
231
|
+
# The key that was deleted from doozer
|
232
|
+
# Supplying a key of '*' means all paths
|
227
233
|
# Default: '*'
|
228
234
|
#
|
229
235
|
# Example:
|
230
|
-
# registry.on_delete do |
|
231
|
-
# puts "#{
|
236
|
+
# registry.on_delete do |key, revision|
|
237
|
+
# puts "#{key} was deleted"
|
232
238
|
# end
|
233
|
-
def on_delete(
|
239
|
+
def on_delete(key='*', &block)
|
234
240
|
# Start monitoring thread if not already started
|
235
241
|
monitor_thread
|
236
|
-
((@delete_subscribers ||= ThreadSafe::Hash.new)[
|
242
|
+
((@delete_subscribers ||= ThreadSafe::Hash.new)[key] ||= ThreadSafe::Array.new) << block
|
237
243
|
end
|
238
244
|
|
239
245
|
############################
|
240
246
|
protected
|
241
247
|
|
242
|
-
# Returns the full
|
243
|
-
def
|
244
|
-
"#{@
|
248
|
+
# Returns the full key given a relative key
|
249
|
+
def full_key(relative_key)
|
250
|
+
"#{@root}/#{relative_key}"
|
245
251
|
end
|
246
252
|
|
247
|
-
# Returns the full
|
248
|
-
def
|
249
|
-
|
253
|
+
# Returns the full key given a relative key
|
254
|
+
def relative_key(full_key)
|
255
|
+
full_key.sub(@root_with_trail, '')
|
250
256
|
end
|
251
257
|
|
252
|
-
# The
|
253
|
-
def changed(
|
254
|
-
logger.debug
|
258
|
+
# The key has been added or updated in the registry
|
259
|
+
def changed(key, value, revision)
|
260
|
+
logger.debug "Updated: #{key}", value
|
255
261
|
|
256
262
|
return unless @update_subscribers
|
257
263
|
|
258
264
|
# Subscribers to specific paths
|
259
|
-
if subscribers = @update_subscribers[
|
260
|
-
subscribers.each{|subscriber| subscriber.call(
|
265
|
+
if subscribers = @update_subscribers[key]
|
266
|
+
subscribers.each{|subscriber| subscriber.call(key, value, revision)}
|
261
267
|
end
|
262
268
|
|
263
269
|
# Any subscribers for all events?
|
264
270
|
if all_subscribers = @update_subscribers['*']
|
265
|
-
all_subscribers.each{|subscriber| subscriber.call(
|
271
|
+
all_subscribers.each{|subscriber| subscriber.call(key, value, revision)}
|
266
272
|
end
|
267
273
|
end
|
268
274
|
|
269
275
|
# Existing data has been removed from the registry
|
270
|
-
def deleted(
|
271
|
-
logger.debug { "Deleted: #{
|
276
|
+
def deleted(key, revision)
|
277
|
+
logger.debug { "Deleted: #{key}" }
|
272
278
|
|
273
279
|
return unless @delete_subscribers
|
274
280
|
|
275
281
|
# Subscribers to specific paths
|
276
|
-
if subscribers = @delete_subscribers[
|
277
|
-
subscribers.each{|subscriber| subscriber.call(
|
282
|
+
if subscribers = @delete_subscribers[key]
|
283
|
+
subscribers.each{|subscriber| subscriber.call(key, revision)}
|
278
284
|
end
|
279
285
|
|
280
286
|
# Any subscribers for all events?
|
281
287
|
if all_subscribers = @delete_subscribers['*']
|
282
|
-
all_subscribers.each{|subscriber| subscriber.call(
|
288
|
+
all_subscribers.each{|subscriber| subscriber.call(key, revision)}
|
283
289
|
end
|
284
290
|
end
|
285
291
|
|
286
292
|
# Waits for any updates from Doozer and updates the internal service registry
|
287
293
|
def watch_registry
|
288
|
-
watch_path = "#{@
|
294
|
+
watch_path = "#{@root}/**"
|
289
295
|
logger.info "Start monitoring #{watch_path}"
|
290
296
|
# This thread must use its own dedicated doozer connection
|
291
297
|
doozer = RubyDoozer::Client.new(@doozer_config)
|
@@ -299,23 +305,21 @@ module RubyDoozer
|
|
299
305
|
# Update the current_revision with every change notification
|
300
306
|
@current_revision = node.rev
|
301
307
|
|
302
|
-
# Remove the Root
|
303
|
-
|
308
|
+
# Remove the Root key
|
309
|
+
key = relative_key(node.path)
|
304
310
|
|
305
311
|
case node.flags
|
306
312
|
when 4
|
307
|
-
changed(
|
313
|
+
changed(key, @deserializer.deserialize(node.value), node.rev)
|
308
314
|
when 8
|
309
|
-
deleted(
|
315
|
+
deleted(key, node.rev)
|
310
316
|
else
|
311
317
|
logger.error "Unknown flags returned by doozer:#{node.flags}"
|
312
318
|
end
|
313
319
|
end
|
314
320
|
logger.info "Stopping monitoring thread normally"
|
315
321
|
|
316
|
-
|
317
|
-
|
318
|
-
rescue Exception => exc
|
322
|
+
rescue ScriptError, NameError, StandardError, Exception => exc
|
319
323
|
logger.error "Exception in monitoring thread", exc
|
320
324
|
ensure
|
321
325
|
doozer.close if doozer
|
data/lib/ruby_doozer/version.rb
CHANGED
@@ -62,42 +62,55 @@ class CachedRegistryTest < Test::Unit::TestCase
|
|
62
62
|
[nil, '*'].each do |monitor_path|
|
63
63
|
context "with monitor_path:#{monitor_path}" do
|
64
64
|
should "callback on create" do
|
65
|
+
created_revision = nil
|
65
66
|
created_path = nil
|
66
67
|
created_value = nil
|
67
|
-
@registry.on_create(monitor_path||'three') do |path, value|
|
68
|
+
@registry.on_create(monitor_path||'three') do |path, value, revision|
|
69
|
+
created_revision = revision
|
68
70
|
created_path = path
|
69
71
|
created_value = value
|
70
72
|
end
|
71
73
|
@registry['three'] = 'created'
|
72
74
|
# Allow doozer to send back the change
|
73
|
-
sleep 0.
|
75
|
+
sleep 0.3
|
74
76
|
assert_equal 'three', created_path
|
75
77
|
assert_equal 'created', created_value
|
78
|
+
assert_equal true, created_revision > 0
|
76
79
|
end
|
77
80
|
|
78
81
|
should "callback on update" do
|
82
|
+
updated_revision = nil
|
79
83
|
updated_path = nil
|
80
84
|
updated_value = nil
|
81
|
-
@registry.on_update(monitor_path||'bar') do |path, value|
|
85
|
+
@registry.on_update(monitor_path||'bar') do |path, value, revision|
|
86
|
+
updated_revision = revision
|
82
87
|
updated_path = path
|
83
88
|
updated_value = value
|
84
89
|
end
|
90
|
+
# Allow monitoring thread to start
|
91
|
+
sleep 0.1
|
85
92
|
@registry['bar'] = 'updated'
|
86
93
|
# Allow doozer to send back the change
|
87
|
-
sleep 0.
|
94
|
+
sleep 0.3
|
88
95
|
assert_equal 'bar', updated_path
|
89
96
|
assert_equal 'updated', updated_value
|
97
|
+
assert_equal true, updated_revision > 0
|
90
98
|
end
|
91
99
|
|
92
100
|
should "callback on delete" do
|
93
101
|
deleted_path = nil
|
94
|
-
|
102
|
+
deleted_revision = nil
|
103
|
+
@registry.on_delete(monitor_path||'bar') do |path, revision|
|
95
104
|
deleted_path = path
|
105
|
+
deleted_revision = revision
|
96
106
|
end
|
107
|
+
# Allow monitoring thread to start
|
108
|
+
sleep 0.1
|
97
109
|
# Allow doozer to send back the change
|
98
110
|
@registry.delete('bar')
|
99
|
-
sleep 0.
|
111
|
+
sleep 0.3
|
100
112
|
assert_equal 'bar', deleted_path
|
113
|
+
assert_equal true, deleted_revision > 0
|
101
114
|
end
|
102
115
|
end
|
103
116
|
end
|
data/test/registry_test.rb
CHANGED
@@ -65,9 +65,11 @@ class RegistryTest < Test::Unit::TestCase
|
|
65
65
|
[nil, '*'].each do |monitor_path|
|
66
66
|
context "with monitor_path:#{monitor_path}" do
|
67
67
|
should "callback on update" do
|
68
|
+
updated_revision = nil
|
68
69
|
updated_path = nil
|
69
70
|
updated_value = nil
|
70
|
-
@registry.on_update(monitor_path||'bar') do |path, value|
|
71
|
+
@registry.on_update(monitor_path||'bar') do |path, value, revision|
|
72
|
+
updated_revision = revision
|
71
73
|
updated_path = path
|
72
74
|
updated_value = value
|
73
75
|
end
|
@@ -78,12 +80,15 @@ class RegistryTest < Test::Unit::TestCase
|
|
78
80
|
sleep 0.3
|
79
81
|
assert_equal 'bar', updated_path
|
80
82
|
assert_equal 'updated', updated_value
|
83
|
+
assert_equal true, updated_revision > 0
|
81
84
|
end
|
82
85
|
|
83
86
|
should "callback on delete" do
|
84
87
|
deleted_path = nil
|
85
|
-
|
88
|
+
deleted_revision = nil
|
89
|
+
@registry.on_delete(monitor_path||'bar') do |path, revision|
|
86
90
|
deleted_path = path
|
91
|
+
deleted_revision = revision
|
87
92
|
end
|
88
93
|
# Allow monitoring thread to start
|
89
94
|
sleep 0.1
|
@@ -91,6 +96,7 @@ class RegistryTest < Test::Unit::TestCase
|
|
91
96
|
@registry.delete('bar')
|
92
97
|
sleep 0.3
|
93
98
|
assert_equal 'bar', deleted_path
|
99
|
+
assert_equal true, deleted_revision > 0
|
94
100
|
end
|
95
101
|
end
|
96
102
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_doozer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-04-
|
11
|
+
date: 2013-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: semantic_logger
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: multi_json
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.6.1
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.6.1
|
83
97
|
description: Ruby Client for doozer
|
84
98
|
email:
|
85
99
|
- reidmo@gmail.com
|
@@ -96,6 +110,8 @@ files:
|
|
96
110
|
- lib/ruby_doozer/cached_registry.rb
|
97
111
|
- lib/ruby_doozer/client.rb
|
98
112
|
- lib/ruby_doozer/exceptions.rb
|
113
|
+
- lib/ruby_doozer/json/deserializer.rb
|
114
|
+
- lib/ruby_doozer/json/serializer.rb
|
99
115
|
- lib/ruby_doozer/msg.pb.rb
|
100
116
|
- lib/ruby_doozer/registry.rb
|
101
117
|
- lib/ruby_doozer/version.rb
|