omf_common 6.0.0.pre.10 → 6.0.0.pre.11
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.
- data/bin/monitor_topic.rb +80 -0
- data/bin/send_create.rb +94 -0
- data/bin/send_request.rb +58 -0
- data/example/engine_alt.rb +136 -0
- data/example/vm_alt.rb +65 -0
- data/lib/omf_common.rb +224 -3
- data/lib/omf_common/comm.rb +113 -46
- data/lib/omf_common/comm/amqp/amqp_communicator.rb +76 -0
- data/lib/omf_common/comm/amqp/amqp_topic.rb +91 -0
- data/lib/omf_common/comm/local/local_communicator.rb +64 -0
- data/lib/omf_common/comm/local/local_topic.rb +42 -0
- data/lib/omf_common/comm/topic.rb +190 -0
- data/lib/omf_common/{dsl/xmpp.rb → comm/xmpp/communicator.rb} +93 -53
- data/lib/omf_common/comm/xmpp/topic.rb +147 -0
- data/lib/omf_common/{dsl → comm/xmpp}/xmpp_mp.rb +2 -0
- data/lib/omf_common/eventloop.rb +94 -0
- data/lib/omf_common/eventloop/em.rb +57 -0
- data/lib/omf_common/eventloop/local_evl.rb +78 -0
- data/lib/omf_common/message.rb +112 -229
- data/lib/omf_common/message/json/json_message.rb +129 -0
- data/lib/omf_common/message/xml/message.rb +410 -0
- data/lib/omf_common/message/xml/relaxng_schema.rb +17 -0
- data/lib/omf_common/message/xml/topic_message.rb +20 -0
- data/lib/omf_common/protocol/6.0.rnc +11 -21
- data/lib/omf_common/protocol/6.0.rng +52 -119
- data/lib/omf_common/version.rb +1 -1
- data/omf_common.gemspec +4 -2
- data/test/fixture/pubsub.rb +19 -19
- data/test/omf_common/{dsl/xmpp_spec.rb → comm/xmpp/communicator_spec.rb} +47 -111
- data/test/omf_common/comm/xmpp/topic_spec.rb +113 -0
- data/test/omf_common/comm_spec.rb +1 -0
- data/test/omf_common/message/xml/message_spec.rb +136 -0
- data/test/omf_common/message_spec.rb +37 -131
- data/test/test_helper.rb +4 -1
- metadata +38 -28
- data/lib/omf_common/core_ext/object.rb +0 -21
- data/lib/omf_common/relaxng_schema.rb +0 -17
- data/lib/omf_common/topic.rb +0 -34
- data/lib/omf_common/topic_message.rb +0 -20
- data/test/omf_common/topic_message_spec.rb +0 -114
- data/test/omf_common/topic_spec.rb +0 -75
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module OmfCommon
|
5
|
+
class Comm
|
6
|
+
class Topic
|
7
|
+
|
8
|
+
@@name2inst = {}
|
9
|
+
@@lock = Monitor.new
|
10
|
+
|
11
|
+
def self.create(name, opts = {}, &block)
|
12
|
+
# Force string conversion as 'name' can be an ExperimentProperty
|
13
|
+
name = name.to_s.to_sym
|
14
|
+
@@lock.synchronize do
|
15
|
+
unless @@name2inst[name]
|
16
|
+
debug "New topic: #{name}"
|
17
|
+
#opts[:address] ||= address_for(name)
|
18
|
+
@@name2inst[name] = self.new(name, opts, &block)
|
19
|
+
else
|
20
|
+
debug "Existing topic: #{name}"
|
21
|
+
block.call(@@name2inst[name]) if block
|
22
|
+
end
|
23
|
+
@@name2inst[name]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.[](name)
|
28
|
+
@@name2inst[name]
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :id
|
32
|
+
|
33
|
+
# Request the creation of a new resource. Returns itself
|
34
|
+
#
|
35
|
+
def create(res_type, config_props = {}, core_props = {}, &block)
|
36
|
+
# new_res = nil
|
37
|
+
#res_name = res_name.to_sym
|
38
|
+
#config_props[:name] ||= res_name
|
39
|
+
config_props[:type] ||= res_type
|
40
|
+
debug "Create resource of type '#{res_type}'"
|
41
|
+
create_message_and_publish(:create, config_props, core_props, block)
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def configure(props = {}, core_props = {}, &block)
|
46
|
+
create_message_and_publish(:configure, props, core_props, block)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def request(select = [], core_props = {}, &block)
|
51
|
+
# TODO: What are the parameters to the request method really?
|
52
|
+
create_message_and_publish(:request, select, core_props, block)
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def inform(type, props = {}, core_props = {}, &block)
|
57
|
+
msg = OmfCommon::Message.create(:inform, props, core_props.merge(itype: type))
|
58
|
+
publish(msg, &block)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# def inform(type, props = {}, &block)
|
63
|
+
# msg = OmfCommon::Message.create(:inform, props)
|
64
|
+
# msg.itype = type
|
65
|
+
# publish(msg, &block)
|
66
|
+
# self
|
67
|
+
# end
|
68
|
+
|
69
|
+
def release(resource, core_props = {}, &block)
|
70
|
+
unless resource.is_a? self.class
|
71
|
+
raise "Expected '#{self.class}', but got '#{resource.class}'"
|
72
|
+
end
|
73
|
+
msg = OmfCommon::Message.create(:release, {}, core_props.merge(res_id: resource.id))
|
74
|
+
publish(msg, &block)
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def create_message_and_publish(type, props = {}, core_props = {}, block = nil)
|
80
|
+
debug "(#{id}) create_message_and_publish '#{type}': #{props.inspect}"
|
81
|
+
msg = OmfCommon::Message.create(type, props, core_props)
|
82
|
+
publish(msg, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def publish(msg, &block)
|
86
|
+
# TODO should it be _send_message(msg, &block) ?
|
87
|
+
#raise "Expected message but got '#{msg.class}" unless msg.is_a?(OmfCommon::Message)
|
88
|
+
_send_message(msg, block)
|
89
|
+
end
|
90
|
+
|
91
|
+
[:created,
|
92
|
+
:create_succeeded, :create_failed,
|
93
|
+
:inform_status, :inform_failed,
|
94
|
+
:released, :failed,
|
95
|
+
:message
|
96
|
+
].each do |itype|
|
97
|
+
mname = "on_#{itype}"
|
98
|
+
define_method(mname) do |*args, &message_block|
|
99
|
+
debug "(#{id}) register handler for '#{mname}'"
|
100
|
+
@lock.synchronize do
|
101
|
+
(@handlers[itype] ||= []) << message_block
|
102
|
+
end
|
103
|
+
self
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Unsubscribe from the underlying comms layer
|
108
|
+
#
|
109
|
+
def unsubscribe()
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
def on_subscribed(&block)
|
114
|
+
raise "Not implemented"
|
115
|
+
end
|
116
|
+
|
117
|
+
# For detecting message publishing error, means if callback indeed yield a Topic object, there is no publishing error, thus always false
|
118
|
+
def error?
|
119
|
+
false
|
120
|
+
end
|
121
|
+
|
122
|
+
def address
|
123
|
+
raise "Not implemented"
|
124
|
+
end
|
125
|
+
|
126
|
+
def after(delay_sec, &block)
|
127
|
+
return unless block
|
128
|
+
OmfCommon.eventloop.after(delay_sec) do
|
129
|
+
block.arity == 1 ? block.call(self) : block.call
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def initialize(id, opts = {})
|
136
|
+
@id = id
|
137
|
+
#@address = opts[:address]
|
138
|
+
@handlers = {}
|
139
|
+
@lock = Monitor.new
|
140
|
+
@context2cbk = {}
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
def _send_message(msg, block = nil)
|
145
|
+
if (block)
|
146
|
+
# register callback for responses to 'mid'
|
147
|
+
@context2cbk[msg.mid.to_s] = {block: block, created_at: Time.now}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def on_incoming_message(msg)
|
152
|
+
type = msg.operation
|
153
|
+
debug "(#{id}) Deliver message '#{type}': #{msg.inspect}"
|
154
|
+
htypes = [type, :message]
|
155
|
+
if type == :inform
|
156
|
+
if it = msg.itype.to_s.downcase
|
157
|
+
#puts "TTT> #{it}"
|
158
|
+
case it
|
159
|
+
when "creation_ok"
|
160
|
+
htypes << :create_succeeded
|
161
|
+
when 'status'
|
162
|
+
htypes << :inform_status
|
163
|
+
else
|
164
|
+
htypes << it.to_sym
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
debug "(#{id}) Message type '#{htypes.inspect}' (#{msg.class}:#{msg.cid})"
|
170
|
+
hs = htypes.map do |ht| @handlers[ht] end.compact.flatten
|
171
|
+
debug "(#{id}) Distributing message to '#{hs.inspect}'"
|
172
|
+
hs.each do |block|
|
173
|
+
block.call msg
|
174
|
+
end
|
175
|
+
if cbk = @context2cbk[msg.cid.to_s]
|
176
|
+
debug "(#{id}) Distributing message to '#{cbk.inspect}'"
|
177
|
+
cbk[:last_used] = Time.now
|
178
|
+
cbk[:block].call(msg)
|
179
|
+
# else
|
180
|
+
# if msg.cid
|
181
|
+
# puts "====NOOOO for #{msg.cid} - #{@context2cbk.keys.inspect}"
|
182
|
+
# end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -1,10 +1,18 @@
|
|
1
1
|
require 'blather/client/dsl'
|
2
2
|
|
3
|
+
require 'omf_common/comm/xmpp/xmpp_mp'
|
4
|
+
require 'omf_common/comm/xmpp/topic'
|
5
|
+
require 'uri'
|
6
|
+
require 'socket'
|
7
|
+
|
3
8
|
module OmfCommon
|
4
|
-
|
5
|
-
|
9
|
+
class Comm
|
10
|
+
class XMPP
|
11
|
+
class Communicator < OmfCommon::Comm
|
6
12
|
include Blather::DSL
|
7
13
|
|
14
|
+
attr_accessor :published_messages, :normal_shutdown_mode, :retry_counter
|
15
|
+
|
8
16
|
HOST_PREFIX = 'pubsub'
|
9
17
|
|
10
18
|
PUBSUB_CONFIGURE = Blather::Stanza::X.new({
|
@@ -17,9 +25,63 @@ module OmfCommon
|
|
17
25
|
{ :var => "pubsub#publish_model", :value => "open" }]
|
18
26
|
})
|
19
27
|
|
28
|
+
# Capture system :INT & :TERM signal
|
29
|
+
def on_interrupted(&block)
|
30
|
+
if block
|
31
|
+
trap(:INT) { block.call(self) }
|
32
|
+
trap(:TERM) { block.call(self) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_connected(&block)
|
37
|
+
when_ready do
|
38
|
+
block.call(self)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set up XMPP options and start the Eventmachine, connect to XMPP server
|
43
|
+
#
|
44
|
+
def init(opts = {})
|
45
|
+
@pubsub_host = opts[:pubsub_domain]
|
46
|
+
if opts[:url]
|
47
|
+
url = URI(opts[:url])
|
48
|
+
username, password, server = url.user, url.password, url.host
|
49
|
+
else
|
50
|
+
username, password, server = opts[:username], opts[:password], opts[:server]
|
51
|
+
end
|
52
|
+
|
53
|
+
random_name = "#{Socket.gethostname}-#{Process.pid}"
|
54
|
+
username ||= random_name
|
55
|
+
password ||= random_name
|
56
|
+
|
57
|
+
raise ArgumentError, "Username cannot be nil when connect to XMPP" if username.nil?
|
58
|
+
raise ArgumentError, "Password cannot be nil when connect to XMPP" if password.nil?
|
59
|
+
raise ArgumentError, "Server cannot be nil when connect to XMPP" if server.nil?
|
60
|
+
|
61
|
+
@retry_counter = 0
|
62
|
+
@normal_shutdown_mode = false
|
63
|
+
|
64
|
+
connect(username, password, server)
|
65
|
+
|
66
|
+
disconnected do
|
67
|
+
unless normal_shutdown_mode
|
68
|
+
unless retry_counter > 0
|
69
|
+
@retry_counter += 1
|
70
|
+
client.connect
|
71
|
+
else
|
72
|
+
error "Authentication failed."
|
73
|
+
OmfCommon.eventloop.stop
|
74
|
+
end
|
75
|
+
else
|
76
|
+
shutdown
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
20
81
|
# Set up XMPP options and start the Eventmachine, connect to XMPP server
|
21
82
|
#
|
22
83
|
def connect(username, password, server)
|
84
|
+
info "Connecting to '#{server}' ..."
|
23
85
|
jid = "#{username}@#{server}"
|
24
86
|
client.setup(jid, password)
|
25
87
|
client.run
|
@@ -28,38 +90,18 @@ module OmfCommon
|
|
28
90
|
|
29
91
|
# Shut down XMPP connection
|
30
92
|
def disconnect(opts = {})
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# none means... topics subscribed to
|
36
|
-
none_topics = a[:none] ? a[:none].size : 0
|
37
|
-
|
38
|
-
if none_topics > 0
|
39
|
-
info "Unsubscribing #{none_topics} pubsub topic(s)"
|
40
|
-
unsubscribe
|
41
|
-
end
|
42
|
-
|
43
|
-
if owner_topics > 0
|
44
|
-
info "Deleting #{owner_topics} pubsub topic(s) in 2 seconds"
|
45
|
-
EM.add_timer(2) do
|
46
|
-
a[:owner].each { |topic| delete_topic(topic) }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
shutdown if none_topics == 0 && owner_topics == 0
|
51
|
-
end
|
52
|
-
else
|
53
|
-
shutdown
|
54
|
-
end
|
93
|
+
# NOTE Do not clean up
|
94
|
+
info "Disconnecting ..."
|
95
|
+
@normal_shutdown_mode = true
|
96
|
+
shutdown
|
55
97
|
OmfCommon::DSL::Xmpp::MPConnection.inject(Time.now.to_f, jid, 'disconnect') if OmfCommon::Measure.enabled?
|
56
98
|
end
|
57
99
|
|
58
100
|
# Create a new pubsub topic with additional configuration
|
59
101
|
#
|
60
102
|
# @param [String] topic Pubsub topic name
|
61
|
-
def create_topic(topic,
|
62
|
-
|
103
|
+
def create_topic(topic, opts = {})
|
104
|
+
OmfCommon::Comm::XMPP::Topic.create(topic)
|
63
105
|
end
|
64
106
|
|
65
107
|
# Delete a pubsub topic
|
@@ -75,22 +117,19 @@ module OmfCommon
|
|
75
117
|
# @param [Hash] opts
|
76
118
|
# @option opts [Boolean] :create_if_non_existent create the topic if non-existent, use this option with caution
|
77
119
|
def subscribe(topic, opts = {}, &block)
|
78
|
-
if
|
79
|
-
|
80
|
-
if a[:owner] && a[:owner].include?(topic)
|
81
|
-
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
82
|
-
else
|
83
|
-
create_topic(topic) do
|
84
|
-
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
else
|
89
|
-
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
90
|
-
end
|
120
|
+
topic = topic.first if topic.is_a? Array
|
121
|
+
OmfCommon::Comm::XMPP::Topic.create(topic, &block)
|
91
122
|
MPSubscription.inject(Time.now.to_f, jid, 'join', topic) if OmfCommon::Measure.enabled?
|
92
123
|
end
|
93
124
|
|
125
|
+
def _subscribe(topic, &block)
|
126
|
+
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
127
|
+
end
|
128
|
+
|
129
|
+
def _create(topic, &block)
|
130
|
+
pubsub.create(topic, default_host, PUBSUB_CONFIGURE, &callback_logging(__method__, topic, &block))
|
131
|
+
end
|
132
|
+
|
94
133
|
# Un-subscribe all existing subscriptions from all pubsub topics.
|
95
134
|
def unsubscribe
|
96
135
|
pubsub.subscriptions(default_host) do |m|
|
@@ -108,10 +147,12 @@ module OmfCommon
|
|
108
147
|
# Publish to a pubsub topic
|
109
148
|
#
|
110
149
|
# @param [String] topic Pubsub topic name
|
111
|
-
# @param [
|
150
|
+
# @param [OmfCommon::Message] message Any XML fragment to be sent as payload
|
112
151
|
def publish(topic, message, &block)
|
113
152
|
raise StandardError, "Invalid message" unless message.valid?
|
114
153
|
|
154
|
+
message = message.xml unless message.kind_of? String
|
155
|
+
|
115
156
|
new_block = proc do |stanza|
|
116
157
|
published_messages << OpenSSL::Digest::SHA1.new(message.to_s)
|
117
158
|
block.call(stanza) if block
|
@@ -121,13 +162,6 @@ module OmfCommon
|
|
121
162
|
MPPublished.inject(Time.now.to_f, jid, topic, message.to_s.gsub("\n",'')) if OmfCommon::Measure.enabled?
|
122
163
|
end
|
123
164
|
|
124
|
-
# Event machine related method delegation
|
125
|
-
%w(add_timer add_periodic_timer).each do |m_name|
|
126
|
-
define_method(m_name) do |*args, &block|
|
127
|
-
EM.send(m_name, *args, &block)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
165
|
# Event callback for pubsub topic event(item published)
|
132
166
|
#
|
133
167
|
def topic_event(additional_guard = nil, &block)
|
@@ -148,16 +182,21 @@ module OmfCommon
|
|
148
182
|
|
149
183
|
private
|
150
184
|
|
185
|
+
def initialize(opts = {})
|
186
|
+
self.published_messages = []
|
187
|
+
super
|
188
|
+
end
|
189
|
+
|
151
190
|
# Provide a new block wrap to automatically log errors
|
152
191
|
def callback_logging(*args, &block)
|
153
|
-
m = args.empty? ? "OPERATION" : args.
|
192
|
+
m = args.empty? ? "OPERATION" : args.join(" >> ")
|
154
193
|
proc do |stanza|
|
155
194
|
if stanza.respond_to?(:error?) && stanza.error?
|
156
195
|
e_stanza = Blather::StanzaError.import(stanza)
|
157
196
|
if [:unexpected_request].include? e_stanza.name
|
158
197
|
logger.debug e_stanza
|
159
|
-
elsif e_stanza.name == :conflict
|
160
|
-
logger.debug e_stanza
|
198
|
+
elsif e_stanza.name == :conflict
|
199
|
+
#logger.debug e_stanza
|
161
200
|
else
|
162
201
|
logger.warn "#{e_stanza} Original: #{e_stanza.original}"
|
163
202
|
end
|
@@ -168,8 +207,9 @@ module OmfCommon
|
|
168
207
|
end
|
169
208
|
|
170
209
|
def default_host
|
171
|
-
"#{HOST_PREFIX}.#{
|
210
|
+
@pubsub_host || "#{HOST_PREFIX}.#{jid.domain}"
|
172
211
|
end
|
173
212
|
end
|
174
213
|
end
|
175
214
|
end
|
215
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module OmfCommon
|
2
|
+
class Comm
|
3
|
+
class XMPP
|
4
|
+
class Topic < OmfCommon::Comm::Topic
|
5
|
+
%w(creation.ok creation.failed status released error warn).each do |itype|
|
6
|
+
define_method("on_#{itype.gsub(/\./, '_')}") do |*args, &message_block|
|
7
|
+
mid = args[0].mid if args[0]
|
8
|
+
|
9
|
+
raise ArgumentError, 'Missing callback' if message_block.nil?
|
10
|
+
|
11
|
+
event_block = proc do |event|
|
12
|
+
message_block.call(OmfCommon::Message.parse(event.items.first.payload))
|
13
|
+
end
|
14
|
+
|
15
|
+
guard_block = proc do |event|
|
16
|
+
(event.items?) && (!event.delayed?) &&
|
17
|
+
event.items.first.payload &&
|
18
|
+
(omf_message = OmfCommon::Message.parse(event.items.first.payload)) &&
|
19
|
+
event.node == id.to_s &&
|
20
|
+
omf_message.operation == :inform &&
|
21
|
+
omf_message.read_content(:itype) == itype.upcase &&
|
22
|
+
(mid ? (omf_message.cid == mid) : true)
|
23
|
+
end
|
24
|
+
|
25
|
+
OmfCommon.comm.topic_event(guard_block, &event_block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_message(message_guard_proc = nil, ref_id = 0, &message_block)
|
30
|
+
@lock.synchronize do
|
31
|
+
@on_message_cbks[ref_id] ||= []
|
32
|
+
@on_message_cbks[ref_id] << message_block
|
33
|
+
end
|
34
|
+
|
35
|
+
event_block = proc do |event|
|
36
|
+
@on_message_cbks.each do |id, cbks|
|
37
|
+
cbks.each do |cbk|
|
38
|
+
cbk.call(OmfCommon::Message.parse(event.items.first.payload))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
guard_block = proc do |event|
|
44
|
+
(event.items?) && (!event.delayed?) &&
|
45
|
+
event.items.first.payload &&
|
46
|
+
(omf_message = OmfCommon::Message.parse(event.items.first.payload)) &&
|
47
|
+
event.node == id.to_s &&
|
48
|
+
(valid_guard?(message_guard_proc) ? message_guard_proc.call(omf_message) : true)
|
49
|
+
end
|
50
|
+
OmfCommon.comm.topic_event(guard_block, &event_block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def delete_on_message_cbk_by_id(id)
|
54
|
+
@lock.synchronize do
|
55
|
+
@on_message_cbks[id] && @on_message_cbks.reject! { |k| k == id.to_s }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def inform(type, props = {}, core_props = {}, &block)
|
60
|
+
msg = OmfCommon::Message.create(:inform, props, core_props.merge(itype: type))
|
61
|
+
publish(msg, &block)
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def publish(msg, &block)
|
66
|
+
_send_message(msg, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def address
|
70
|
+
"xmpp://#{id.to_s}@#{OmfCommon.comm.jid.domain}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_subscribed(&block)
|
74
|
+
return unless block
|
75
|
+
|
76
|
+
@lock.synchronize do
|
77
|
+
@on_subscrided_handlers << block
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def initialize(id, opts = {}, &block)
|
84
|
+
@on_message_cbks = Hashie::Mash.new
|
85
|
+
|
86
|
+
id = $1 if id =~ /^xmpp:\/\/(.+)@.+$/
|
87
|
+
|
88
|
+
super
|
89
|
+
|
90
|
+
@on_subscrided_handlers = []
|
91
|
+
|
92
|
+
topic_block = proc do |stanza|
|
93
|
+
if stanza.error?
|
94
|
+
block.call(stanza) if block
|
95
|
+
else
|
96
|
+
block.call(self) if block
|
97
|
+
|
98
|
+
@lock.synchronize do
|
99
|
+
@on_subscrided_handlers.each do |handler|
|
100
|
+
handler.call
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
OmfCommon.comm._create(id.to_s) do |stanza|
|
107
|
+
if stanza.error?
|
108
|
+
e_stanza = Blather::StanzaError.import(stanza)
|
109
|
+
if e_stanza.name == :conflict
|
110
|
+
# Topic exists, just subscribe to it.
|
111
|
+
OmfCommon.comm._subscribe(id.to_s, &topic_block)
|
112
|
+
else
|
113
|
+
block.call(stanza) if block
|
114
|
+
end
|
115
|
+
else
|
116
|
+
OmfCommon.comm._subscribe(id.to_s, &topic_block)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def _send_message(msg, &block)
|
122
|
+
# while sending a message, need to setup handler for replying messages
|
123
|
+
OmfCommon.comm.publish(self.id, msg) do |stanza|
|
124
|
+
if !stanza.error? && !block.nil?
|
125
|
+
on_error(msg, &block)
|
126
|
+
on_warn(msg, &block)
|
127
|
+
case msg.operation
|
128
|
+
when :create
|
129
|
+
on_creation_ok(msg, &block)
|
130
|
+
on_creation_failed(msg, &block)
|
131
|
+
when :configure, :request
|
132
|
+
on_status(msg, &block)
|
133
|
+
when :release
|
134
|
+
on_released(msg, &block)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def valid_guard?(guard_proc)
|
141
|
+
guard_proc && guard_proc.class == Proc
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|