omf_common 6.0.0.pre.10 → 6.0.0.pre.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/bin/monitor_topic.rb +80 -0
  2. data/bin/send_create.rb +94 -0
  3. data/bin/send_request.rb +58 -0
  4. data/example/engine_alt.rb +136 -0
  5. data/example/vm_alt.rb +65 -0
  6. data/lib/omf_common.rb +224 -3
  7. data/lib/omf_common/comm.rb +113 -46
  8. data/lib/omf_common/comm/amqp/amqp_communicator.rb +76 -0
  9. data/lib/omf_common/comm/amqp/amqp_topic.rb +91 -0
  10. data/lib/omf_common/comm/local/local_communicator.rb +64 -0
  11. data/lib/omf_common/comm/local/local_topic.rb +42 -0
  12. data/lib/omf_common/comm/topic.rb +190 -0
  13. data/lib/omf_common/{dsl/xmpp.rb → comm/xmpp/communicator.rb} +93 -53
  14. data/lib/omf_common/comm/xmpp/topic.rb +147 -0
  15. data/lib/omf_common/{dsl → comm/xmpp}/xmpp_mp.rb +2 -0
  16. data/lib/omf_common/eventloop.rb +94 -0
  17. data/lib/omf_common/eventloop/em.rb +57 -0
  18. data/lib/omf_common/eventloop/local_evl.rb +78 -0
  19. data/lib/omf_common/message.rb +112 -229
  20. data/lib/omf_common/message/json/json_message.rb +129 -0
  21. data/lib/omf_common/message/xml/message.rb +410 -0
  22. data/lib/omf_common/message/xml/relaxng_schema.rb +17 -0
  23. data/lib/omf_common/message/xml/topic_message.rb +20 -0
  24. data/lib/omf_common/protocol/6.0.rnc +11 -21
  25. data/lib/omf_common/protocol/6.0.rng +52 -119
  26. data/lib/omf_common/version.rb +1 -1
  27. data/omf_common.gemspec +4 -2
  28. data/test/fixture/pubsub.rb +19 -19
  29. data/test/omf_common/{dsl/xmpp_spec.rb → comm/xmpp/communicator_spec.rb} +47 -111
  30. data/test/omf_common/comm/xmpp/topic_spec.rb +113 -0
  31. data/test/omf_common/comm_spec.rb +1 -0
  32. data/test/omf_common/message/xml/message_spec.rb +136 -0
  33. data/test/omf_common/message_spec.rb +37 -131
  34. data/test/test_helper.rb +4 -1
  35. metadata +38 -28
  36. data/lib/omf_common/core_ext/object.rb +0 -21
  37. data/lib/omf_common/relaxng_schema.rb +0 -17
  38. data/lib/omf_common/topic.rb +0 -34
  39. data/lib/omf_common/topic_message.rb +0 -20
  40. data/test/omf_common/topic_message_spec.rb +0 -114
  41. data/test/omf_common/topic_spec.rb +0 -75
@@ -1,65 +1,132 @@
1
- require 'omf_common/dsl/xmpp'
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
- def initialize(pubsub_implementation)
11
- @published_messages = []
12
- self.extend("OmfCommon::DSL::#{pubsub_implementation.to_s.camelize}".constantize)
13
- end
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
- # Generate OMF related message
16
- %w(create configure request inform release).each do |m_name|
17
- define_method("#{m_name}_message") do |*args, &block|
18
- message =
19
- if block
20
- Message.send(m_name, *args, &block)
21
- elsif args[0].kind_of? Array
22
- Message.send(m_name) do |v|
23
- args[0].each do |opt|
24
- if opt.kind_of? Hash
25
- opt.each_pair do |key, value|
26
- v.property(key, value)
27
- end
28
- else
29
- v.property(opt)
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
- OmfCommon::TopicMessage.new(message, self)
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
- %w(created status released failed).each do |inform_type|
42
- define_method("on_#{inform_type}_message") do |*args, &message_block|
43
- msg_id = args[0].msg_id if args[0]
44
- event_block = proc do |event|
45
- message_block.call(Message.parse(event.items.first.payload))
46
- end
47
- guard_block = proc do |event|
48
- (event.items?) && (!event.delayed?) &&
49
- event.items.first.payload &&
50
- (omf_message = Message.parse(event.items.first.payload)) &&
51
- omf_message.operation == :inform &&
52
- omf_message.read_content(:inform_type) == inform_type.upcase &&
53
- (msg_id ? (omf_message.context_id == msg_id) : true)
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
- topic_event(guard_block, &callback_logging(__method__, &event_block))
114
+ t
56
115
  end
116
+ ta[0]
57
117
  end
58
118
 
59
- # Return a topic object represents pubsub topic
119
+ # Return the options used to initiate this
120
+ # communicator.
60
121
  #
61
- def get_topic(topic_id)
62
- OmfCommon::Topic.new(topic_id, self)
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