celluloid-presence 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.textile +51 -0
- data/Rakefile +10 -0
- data/lib/celluloid-presence/presence.rb +162 -0
- data/lib/celluloid-presence/service.rb +160 -0
- data/lib/celluloid-presence/version.rb +6 -0
- data/lib/celluloid-presence.rb +3 -0
- data/lib/dcell/registries/zk_presence_adapter.rb +152 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 83c3287a94c2f820bab2be50041e10183562379d
|
4
|
+
data.tar.gz: 5e94a2416dcaca6535a64291eb525b5117a8d338
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c90b5508fc1281b5f3713b87c9a980b89e9e46728db5efdd53ca782fe10393c560d78901a0b0707fcb154d6eb0320b314f4e84edaf81790e8296583210821eff
|
7
|
+
data.tar.gz: 979c29216afcd3a3d958f8ee6625cfb91e7bcedb47d45d75ffad5675e0b2de0a9a9ff82d9091552c1e14ebe129bc1e51917dd6fe70f0d10a7aa8d514029356bb
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
h1. Celluloid Presence
|
2
|
+
|
3
|
+
Start an instance of "ZooKeeper":http://zookeeper.apache.org/ on your server then run:
|
4
|
+
* OSX:
|
5
|
+
*
|
6
|
+
|
7
|
+
<pre><code class="ruby">
|
8
|
+
require 'rubygems'
|
9
|
+
require 'celluloid-presence'
|
10
|
+
|
11
|
+
Celluloid::Presence::ZkService.init :server => 'localhost'
|
12
|
+
Celluloid::Presence::ZkPresence.supervise_as :presence, :service_name => :presence
|
13
|
+
|
14
|
+
class Messaging
|
15
|
+
include Celluloid
|
16
|
+
include Celluloid::Notifications
|
17
|
+
|
18
|
+
def self.finalizer
|
19
|
+
:finalize
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(service_name)
|
23
|
+
@service_name = service_name
|
24
|
+
subscribe("#{@service_name}_nodes", :node_update)
|
25
|
+
end
|
26
|
+
|
27
|
+
def node_update(event, nodes)
|
28
|
+
p "\nNode list updated!"
|
29
|
+
nodes.each do |node|
|
30
|
+
p " -> #{Actor[@service_name].get(node)}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
|
38
|
+
def finalize
|
39
|
+
Actor[@service_name].terminate
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Messaging.run(:presence)
|
44
|
+
</code></pre>
|
45
|
+
|
46
|
+
|
47
|
+
h2. Start using it now
|
48
|
+
|
49
|
+
# Read the "Documentation":http://rubydoc.info/gems/celluloid-promise/Celluloid/Presence
|
50
|
+
# Then @gem install celluloid-presence@
|
51
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
module Presence
|
5
|
+
class ZkPresence
|
6
|
+
include Celluloid
|
7
|
+
include Celluloid::Notifications
|
8
|
+
|
9
|
+
PREFIX ||= '/coPresence'
|
10
|
+
NODE_PREFIX ||= 'node-'
|
11
|
+
|
12
|
+
|
13
|
+
def self.finalizer
|
14
|
+
:finalize
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
@env = options[:env] || 'production'
|
20
|
+
@base_path = options[:service_name].nil? ? "#{PREFIX}/#{@env}/default" : "#{PREFIX}/#{@env}/#{options[:service_name]}"
|
21
|
+
@base_path_sym = @base_path.to_sym
|
22
|
+
@node_path = nil # This is officially set in connect_setup
|
23
|
+
@service_name = options[:service_name] || :default
|
24
|
+
@nodes = []
|
25
|
+
|
26
|
+
if options[:node_address].nil?
|
27
|
+
use_ip_v4 = !options[:ip_v6] # IP v6 or IP v4 if using the default node data
|
28
|
+
@node_address = proc { ip_address(use_ip_v4) }
|
29
|
+
else
|
30
|
+
node_address = options[:node_address]
|
31
|
+
@node_address = proc { node_address.is_a?(Proc) ? node_address.call : node_address }
|
32
|
+
end
|
33
|
+
@last_known_address = nil
|
34
|
+
|
35
|
+
#
|
36
|
+
# These callbacks will be executed on a seperate thread
|
37
|
+
# Which is why we need to use notifications update state
|
38
|
+
#
|
39
|
+
zk.register(@base_path)
|
40
|
+
subscribe("zk_event_#{@base_path}", :zk_callback)
|
41
|
+
subscribe('zk_connected', :on_connected)
|
42
|
+
subscribe('zk_connecting', :on_connecting)
|
43
|
+
|
44
|
+
on_connected if zk.connected?
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
#
|
49
|
+
# Provides the list of known nodes
|
50
|
+
#
|
51
|
+
attr_reader :nodes
|
52
|
+
|
53
|
+
|
54
|
+
#
|
55
|
+
# This informs us of changes to the list of base path's children
|
56
|
+
#
|
57
|
+
def zk_callback(event_name, event)
|
58
|
+
#p "EVENT OCUURED #{event.event_name} #{event.path}"
|
59
|
+
if event.node_child? # We are only listening to child events so we only need to handle these
|
60
|
+
begin
|
61
|
+
@nodes = zk.children(@base_path, :watch => true) # re-set watch
|
62
|
+
update_node_information
|
63
|
+
rescue ZK::Exceptions::NoNode # Technically this shouldn't happen unless someone deleted our base path
|
64
|
+
on_connected if zk.connected?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# This informs us of a new connection being established with zookeeper
|
71
|
+
#
|
72
|
+
def on_connected(event = nil)
|
73
|
+
address = @node_address.call
|
74
|
+
if @node_path.nil? or not zk.exists?(@node_path) # Create presence node as it doesn't exist
|
75
|
+
#p 'node re-created'
|
76
|
+
@last_known_address = address
|
77
|
+
connect_setup
|
78
|
+
elsif @last_known_address != address # Recreate existing presence node as our IP changed
|
79
|
+
#p 'node ip_changed, recreating'
|
80
|
+
zk.async.ensure(:delete, @node_path)
|
81
|
+
@last_known_address = address
|
82
|
+
connect_setup
|
83
|
+
else # Else our node presence information is accurate, lets get the latest list
|
84
|
+
@nodes = zk.children(@base_path, :watch => true)
|
85
|
+
end
|
86
|
+
|
87
|
+
update_node_information # inform listeners of a node list update
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# This informs us that we've been disconnected from zookeeper
|
92
|
+
#
|
93
|
+
def on_connecting event
|
94
|
+
publish("#{@service_name}_nodes_stale")
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Returns the value of a node
|
99
|
+
#
|
100
|
+
def get(node_id)
|
101
|
+
result, _ = zk.get("#{@base_path}/#{node_id}")
|
102
|
+
result
|
103
|
+
rescue ZK::Exceptions::NoNode
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Returns the name of this node
|
108
|
+
#
|
109
|
+
def name
|
110
|
+
@node_path.split('/')[-1]
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
|
117
|
+
#
|
118
|
+
# Shortcut to the zookeeper service
|
119
|
+
#
|
120
|
+
def zk
|
121
|
+
Actor[:zk_service]
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# creates the presence node
|
126
|
+
#
|
127
|
+
def connect_setup
|
128
|
+
zk.mkdir_p @base_path
|
129
|
+
@node_path = zk.create "#{@base_path}/#{NODE_PREFIX}", @last_known_address, :sequence => true, :ephemeral => true
|
130
|
+
@nodes = zk.children @base_path, :watch => true
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Pushes an updated node list to subscribers
|
135
|
+
#
|
136
|
+
def update_node_information
|
137
|
+
publish("#{@service_name}_nodes", @nodes)
|
138
|
+
end
|
139
|
+
|
140
|
+
#
|
141
|
+
# Grabs a valid IP address
|
142
|
+
#
|
143
|
+
def ip_address(ip_v4)
|
144
|
+
ip = if ip_v4
|
145
|
+
Socket.ip_address_list.detect {|a| a.ipv4? && !a.ipv4_loopback?}
|
146
|
+
else
|
147
|
+
Socket.ip_address_list.detect {|a| !a.ipv4? && !(a.ipv6_linklocal? || a.ipv6_loopback?)}
|
148
|
+
end
|
149
|
+
return ip.ip_address unless ip.nil?
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# On termination make sure zookeeper is updated
|
155
|
+
#
|
156
|
+
def finalize
|
157
|
+
zk.async.unregister(@base_path)
|
158
|
+
zk.async.ensure(:delete, @node_path) unless @node_path.nil?
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'zk'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
module Presence
|
5
|
+
class ZkService
|
6
|
+
include Celluloid
|
7
|
+
include Celluloid::Notifications
|
8
|
+
|
9
|
+
DEFAULT_PORT ||= 2181
|
10
|
+
@@zk ||= nil # The single zookeeper instance
|
11
|
+
@@registry ||= {} # Paths we are interested in receiving events from
|
12
|
+
@@registry_count ||= {} # Listener counts (for unregistering)
|
13
|
+
@@ensure ||= [] # Tasks we want to ensure are completed (even when disconnected)
|
14
|
+
@@connected ||= false # We'll maintain our own connected state
|
15
|
+
|
16
|
+
|
17
|
+
#
|
18
|
+
# Optional init function to supervise this actor
|
19
|
+
#
|
20
|
+
def self.init(options)
|
21
|
+
ZkService.supervise_as :zk_service, options
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create a single connection to Zookeeper that persists through Actor crashes
|
25
|
+
#
|
26
|
+
# servers: a list of Zookeeper servers to connect to. Each server in the
|
27
|
+
# list has a host/port configuration
|
28
|
+
def initialize(options)
|
29
|
+
@@zk ||= begin
|
30
|
+
Fanout.supervise_as :notifications_fanout if Actor[:notifications_fanout].nil?
|
31
|
+
|
32
|
+
# Let them specify a single server instead of many
|
33
|
+
servers = options[:server].nil? ? options[:servers] : [options[:server]]
|
34
|
+
raise "no Zookeeper servers given" unless servers
|
35
|
+
|
36
|
+
# Add the default Zookeeper port unless specified
|
37
|
+
servers.map! do |server|
|
38
|
+
if server[/:\d+$/]
|
39
|
+
server
|
40
|
+
else
|
41
|
+
"#{server}:#{DEFAULT_PORT}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
ZK.new(*servers) do |zk|
|
46
|
+
zk.on_connecting &proc { Actor[:zk_service].async.on_connecting }
|
47
|
+
zk.on_connected &proc { Actor[:zk_service].async.on_connected }
|
48
|
+
end
|
49
|
+
end.tap do |zk|
|
50
|
+
@@connected = zk.connected?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Called once a connection is made to the zookeeper cluster
|
56
|
+
# Runs any impending ensures before informing any subscribed actors
|
57
|
+
#
|
58
|
+
def on_connected
|
59
|
+
@@connected = true
|
60
|
+
while not @@ensure.empty?
|
61
|
+
func = @@ensure.shift
|
62
|
+
ensured func[0], *func[1] # func[0] == function name, func[1] == arguments
|
63
|
+
end
|
64
|
+
publish('zk_connected')
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Called on disconnect from zookeeper
|
69
|
+
# Might be that the zookeeper node crashed or zookeeper is down, may not effect any other connections
|
70
|
+
#
|
71
|
+
def on_connecting
|
72
|
+
@@connected = false
|
73
|
+
publish('zk_connecting')
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Publishes any zookeeper events that have been registered
|
78
|
+
#
|
79
|
+
def event_callback(path, event)
|
80
|
+
publish("zk_event_#{path}", event)
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Uses a closure to cleanly pull the zookeeper event back into the protection of celluloid
|
85
|
+
#
|
86
|
+
def register(path)
|
87
|
+
path = path.to_sym
|
88
|
+
if @@registry[path].nil?
|
89
|
+
callback = proc { |event| Actor[:zk_service].async.event_callback(path, event) }
|
90
|
+
@@registry[path] = @@zk.register(path.to_s, &callback)
|
91
|
+
end
|
92
|
+
@@registry_count[path] = (@@registry_count[path] || 0) + 1
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# unsubscribes from zookeeper events once there are no more listeners
|
97
|
+
#
|
98
|
+
def unregister(path)
|
99
|
+
path = path.to_sym
|
100
|
+
if @@registry[path]
|
101
|
+
@@registry_count[path] -= 1
|
102
|
+
if @@registry_count[path] <= 0
|
103
|
+
sub = @@registry.delete(path)
|
104
|
+
sub.unsubscribe
|
105
|
+
@@registry_count.delete(path)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Our abstracted connected status to avoid race conditions
|
112
|
+
#
|
113
|
+
def connected?
|
114
|
+
@@connected
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Ensures important requests are followed through in the case of disconnect / reconnect
|
119
|
+
# Ignores request if the node does not exist
|
120
|
+
# USE SPARINGLY
|
121
|
+
#
|
122
|
+
def ensure(func, *args)
|
123
|
+
if connected?
|
124
|
+
ensured(func, *args)
|
125
|
+
else
|
126
|
+
@@ensure.push [func, args]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
#
|
132
|
+
# Proxy the following functions
|
133
|
+
#
|
134
|
+
# Automatically creates a callable function for each command
|
135
|
+
# http://blog.jayfields.com/2007/10/ruby-defining-class-methods.html
|
136
|
+
# http://blog.jayfields.com/2008/02/ruby-dynamically-define-method.html
|
137
|
+
#
|
138
|
+
SAFE_OPS ||= [:get, :children, :create, :mkdir_p, :delete, :stat, :exists?, :set, :rm_rf]
|
139
|
+
SAFE_OPS.each do |func|
|
140
|
+
define_method func do |*args|
|
141
|
+
begin
|
142
|
+
@@zk.send func, *args if connected?
|
143
|
+
rescue Zookeeper::Exceptions::NotConnected
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
|
152
|
+
def ensured(func, *args)
|
153
|
+
@@zk.send func, *args
|
154
|
+
rescue Zookeeper::Exceptions::NotConnected
|
155
|
+
@@ensure << [func, args]
|
156
|
+
rescue ZK::Exceptions::NoNode
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'celluloid-presence'
|
2
|
+
|
3
|
+
|
4
|
+
module DCell
|
5
|
+
module Registry
|
6
|
+
class ZkPresenceAdapter
|
7
|
+
def initialize(options)
|
8
|
+
Celluloid::Presence::ZkService.init options
|
9
|
+
|
10
|
+
@node_registry = NodeRegistry.new(options)
|
11
|
+
@global_registry = GlobalRegistry.new(:zk_service, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
class NodeRegistry
|
16
|
+
include Celluloid
|
17
|
+
include Celluloid::Notifications
|
18
|
+
|
19
|
+
def initialize(options)
|
20
|
+
@mutex = Mutex.new
|
21
|
+
@current_address = nil
|
22
|
+
|
23
|
+
Celluloid::Presence::ZkPresence.supervise_as :dcell_presence, {
|
24
|
+
:service_name => :dcell_presence,
|
25
|
+
:node_address => proc { @mutex.synchronize { @current_address } },
|
26
|
+
:env => options[:env] || 'production'
|
27
|
+
}
|
28
|
+
|
29
|
+
@service_name = :dcell_presence
|
30
|
+
@directory = {} # node_name => address
|
31
|
+
@mapping = {} # zk_path => node_name
|
32
|
+
|
33
|
+
subscribe("#{@service_name}_nodes", :node_update)
|
34
|
+
|
35
|
+
@nodes = []
|
36
|
+
update_directory(presence.nodes)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get(node_id)
|
40
|
+
@directory[node_id]
|
41
|
+
end
|
42
|
+
|
43
|
+
def nodes
|
44
|
+
@directory.keys
|
45
|
+
end
|
46
|
+
|
47
|
+
def node_update(event, nodes)
|
48
|
+
update_directory(nodes)
|
49
|
+
end
|
50
|
+
|
51
|
+
def set(node_id, addr)
|
52
|
+
@mutex.synchronize {
|
53
|
+
@current_address = Marshal.dump [node_id, addr]
|
54
|
+
}
|
55
|
+
presence.on_connected # This causes an address update on zookeeper
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
|
62
|
+
def update_directory(new_list)
|
63
|
+
unsubscribe = @nodes - new_list # TODO:: use sets here instead of arrays for speed
|
64
|
+
subscribe = new_list - @nodes
|
65
|
+
|
66
|
+
unsubscribe.each do |node|
|
67
|
+
node_name = @mapping.delete(node)
|
68
|
+
@directory.delete(node_name)
|
69
|
+
end
|
70
|
+
|
71
|
+
subscribe.each do |node|
|
72
|
+
value = presence.get(node)
|
73
|
+
if value.nil?
|
74
|
+
@nodes.delete value
|
75
|
+
else
|
76
|
+
begin
|
77
|
+
info = Marshal.load value
|
78
|
+
@mapping[node] = info[0]
|
79
|
+
@directory[info[0]] = info[1]
|
80
|
+
rescue
|
81
|
+
@nodes.delete value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
@nodes = new_list
|
87
|
+
end
|
88
|
+
|
89
|
+
def presence
|
90
|
+
::Celluloid::Actor[@service_name]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def clear_nodes; end # This is now self maintaining hence no op
|
95
|
+
def get_node(node_id); @node_registry.get(node_id) end
|
96
|
+
def nodes; @node_registry.nodes end
|
97
|
+
def set_node(node_id, addr); @node_registry.set(node_id, addr) end
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
class GlobalRegistry
|
102
|
+
PREFIX = "/dcell_global"
|
103
|
+
|
104
|
+
def initialize(service_name, options)
|
105
|
+
options = options.inject({}) { |h,(k,v)| h[k.to_s] = v; h }
|
106
|
+
|
107
|
+
@service_name = service_name
|
108
|
+
@env = options['env'] || 'production'
|
109
|
+
@base_path = "#{PREFIX}/#{@env}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def get(key)
|
113
|
+
value, _ = zk.get "#{@base_path}/#{key}"
|
114
|
+
Marshal.load value
|
115
|
+
rescue ZK::Exceptions::NoNode
|
116
|
+
end
|
117
|
+
|
118
|
+
# Set a global value
|
119
|
+
def set(key, value)
|
120
|
+
path = "#{@base_path}/#{key}"
|
121
|
+
string = Marshal.dump value
|
122
|
+
|
123
|
+
zk.set path, string
|
124
|
+
rescue ZK::Exceptions::NoNode
|
125
|
+
zk.create path, string
|
126
|
+
end
|
127
|
+
|
128
|
+
# The keys to all globals in the system
|
129
|
+
def global_keys
|
130
|
+
zk.children(@base_path)
|
131
|
+
end
|
132
|
+
|
133
|
+
def clear
|
134
|
+
zk.rm_rf @base_path
|
135
|
+
zk.mkdir_p @base_path
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def zk
|
141
|
+
Celluloid::Actor[@service_name]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
def clear_globals; @global_registry.clear end
|
147
|
+
def get_global(key); @global_registry.get(key) end
|
148
|
+
def set_global(key, value); @global_registry.set(key, value) end
|
149
|
+
def global_keys; @global_registry.global_keys end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: celluloid-presence
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen von Takach
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-03-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: celluloid
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Node presence using ZooKeeper for celluloid services
|
42
|
+
email:
|
43
|
+
- steve@cotag.me
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/celluloid-presence/presence.rb
|
49
|
+
- lib/celluloid-presence/service.rb
|
50
|
+
- lib/celluloid-presence/version.rb
|
51
|
+
- lib/celluloid-presence.rb
|
52
|
+
- lib/dcell/registries/zk_presence_adapter.rb
|
53
|
+
- MIT-LICENSE
|
54
|
+
- Rakefile
|
55
|
+
- README.textile
|
56
|
+
homepage: https://github.com/cotag/celluloid-presence
|
57
|
+
licenses: []
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.0.0
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: Node presence using ZooKeeper for celluloid services
|
79
|
+
test_files: []
|