Class: Celluloid::Presence::ZkPresence

Inherits:
Object
  • Object
show all
Includes:
Celluloid, Notifications
Defined in:
lib/celluloid-presence/presence.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ZkPresence

Returns a new instance of ZkPresence.



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
# File 'lib/celluloid-presence/presence.rb', line 18

def initialize(options = {})
	@env = options[:env] || 'production'
	@base_path = options[:service_name].nil? ? "#{PREFIX}/#{@env}/default" : "#{PREFIX}/#{@env}/#{options[:service_name]}"
	@base_path_sym = @base_path.to_sym
	@node_path = nil	# This is officially set in connect_setup
	@service_name = options[:service_name] || :default
	@nodes = []
		
	if options[:node_address].nil?
		use_ip_v4 = !options[:ip_v6]		# IP v6 or IP v4 if using the default node data
		@node_address = proc { ip_address(use_ip_v4) }
	else
		node_address = options[:node_address]
		@node_address = proc { node_address.is_a?(Proc) ? node_address.call : node_address }
	end
	@last_known_address = nil
		
	#
	# These callbacks will be executed on a seperate thread
	# Which is why we need to use notifications update state
	#
	zk.register(@base_path)
	subscribe("zk_event_#{@base_path}", :zk_callback)
	subscribe('zk_connected', :on_connected)
	subscribe('zk_connecting', :on_connecting)
	
	on_connected
end

Instance Attribute Details

#nodesObject (readonly)

Provides the list of known nodes



51
52
53
# File 'lib/celluloid-presence/presence.rb', line 51

def nodes
  @nodes
end

Class Method Details

.finalizerObject



13
14
15
# File 'lib/celluloid-presence/presence.rb', line 13

def self.finalizer
	:finalize
end

Instance Method Details

#get(node_id) ⇒ Object

Returns the value of a node



102
103
104
105
106
# File 'lib/celluloid-presence/presence.rb', line 102

def get(node_id)
	result, _ = zk.get("#{@base_path}/#{node_id}")
	result
rescue ZK::Exceptions::NoNode
end

#nameObject

Returns the name of this node



111
112
113
# File 'lib/celluloid-presence/presence.rb', line 111

def name
	@node_path.split('/')[-1]
end

#on_connected(event = nil) ⇒ Object

This informs us of a new connection being established with zookeeper



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/celluloid-presence/presence.rb', line 72

def on_connected(event = nil)
	return unless zk.connected?
	
	address = @node_address.call
	if @node_path.nil? or not zk.exists?(@node_path)	# Create presence node as it doesn't exist
		#p 'node re-created'
		@last_known_address = address
		connect_setup
	elsif @last_known_address != address		# Recreate existing presence node as our IP changed
		#p 'node ip_changed, recreating'
		zk.async.ensure(:delete, @node_path)
		@last_known_address = address
		connect_setup
	else												# Else our node presence information is accurate, lets get the latest list
		@nodes = zk.children(@base_path, :watch => true)
	end
	
	update_node_information								# inform listeners of a node list update
end

#on_connecting(event) ⇒ Object

This informs us that we’ve been disconnected from zookeeper



95
96
97
# File 'lib/celluloid-presence/presence.rb', line 95

def on_connecting event
	publish("#{@service_name}_nodes_stale")
end

#zk_callback(event_name, event) ⇒ Object

This informs us of changes to the list of base path’s children



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/celluloid-presence/presence.rb', line 57

def zk_callback(event_name, event)
	#p "EVENT OCUURED #{event.event_name} #{event.path}"
	if event.node_child?	# We are only listening to child events so we only need to handle these
		begin
			@nodes = zk.children(@base_path, :watch => true)    # re-set watch
			update_node_information
		rescue ZK::Exceptions::NoNode		# Technically this shouldn't happen unless someone deleted our base path
			on_connected
		end
	end
end