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
data/lib/omf_common/comm.rb
CHANGED
@@ -1,65 +1,132 @@
|
|
1
|
-
require 'omf_common/
|
2
|
-
require 'omf_common/dsl/xmpp_mp'
|
3
|
-
|
1
|
+
require 'omf_common/comm/topic'
|
4
2
|
|
5
3
|
module OmfCommon
|
6
4
|
# PubSub communication class, can be extended with different implementations
|
7
5
|
class Comm
|
8
|
-
attr_accessor :published_messages
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
@@providers = {
|
8
|
+
xmpp: {
|
9
|
+
require: 'omf_common/comm/xmpp/communicator',
|
10
|
+
constructor: 'OmfCommon::Comm::XMPP::Communicator',
|
11
|
+
message_provider: {
|
12
|
+
type: :xml
|
13
|
+
}
|
14
|
+
},
|
15
|
+
amqp: {
|
16
|
+
require: 'omf_common/comm/amqp/amqp_communicator',
|
17
|
+
constructor: 'OmfCommon::Comm::AMQP::Communicator',
|
18
|
+
message_provider: {
|
19
|
+
type: :json
|
20
|
+
}
|
21
|
+
},
|
22
|
+
local: {
|
23
|
+
require: 'omf_common/comm/local/local_communicator',
|
24
|
+
constructor: 'OmfCommon::Comm::Local::Communicator',
|
25
|
+
message_provider: {
|
26
|
+
type: :json
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
@@instance = nil
|
14
31
|
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
else
|
34
|
-
Message.send(m_name)
|
32
|
+
#
|
33
|
+
# opts:
|
34
|
+
# :type - pre installed comms provider
|
35
|
+
# :provider - custom provider (opts)
|
36
|
+
# :require - gem to load first (opts)
|
37
|
+
# :constructor - Class implementing provider
|
38
|
+
#
|
39
|
+
def self.init(opts)
|
40
|
+
if @@instance
|
41
|
+
raise "Comms layer already initialised"
|
42
|
+
end
|
43
|
+
unless provider = opts[:provider]
|
44
|
+
unless type = opts[:type]
|
45
|
+
if url = opts[:url]
|
46
|
+
type = url.split(':')[0].to_sym
|
35
47
|
end
|
48
|
+
end
|
49
|
+
provider = @@providers[type]
|
50
|
+
end
|
51
|
+
unless provider
|
52
|
+
raise "Missing Comm provider declaration. Either define 'type', 'provider', or 'url'"
|
53
|
+
end
|
36
54
|
|
37
|
-
|
55
|
+
require provider[:require] if provider[:require]
|
56
|
+
|
57
|
+
if class_name = provider[:constructor]
|
58
|
+
provider_class = class_name.split('::').inject(Object) {|c,n| c.const_get(n) }
|
59
|
+
inst = provider_class.new(opts)
|
60
|
+
else
|
61
|
+
raise "Missing communicator creation info - :constructor"
|
38
62
|
end
|
63
|
+
@@instance = inst
|
64
|
+
Message.init(provider[:message_provider])
|
65
|
+
inst.init(opts)
|
39
66
|
end
|
40
67
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
68
|
+
def self.instance
|
69
|
+
@@instance
|
70
|
+
end
|
71
|
+
|
72
|
+
# Initialize comms layer
|
73
|
+
#
|
74
|
+
def init(opts = {})
|
75
|
+
raise "Not implemented"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Shut down comms layer
|
79
|
+
def disconnect(opts = {})
|
80
|
+
raise "Not implemented"
|
81
|
+
end
|
82
|
+
|
83
|
+
def on_connected(&block)
|
84
|
+
raise "Not implemented"
|
85
|
+
end
|
86
|
+
|
87
|
+
# Create a new pubsub topic with additional configuration
|
88
|
+
#
|
89
|
+
# @param [String] topic Pubsub topic name
|
90
|
+
def create_topic(topic, opts = {})
|
91
|
+
raise "Not implemented"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Delete a pubsub topic
|
95
|
+
#
|
96
|
+
# @param [String] topic Pubsub topic name
|
97
|
+
def delete_topic(topic, &block)
|
98
|
+
raise "Not implemented"
|
99
|
+
end
|
100
|
+
|
101
|
+
# Subscribe to a pubsub topic
|
102
|
+
#
|
103
|
+
# @param [String, Array] topic_name Pubsub topic name
|
104
|
+
# @param [Hash] opts
|
105
|
+
# @option opts [Boolean] :create_if_non_existent create the topic if non-existent, use this option with caution
|
106
|
+
#
|
107
|
+
def subscribe(topic_name, opts = {}, &block)
|
108
|
+
tna = (topic_name.is_a? Array) ? topic_name : [topic_name]
|
109
|
+
ta = tna.collect do |tn|
|
110
|
+
t = create_topic(tn)
|
111
|
+
if block
|
112
|
+
block.call(t)
|
54
113
|
end
|
55
|
-
|
114
|
+
t
|
56
115
|
end
|
116
|
+
ta[0]
|
57
117
|
end
|
58
118
|
|
59
|
-
# Return
|
119
|
+
# Return the options used to initiate this
|
120
|
+
# communicator.
|
60
121
|
#
|
61
|
-
def
|
62
|
-
|
122
|
+
def options()
|
123
|
+
@opts
|
63
124
|
end
|
125
|
+
|
126
|
+
private
|
127
|
+
def initialize(opts = {})
|
128
|
+
@opts = opts
|
129
|
+
end
|
130
|
+
|
64
131
|
end
|
65
132
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'amqp'
|
2
|
+
require 'omf_common/comm/amqp/amqp_topic'
|
3
|
+
#require 'omf_common/comm/monkey_patches'
|
4
|
+
|
5
|
+
module OmfCommon
|
6
|
+
class Comm
|
7
|
+
class AMQP
|
8
|
+
class Communicator < OmfCommon::Comm
|
9
|
+
|
10
|
+
# def initialize(opts = {})
|
11
|
+
# # ignore arguments
|
12
|
+
# end
|
13
|
+
|
14
|
+
# Initialize comms layer
|
15
|
+
#
|
16
|
+
def init(opts = {})
|
17
|
+
unless (@url = opts[:url])
|
18
|
+
raise "Missing 'url' option for AQMP layer"
|
19
|
+
end
|
20
|
+
@address_prefix = @url + '/'
|
21
|
+
::AMQP.connect(@url) do |connection|
|
22
|
+
@channel = ::AMQP::Channel.new(connection)
|
23
|
+
|
24
|
+
if @on_connected_proc
|
25
|
+
@on_connected_proc.arity == 1 ? @on_connected_proc.call(self) : @on_connected_proc.call
|
26
|
+
end
|
27
|
+
|
28
|
+
OmfCommon.eventloop.on_stop do
|
29
|
+
connection.close
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Shut down comms layer
|
35
|
+
def disconnect(opts = {})
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_connected(&block)
|
39
|
+
@on_connected_proc = block
|
40
|
+
end
|
41
|
+
|
42
|
+
# Create a new pubsub topic with additional configuration
|
43
|
+
#
|
44
|
+
# @param [String] topic Pubsub topic name
|
45
|
+
def create_topic(topic, opts = {})
|
46
|
+
raise "Topic can't be nil or empty" if topic.nil? || topic.empty?
|
47
|
+
opts = opts.dup
|
48
|
+
opts[:channel] = @channel
|
49
|
+
if topic.start_with? 'amqp:'
|
50
|
+
# absolute address
|
51
|
+
unless topic.start_with? @address_prefix
|
52
|
+
raise "Cannot subscribe to a topic from different domain (#{topic})"
|
53
|
+
end
|
54
|
+
opts[:address] = topic
|
55
|
+
topic = topic.split(@address_prefix).last
|
56
|
+
else
|
57
|
+
opts[:address] = @address_prefix + topic
|
58
|
+
end
|
59
|
+
OmfCommon::Comm::AMQP::Topic.create(topic, opts)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Delete a pubsub topic
|
63
|
+
#
|
64
|
+
# @param [String] topic Pubsub topic name
|
65
|
+
def delete_topic(topic, &block)
|
66
|
+
if t = OmfCommon::CommProvider::AMQP::Topic.find(topic)
|
67
|
+
t.release
|
68
|
+
else
|
69
|
+
warn "Attempt to delete unknown topic '#{topic}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module OmfCommon
|
4
|
+
class Comm
|
5
|
+
class AMQP
|
6
|
+
class Topic < OmfCommon::Comm::Topic
|
7
|
+
|
8
|
+
# def self.address_for(name)
|
9
|
+
# "#{name}@local"
|
10
|
+
# end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"AMQP::Topic<#{id}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
def address
|
17
|
+
@address
|
18
|
+
end
|
19
|
+
|
20
|
+
# Call 'block' when topic is subscribed to underlying messaging
|
21
|
+
# infrastructure.
|
22
|
+
#
|
23
|
+
def on_subscribed(&block)
|
24
|
+
return unless block
|
25
|
+
|
26
|
+
call_now = false
|
27
|
+
@lock.synchronize do
|
28
|
+
if @subscribed
|
29
|
+
call_now = true
|
30
|
+
else
|
31
|
+
@on_subscrided_handlers << block
|
32
|
+
end
|
33
|
+
end
|
34
|
+
if call_now
|
35
|
+
after(0, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def initialize(id, opts = {})
|
43
|
+
unless channel = opts.delete(:channel)
|
44
|
+
raise "Missing :channel option"
|
45
|
+
end
|
46
|
+
super
|
47
|
+
@address = opts[:address]
|
48
|
+
@exchange = channel.topic(id, :auto_delete => true)
|
49
|
+
@lock = Monitor.new
|
50
|
+
@subscribed = false
|
51
|
+
@on_subscrided_handlers = []
|
52
|
+
|
53
|
+
# Subscribe as well
|
54
|
+
#puts "QQ0(#{id})"
|
55
|
+
channel.queue("", :exclusive => true) do |queue|
|
56
|
+
#puts "QQ1(#{id}): #{queue}"
|
57
|
+
queue.bind(@exchange)
|
58
|
+
queue.subscribe do |headers, payload|
|
59
|
+
#puts "===(#{id}) Incoming message '#{payload}'"
|
60
|
+
msg = Message.parse(payload)
|
61
|
+
#puts "---(#{id}) Parsed message '#{msg}'"
|
62
|
+
on_incoming_message(msg)
|
63
|
+
end
|
64
|
+
# Call all accumulated on_subscribed handlers
|
65
|
+
@lock.synchronize do
|
66
|
+
@subscribed = true
|
67
|
+
@on_subscrided_handlers.each do |block|
|
68
|
+
after(0, &block)
|
69
|
+
end
|
70
|
+
@on_subscrided_handlers = nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def _send_message(msg, block = nil)
|
77
|
+
super
|
78
|
+
debug "(#{id}) Send message #{msg.inspect}"
|
79
|
+
content = msg.marshall
|
80
|
+
@exchange.publish(content)
|
81
|
+
# OmfCommon.eventloop.after(0) do
|
82
|
+
# on_incoming_message(msg)
|
83
|
+
# end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
end # class
|
89
|
+
end # module
|
90
|
+
end # module
|
91
|
+
end # module
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'omf_common/comm/local/local_topic'
|
2
|
+
require 'omf_common/comm/monkey_patches'
|
3
|
+
|
4
|
+
module OmfCommon
|
5
|
+
class Comm
|
6
|
+
class Local
|
7
|
+
class Communicator < OmfCommon::Comm
|
8
|
+
|
9
|
+
# def initialize(opts = {})
|
10
|
+
# # ignore arguments
|
11
|
+
# end
|
12
|
+
|
13
|
+
# Initialize comms layer
|
14
|
+
#
|
15
|
+
def init(opts = {})
|
16
|
+
end
|
17
|
+
|
18
|
+
# Shut down comms layer
|
19
|
+
def disconnect(opts = {})
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create a new pubsub topic with additional configuration
|
23
|
+
#
|
24
|
+
# @param [String] topic Pubsub topic name
|
25
|
+
def create_topic(topic, &block)
|
26
|
+
t = OmfCommon::Comm::Local::Topic.create(topic)
|
27
|
+
if block
|
28
|
+
block.call(t)
|
29
|
+
end
|
30
|
+
t
|
31
|
+
end
|
32
|
+
|
33
|
+
# Delete a pubsub topic
|
34
|
+
#
|
35
|
+
# @param [String] topic Pubsub topic name
|
36
|
+
def delete_topic(topic, &block)
|
37
|
+
if t = OmfCommon::CommProvider::Local::Topic.find(topic)
|
38
|
+
t.release
|
39
|
+
else
|
40
|
+
warn "Attempt to delete unknown topic '#{topic}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def on_connected(&block)
|
45
|
+
return unless block
|
46
|
+
|
47
|
+
OmfCommon.eventloop.after(0) do
|
48
|
+
block.arity == 1 ? block.call(self) : block.call
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Publish to a pubsub topic
|
53
|
+
#
|
54
|
+
# @param [String] topic Pubsub topic name
|
55
|
+
# @param [String] message Any XML fragment to be sent as payload
|
56
|
+
# def publish(topic, message, &block)
|
57
|
+
# raise StandardError, "Invalid message" unless message.valid?
|
58
|
+
#
|
59
|
+
# end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module OmfCommon
|
4
|
+
class Comm
|
5
|
+
class Local
|
6
|
+
class Topic < OmfCommon::Comm::Topic
|
7
|
+
|
8
|
+
# def self.address_for(name)
|
9
|
+
# "#{name}@local"
|
10
|
+
# end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"Mock::Topic<#{id}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
def address
|
17
|
+
"local:/#{id}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_subscribed(&block)
|
21
|
+
return unless block
|
22
|
+
|
23
|
+
OmfCommon.eventloop.after(0) do
|
24
|
+
block.arity == 1 ? block.call(self) : block.call
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def _send_message(msg, block = nil)
|
31
|
+
super
|
32
|
+
debug "(#{id}) Send message #{msg.inspect}"
|
33
|
+
OmfCommon.eventloop.after(0) do
|
34
|
+
on_incoming_message(msg)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
end # class
|
40
|
+
end # module
|
41
|
+
end # module
|
42
|
+
end # module
|