ruby_skynet 0.8.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,75 @@
1
+ require 'thread_safe'
2
+ require 'semantic_logger'
3
+ require 'ruby_skynet/zookeeper/registry'
4
+
5
+ #
6
+ # CachedRegistry
7
+ #
8
+ # Store information in ZooKeeper and subscribe to future changes
9
+ # and keep a local copy of the information in ZooKeeper
10
+ #
11
+ # Notifies registered subscribers when information has changed
12
+ #
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
+ # For example, with a root_path of /foo/bar, any paths passed in will leave
16
+ # out the root_path: host/name
17
+ #
18
+ # Keeps a local copy in memory of all descendant values of the supplied root_path
19
+ # Supports high-frequency calls to retrieve registry data
20
+ # The in-memory cache will be kept in synch with any changes on the server
21
+ module RubySkynet
22
+ module Zookeeper
23
+ class CachedRegistry < Registry
24
+ # Logging instance for this class
25
+ include SemanticLogger::Loggable
26
+
27
+ # Create a CachedRegistry instance to manage information within the Registry
28
+ # and keep a local cached copy of the data in the Registry to support
29
+ # high-speed or frequent reads.
30
+ #
31
+ # Writes are sent to ZooKeeper and then replicated back to the local cache
32
+ # only once ZooKeeper has updated its store
33
+ #
34
+ # See RubySkynet::Zookeeper::Registry for the complete list of options
35
+ #
36
+ def initialize(params)
37
+ @cache = ThreadSafe::Hash.new
38
+ # Supplied block to load the current keys from the Registry
39
+ super(params) do |key, value, version|
40
+ @cache[key] = value
41
+ end
42
+
43
+ on_create {|key, value| @cache[key] = value}
44
+ on_update {|key, value, version| @cache[key] = value}
45
+ on_delete {|key| @cache.delete(key)}
46
+ end
47
+
48
+ # Retrieve the latest value from a specific key from the registry
49
+ def [](key)
50
+ @cache[key]
51
+ end
52
+
53
+ # Iterate over every key, value pair in the registry at the root_path
54
+ #
55
+ # Example:
56
+ # registry.each_pair {|k,v| puts "#{k} => #{v}"}
57
+ def each_pair(&block)
58
+ # Have to duplicate the cache otherwise concurrent changes to the
59
+ # registry will interfere with the iterator
60
+ @cache.dup.each_pair(&block)
61
+ end
62
+
63
+ # Returns [Array<String>] all keys in the registry
64
+ def keys
65
+ @cache.keys
66
+ end
67
+
68
+ # Returns a copy of the registry as a Hash
69
+ def to_h
70
+ @cache.dup
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,27 @@
1
+ # This monkey-patch must be removed when ticket #44 has been included in
2
+ # an updated ZooKeeper Gem
3
+ # Ticket: https://github.com/slyphon/zookeeper/issues/44
4
+ # Pull Request: https://github.com/slyphon/zookeeper/pull/45
5
+
6
+ module Zookeeper
7
+ class JavaBase
8
+
9
+ def get(req_id, path, callback, watcher)
10
+ handle_keeper_exception do
11
+ watch_cb = watcher ? create_watcher(req_id, path) : false
12
+
13
+ if callback
14
+ jzk.getData(path, watch_cb, JavaCB::DataCallback.new(req_id), event_queue)
15
+ [Code::Ok, nil, nil] # the 'nil, nil' isn't strictly necessary here
16
+ else # sync
17
+ stat = JZKD::Stat.new
18
+ value = jzk.getData(path, watch_cb, stat)
19
+ data = String.from_java_bytes(value) unless value.nil?
20
+
21
+ [Code::Ok, data, stat.to_hash]
22
+ end
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ require 'yaml'
2
+ require 'multi_json'
3
+ module RubySkynet
4
+ module Zookeeper
5
+ module Json
6
+
7
+ # Deserialize from JSON entries in Zookeeper
8
+ module Deserializer
9
+ def self.deserialize(value)
10
+ return value if value.nil? || (value == '')
11
+
12
+ if value.strip.start_with?('{') || value.strip.start_with?('[{')
13
+ symbolize(MultiJson.load(value))
14
+ else
15
+ symbolize_string(value)
16
+ end
17
+ end
18
+
19
+ # Returns the supplied value symbolized
20
+ def self.symbolize(v)
21
+ if v.is_a?(Hash)
22
+ symbolize_hash(v)
23
+ elsif v.is_a?(Array)
24
+ symbolize_array(v)
25
+ elsif v.is_a?(String)
26
+ symbolize_string(v)
27
+ else
28
+ v
29
+ end
30
+ end
31
+
32
+ # Returns a new hash updated with keys and values that are strings
33
+ # starting with ':' are turned into symbols
34
+ def self.symbolize_hash(hash)
35
+ h = hash.dup
36
+ hash.each_pair do |k, v|
37
+ # Convert values in the hash
38
+ h[k] = symbolize(v)
39
+
40
+ # Convert key to a symbol if it is a symbol string
41
+ h[k[1..-1].to_sym] = h.delete(k) if k.is_a?(String) && k.start_with?(':')
42
+ end
43
+ h
44
+ end
45
+
46
+ # Returns a new Array with any symbols strings returned as symbols
47
+ def self.symbolize_array(a)
48
+ a.collect {|v| symbolize(v)}
49
+ end
50
+
51
+ # Returns a new string with the string parsed and symbol string converted to a symbol
52
+ def self.symbolize_string(s)
53
+ # JSON Parser cannot parse non-hash/array values
54
+ value = YAML.load(s)
55
+ # Now check for symbols which are strings starting with ':'
56
+ value.is_a?(String) && value.start_with?(':') ? value[1..-1].to_sym : value
57
+ rescue Exception
58
+ s
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,57 @@
1
+ require 'multi_json'
2
+ module RubySkynet
3
+ module Zookeeper
4
+ module Json
5
+
6
+ # Serialize to JSON for storing in Doozer
7
+ module Serializer
8
+ def self.serialize(value)
9
+ if value.is_a?(Hash) || value.is_a?(Array)
10
+ MultiJson.encode(desymbolize(value))
11
+ elsif value.is_a?(Symbol)
12
+ desymbolize_symbol(value)
13
+ else
14
+ value.to_s
15
+ end
16
+ end
17
+
18
+ # Returns the supplied value with symbols converted to a string prefixed
19
+ # with ':'
20
+ def self.desymbolize(v)
21
+ if v.is_a?(Hash)
22
+ desymbolize_hash(v)
23
+ elsif v.is_a?(Array)
24
+ desymbolize_array(v)
25
+ elsif v.is_a?(Symbol)
26
+ desymbolize_symbol(v)
27
+ else
28
+ v.to_s
29
+ end
30
+ end
31
+
32
+ # Returns a new hash with all symbol keys and values as strings starting with ':'
33
+ def self.desymbolize_hash(hash)
34
+ h = hash.dup
35
+ hash.each_pair do |k, v|
36
+ # Convert values in the hash
37
+ h[k] = desymbolize(v)
38
+
39
+ # Convert key to a string if it is a symbol
40
+ h[desymbolize_symbol(k)] = h.delete(k) if k.is_a?(Symbol)
41
+ end
42
+ h
43
+ end
44
+
45
+ # Returns a new Array with any symbols returned as symbol strings
46
+ def self.desymbolize_array(a)
47
+ a.collect {|v| desymbolize(v)}
48
+ end
49
+
50
+ def self.desymbolize_symbol(s)
51
+ ":#{s}"
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+ end