activemessaging 0.6.0
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/Rakefile +50 -0
- data/generators/a13g_test_harness/a13g_test_harness_generator.rb +19 -0
- data/generators/a13g_test_harness/templates/active_messaging_test.rhtml +13 -0
- data/generators/a13g_test_harness/templates/active_messaging_test_controller.rb +29 -0
- data/generators/a13g_test_harness/templates/index.rhtml +17 -0
- data/generators/filter/USAGE +0 -0
- data/generators/filter/filter_generator.rb +19 -0
- data/generators/filter/templates/filter.rb +12 -0
- data/generators/filter/templates/filter_test.rb +28 -0
- data/generators/processor/USAGE +8 -0
- data/generators/processor/processor_generator.rb +31 -0
- data/generators/processor/templates/application.rb +18 -0
- data/generators/processor/templates/broker.yml +79 -0
- data/generators/processor/templates/jruby_poller +117 -0
- data/generators/processor/templates/messaging.rb +12 -0
- data/generators/processor/templates/poller +23 -0
- data/generators/processor/templates/poller.rb +23 -0
- data/generators/processor/templates/processor.rb +8 -0
- data/generators/processor/templates/processor_test.rb +20 -0
- data/generators/tracer/USAGE +8 -0
- data/generators/tracer/templates/controller.rb +14 -0
- data/generators/tracer/templates/helper.rb +2 -0
- data/generators/tracer/templates/index.rhtml +4 -0
- data/generators/tracer/templates/layout.rhtml +16 -0
- data/generators/tracer/templates/trace_processor.rb +100 -0
- data/generators/tracer/tracer_generator.rb +25 -0
- data/lib/activemessaging.rb +133 -0
- data/lib/activemessaging/adapter.rb +21 -0
- data/lib/activemessaging/adapters/asqs.rb +412 -0
- data/lib/activemessaging/adapters/base.rb +82 -0
- data/lib/activemessaging/adapters/jms.rb +237 -0
- data/lib/activemessaging/adapters/reliable_msg.rb +190 -0
- data/lib/activemessaging/adapters/stomp.rb +99 -0
- data/lib/activemessaging/adapters/test.rb +155 -0
- data/lib/activemessaging/adapters/wmq.rb +202 -0
- data/lib/activemessaging/filter.rb +29 -0
- data/lib/activemessaging/gateway.rb +422 -0
- data/lib/activemessaging/message_sender.rb +30 -0
- data/lib/activemessaging/named_base.rb +54 -0
- data/lib/activemessaging/processor.rb +45 -0
- data/lib/activemessaging/support.rb +17 -0
- data/lib/activemessaging/test_helper.rb +194 -0
- data/lib/activemessaging/trace_filter.rb +34 -0
- data/messaging.rb.example +5 -0
- data/tasks/start_consumers.rake +8 -0
- metadata +123 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
module ActiveMessaging
|
2
|
+
module Adapters
|
3
|
+
module Base
|
4
|
+
|
5
|
+
|
6
|
+
# use this as a base for implementing new connections
|
7
|
+
class Connection
|
8
|
+
include ActiveMessaging::Adapter
|
9
|
+
|
10
|
+
#use the register method to add the adapter to the configurable list of supported adapters
|
11
|
+
# register :generic
|
12
|
+
|
13
|
+
#configurable params
|
14
|
+
attr_accessor :reliable
|
15
|
+
|
16
|
+
#generic init method needed by a13g
|
17
|
+
def initialize cfg
|
18
|
+
end
|
19
|
+
|
20
|
+
# called to cleanly get rid of connection
|
21
|
+
def disconnect
|
22
|
+
end
|
23
|
+
|
24
|
+
# destination_name string, headers hash
|
25
|
+
# subscribe to listen on a destination
|
26
|
+
def subscribe destination_name, message_headers={}
|
27
|
+
end
|
28
|
+
|
29
|
+
# destination_name string, headers hash
|
30
|
+
# unsubscribe to listen on a destination
|
31
|
+
def unsubscribe destination_name, message_headers={}
|
32
|
+
end
|
33
|
+
|
34
|
+
# destination_name string, body string, headers hash
|
35
|
+
# send a single message to a destination
|
36
|
+
def send destination_name, message_body, message_headers={}
|
37
|
+
end
|
38
|
+
|
39
|
+
# receive a single message from any of the subscribed destinations
|
40
|
+
# check each destination once, then sleep for poll_interval
|
41
|
+
def receive
|
42
|
+
end
|
43
|
+
|
44
|
+
# called after a message is successfully received and processed
|
45
|
+
def received message, headers={}
|
46
|
+
end
|
47
|
+
|
48
|
+
# called after a message is successfully received but unsuccessfully processed
|
49
|
+
# purpose is to return the message to the destination so receiving and processing and be attempted again
|
50
|
+
def unreceive message, headers={}
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
# I recommend having a destination object to represent each subscribed destination
|
56
|
+
class Destination
|
57
|
+
attr_accessor :name
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
"<Base::Destination name='#{name}'>"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# based on stomp message
|
65
|
+
# command = MESSAGE for successful message from adapter, ERROR for problem from adapter
|
66
|
+
# !!!! must have headers['destination'] = subscription.destination in order to match message to subscription in gateway!!!!
|
67
|
+
class Message
|
68
|
+
attr_accessor :headers, :body, :command
|
69
|
+
|
70
|
+
def initialize headers, id, body, response, destination, command='MESSAGE'
|
71
|
+
@headers, @body, @command = headers, body, command
|
72
|
+
headers['destination'] = destination.name
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
"<Base::Message body='#{body}' headers='#{headers.inspect}' command='#{command}' >"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
|
2
|
+
if defined?(JRUBY_VERSION)
|
3
|
+
#require 'java'
|
4
|
+
include Java
|
5
|
+
|
6
|
+
import javax.naming.InitialContext
|
7
|
+
import javax.jms.MessageListener
|
8
|
+
|
9
|
+
module ActiveMessaging
|
10
|
+
module Adapters
|
11
|
+
module Jms
|
12
|
+
|
13
|
+
class Connection
|
14
|
+
include ActiveMessaging::Adapter
|
15
|
+
register :jms
|
16
|
+
|
17
|
+
attr_accessor :reliable, :connection, :session, :producers, :consumers
|
18
|
+
|
19
|
+
def initialize cfg={}
|
20
|
+
@url = cfg[:url]
|
21
|
+
@login = cfg[:login]
|
22
|
+
@passcode = cfg[:passcode]
|
23
|
+
#initialize our connection factory
|
24
|
+
if cfg.has_key? :connection_factory
|
25
|
+
#this initialize is probably activemq specific. There might be a more generic
|
26
|
+
#way of getting this without resorting to jndi lookup.
|
27
|
+
eval <<-end_eval
|
28
|
+
@connection_factory = Java::#{cfg[:connection_factory]}.new(@login, @password, @url)
|
29
|
+
end_eval
|
30
|
+
elsif cfg.has_key? :jndi
|
31
|
+
@connection_factory = javax.naming.InitialContext.new().lookup(cfg[:jndi])
|
32
|
+
else
|
33
|
+
raise "Either jndi or connection_factory has to be set in the config."
|
34
|
+
end
|
35
|
+
raise "Connection factory could not be initialized." if @connection_factory.nil?
|
36
|
+
|
37
|
+
@connection = @connection_factory.create_connection()
|
38
|
+
@session = @connection.createSession(false, 1)
|
39
|
+
@destinations = []
|
40
|
+
@producers = {}
|
41
|
+
@consumers = {}
|
42
|
+
@connection.start
|
43
|
+
end
|
44
|
+
|
45
|
+
def subscribe queue_name, headers={}
|
46
|
+
queue_name = check_destination_type queue_name, headers
|
47
|
+
find_or_create_consumer queue_name, headers
|
48
|
+
end
|
49
|
+
|
50
|
+
def unsubscribe queue_name, headers={}
|
51
|
+
queue_name = check_destination_type queue_name, headers
|
52
|
+
consumer = @consumers[queue_name]
|
53
|
+
unless consumer.nil?
|
54
|
+
consumer.close
|
55
|
+
@consumers.delete queue_name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def send queue_name, body, headers={}
|
60
|
+
queue_name = check_destination_type queue_name, headers
|
61
|
+
producer = find_or_create_producer queue_name, headers.symbolize_keys
|
62
|
+
message = @session.create_text_message body
|
63
|
+
headers.stringify_keys.each do |key, value|
|
64
|
+
if ['id', 'message-id', 'JMSMessageID'].include? key
|
65
|
+
message.setJMSMessageID value.to_s
|
66
|
+
elsif ['correlation-id', 'JMSCorrelationID'].include? key
|
67
|
+
message.setJMSCorrelationID value.to_s
|
68
|
+
elsif ['expires', 'JMSExpiration'].include? key
|
69
|
+
message.setJMSExpiration value.to_i
|
70
|
+
elsif ['persistent', 'JMSDeliveryMode'].include? key
|
71
|
+
message.setJMSDeliveryMode(value ? 2 : 1)
|
72
|
+
elsif ['priority', 'JMSPriority'].include? key
|
73
|
+
message.setJMSPriority value.to_i
|
74
|
+
elsif ['reply-to', 'JMSReplyTo'].include? key
|
75
|
+
message.setJMSReplyTo value.to_s
|
76
|
+
elsif ['type', 'JMSType'].include? key
|
77
|
+
message.setJMSType value.to_s
|
78
|
+
else #is this the most appropriate thing to do here?
|
79
|
+
message.set_string_property key, value.to_s
|
80
|
+
end
|
81
|
+
end
|
82
|
+
producer.send message
|
83
|
+
end
|
84
|
+
|
85
|
+
def receive_any
|
86
|
+
@consumers.find do |k, c|
|
87
|
+
message = c.receive(1)
|
88
|
+
return condition_message(message) unless message.nil?
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def receive queue_name=nil, headers={}
|
93
|
+
if queue_name.nil?
|
94
|
+
receive_any
|
95
|
+
else
|
96
|
+
consumer = subscribe queue_name, headers
|
97
|
+
message = consumer.receive(1)
|
98
|
+
unsubscribe queue_name, headers
|
99
|
+
condition_message message
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def received message, headers={}
|
104
|
+
#do nothing
|
105
|
+
end
|
106
|
+
|
107
|
+
def unreceive message, headers={}
|
108
|
+
# do nothing
|
109
|
+
end
|
110
|
+
|
111
|
+
def close
|
112
|
+
@consumers.each {|k, c| c.stop }
|
113
|
+
@connection.stop
|
114
|
+
@session.close
|
115
|
+
@connection.close
|
116
|
+
@connection = nil
|
117
|
+
@session = nil
|
118
|
+
@consumers = {}
|
119
|
+
@producers = {}
|
120
|
+
end
|
121
|
+
|
122
|
+
def find_or_create_producer queue_name, headers={}
|
123
|
+
producer = @producers[queue_name]
|
124
|
+
if producer.nil?
|
125
|
+
destination = find_or_create_destination queue_name, headers
|
126
|
+
producer = @session.create_producer destination
|
127
|
+
end
|
128
|
+
producer
|
129
|
+
end
|
130
|
+
|
131
|
+
def find_or_create_consumer queue_name, headers={}
|
132
|
+
consumer = @consumers[queue_name]
|
133
|
+
if consumer.nil?
|
134
|
+
destination = find_or_create_destination queue_name, headers
|
135
|
+
if headers.symbolize_keys.has_key? :selector
|
136
|
+
consumer = @session.create_consumer destination, headers.symbolize_keys[:selector]
|
137
|
+
else
|
138
|
+
consumer = @session.create_consumer destination
|
139
|
+
end
|
140
|
+
|
141
|
+
@consumers[queue_name] = consumer
|
142
|
+
end
|
143
|
+
consumer
|
144
|
+
end
|
145
|
+
|
146
|
+
def find_or_create_destination queue_name, headers={}
|
147
|
+
destination = find_destination queue_name, headers[:destination_type]
|
148
|
+
if destination.nil?
|
149
|
+
if headers.symbolize_keys[:destination_type] == :topic
|
150
|
+
destination = @session.create_topic(queue_name.to_s)
|
151
|
+
@destinations << destination
|
152
|
+
elsif headers.symbolize_keys[:destination_type] == :queue
|
153
|
+
destination = @session.create_queue(queue_name.to_s)
|
154
|
+
@destinations << destination
|
155
|
+
else
|
156
|
+
raise "headers[:destination_type] must be either :queue or :topic. was #{headers[:destination_type]}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
destination
|
160
|
+
end
|
161
|
+
|
162
|
+
protected
|
163
|
+
|
164
|
+
def condition_message message
|
165
|
+
message.class.class_eval {
|
166
|
+
alias_method :body, :text unless method_defined? :body
|
167
|
+
|
168
|
+
def command
|
169
|
+
"MESSAGE"
|
170
|
+
end
|
171
|
+
|
172
|
+
def headers
|
173
|
+
destination.to_s =~ %r{(queue|topic)://(.*)}
|
174
|
+
puts "/#{$1}/#{$2}"
|
175
|
+
{'destination' => "/#{$1}/#{$2}"}
|
176
|
+
end
|
177
|
+
|
178
|
+
} unless message.nil? || message.respond_to?(:command)
|
179
|
+
message
|
180
|
+
end
|
181
|
+
|
182
|
+
def check_destination_type queue_name, headers
|
183
|
+
stringy_h = headers.stringify_keys
|
184
|
+
if queue_name =~ %r{^/(topic|queue)/(.*)$} && !stringy_h.has_key?('destination_type')
|
185
|
+
headers['destination_type'] = $1.to_sym
|
186
|
+
return $2
|
187
|
+
else
|
188
|
+
raise "Must specify destination type either with either 'headers[\'destination_type\']=[:queue|:topic]' or /[topic|queue]/destination_name for queue name '#{queue_name}'" unless [:topic, :queue].include? stringy_h['destination_type']
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def find_destination queue_name, type
|
193
|
+
@destinations.find do |d|
|
194
|
+
if d.is_a?(javax.jms.Topic) && type == :topic
|
195
|
+
d.topic_name == queue_name
|
196
|
+
elsif d.is_a?(javax.jms.Queue) && type == :queue
|
197
|
+
d.queue_name == queue_name
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
#
|
203
|
+
# class RubyMessageListener
|
204
|
+
# include javax.jms.MessageListener
|
205
|
+
#
|
206
|
+
# def initialize(connection, destination, name)
|
207
|
+
# @connection = connection
|
208
|
+
# @destination = destination
|
209
|
+
# @name = name
|
210
|
+
# end
|
211
|
+
#
|
212
|
+
# def onMessage(msg)
|
213
|
+
# headers = {}
|
214
|
+
# enm = msg.getPropertyNames
|
215
|
+
# while enm.hasMoreElements
|
216
|
+
# key = enm.nextElement
|
217
|
+
# headers[key.to_s] = msg.getStringProperty(key)
|
218
|
+
# end
|
219
|
+
# Gateway.dispatch(JMSRecvMessage.new(headers,msg.text,@name))
|
220
|
+
# rescue => e
|
221
|
+
# STDERR.puts "something went really wrong with a message: #{e.inspect}"
|
222
|
+
# end
|
223
|
+
# end
|
224
|
+
#
|
225
|
+
# class JMSRecvMessage < ActiveMessaging::Adapters::Base::Message
|
226
|
+
# def initialize(headers, body, name, command='MESSAGE')
|
227
|
+
# @headers = headers
|
228
|
+
# @body = body
|
229
|
+
# @command = command
|
230
|
+
# @headers['destination'] = name
|
231
|
+
# end
|
232
|
+
# end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'reliable-msg'
|
2
|
+
|
3
|
+
module ReliableMsg
|
4
|
+
|
5
|
+
class Client
|
6
|
+
|
7
|
+
def queue_manager
|
8
|
+
qm
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
module ActiveMessaging
|
16
|
+
module Adapters
|
17
|
+
module ReliableMsg
|
18
|
+
|
19
|
+
THREAD_OLD_TXS = :a13g_reliable_msg_old_txs
|
20
|
+
|
21
|
+
QUEUE_PARAMS = [:expires,:delivery,:priority,:max_deliveries,:drb_uri,:tx_timeout,:connect_count]
|
22
|
+
TOPIC_PARAMS = [:expires,:drb_uri,:tx_timeout,:connect_count]
|
23
|
+
|
24
|
+
class Connection
|
25
|
+
include ActiveMessaging::Adapter
|
26
|
+
|
27
|
+
register :reliable_msg
|
28
|
+
|
29
|
+
#configurable params
|
30
|
+
attr_accessor :reliable, :subscriptions, :destinations, :poll_interval, :current_subscription, :tx_timeout
|
31
|
+
|
32
|
+
#generic init method needed by a13g
|
33
|
+
def initialize cfg
|
34
|
+
@poll_interval = cfg[:poll_interval] || 1
|
35
|
+
@reliable = cfg[:reliable] || true
|
36
|
+
@tx_timeout = cfg[:tx_timeout] || ::ReliableMsg::Client::DEFAULT_TX_TIMEOUT
|
37
|
+
|
38
|
+
@subscriptions = {}
|
39
|
+
@destinations = {}
|
40
|
+
@current_subscription = 0
|
41
|
+
end
|
42
|
+
|
43
|
+
# called to cleanly get rid of connection
|
44
|
+
def disconnect
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
# destination_name string, headers hash
|
49
|
+
# subscribe to listen on a destination
|
50
|
+
# use '/destination-type/name' convetion, like stomp
|
51
|
+
def subscribe destination_name, message_headers={}
|
52
|
+
get_or_create_destination(destination_name, message_headers)
|
53
|
+
if subscriptions.has_key? destination_name
|
54
|
+
subscriptions[destination_name].add
|
55
|
+
else
|
56
|
+
subscriptions[destination_name] = Subscription.new(destination_name, message_headers)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# destination_name string, headers hash
|
61
|
+
# unsubscribe to listen on a destination
|
62
|
+
def unsubscribe destination_name, message_headers={}
|
63
|
+
subscriptions[destination_name].remove
|
64
|
+
subscriptions.delete(destination_name) if subscriptions[destination_name].count <= 0
|
65
|
+
end
|
66
|
+
|
67
|
+
# destination_name string, body string, headers hash
|
68
|
+
# send a single message to a destination
|
69
|
+
def send destination_name, message_body, message_headers={}
|
70
|
+
dest = get_or_create_destination(destination_name)
|
71
|
+
begin
|
72
|
+
dest.put message_body, message_headers
|
73
|
+
rescue Object=>err
|
74
|
+
raise err unless reliable
|
75
|
+
puts "send failed, will retry in #{@poll_interval} seconds"
|
76
|
+
sleep @poll_interval
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_or_create_destination destination_name, message_headers={}
|
81
|
+
return destinations[destination_name] if destinations.has_key? destination_name
|
82
|
+
dd = /^\/(queue|topic)\/(.*)$/.match(destination_name)
|
83
|
+
rm_class = dd[1].titleize
|
84
|
+
message_headers.delete("id")
|
85
|
+
dest_headers = message_headers.reject {|k,v| rm_class == 'Queue' ? !QUEUE_PARAMS.include?(k) : !TOPIC_PARAMS.include?(k)}
|
86
|
+
rm_dest = "ReliableMsg::#{rm_class}".constantize.new(dd[2], dest_headers)
|
87
|
+
destinations[destination_name] = rm_dest
|
88
|
+
end
|
89
|
+
|
90
|
+
# receive a single message from any of the subscribed destinations
|
91
|
+
# check each destination once, then sleep for poll_interval
|
92
|
+
def receive
|
93
|
+
|
94
|
+
raise "No subscriptions to receive messages from." if (subscriptions.nil? || subscriptions.empty?)
|
95
|
+
start = current_subscription
|
96
|
+
while true
|
97
|
+
self.current_subscription = ((current_subscription < subscriptions.length-1) ? current_subscription + 1 : 0)
|
98
|
+
sleep poll_interval if (current_subscription == start)
|
99
|
+
destination_name = subscriptions.keys.sort[current_subscription]
|
100
|
+
destination = destinations[destination_name]
|
101
|
+
unless destination.nil?
|
102
|
+
# from the way we use this, assume this is the start of a transaction,
|
103
|
+
# there should be no current transaction
|
104
|
+
ctx = Thread.current[::ReliableMsg::Client::THREAD_CURRENT_TX]
|
105
|
+
raise "There should not be an existing reliable-msg transaction. #{ctx.inspect}" if ctx
|
106
|
+
|
107
|
+
# start a new transaction
|
108
|
+
@tx = {:qm=>destination.queue_manager}
|
109
|
+
@tx[:tid] = @tx[:qm].begin @tx_timeout
|
110
|
+
Thread.current[::ReliableMsg::Client::THREAD_CURRENT_TX] = @tx
|
111
|
+
begin
|
112
|
+
|
113
|
+
# now call a get on the destination - it will use the transaction
|
114
|
+
#the commit or the abort will occur in the received or unreceive methods
|
115
|
+
reliable_msg = destination.get subscriptions[destination_name].headers[:selector]
|
116
|
+
@tx[:qm].commit(@tx[:tid]) if reliable_msg.nil?
|
117
|
+
|
118
|
+
rescue Object=>err
|
119
|
+
#abort the transaction on error
|
120
|
+
@tx[:qm].abort(@tx[:tid])
|
121
|
+
|
122
|
+
raise err unless reliable
|
123
|
+
puts "receive failed, will retry in #{@poll_interval} seconds"
|
124
|
+
sleep poll_interval
|
125
|
+
end
|
126
|
+
return Message.new(reliable_msg.id, reliable_msg.object, reliable_msg.headers, destination_name, 'MESSAGE', @tx) if reliable_msg
|
127
|
+
|
128
|
+
Thread.current[::ReliableMsg::Client::THREAD_CURRENT_TX] = nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# called after a message is successfully received and processed
|
134
|
+
def received message, headers={}
|
135
|
+
begin
|
136
|
+
message.transaction[:qm].commit(message.transaction[:tid])
|
137
|
+
rescue Object=>ex
|
138
|
+
puts "received failed: #{ex.message}"
|
139
|
+
ensure
|
140
|
+
Thread.current[::ReliableMsg::Client::THREAD_CURRENT_TX] = nil
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
# called after a message is successfully received and processed
|
146
|
+
def unreceive message, headers={}
|
147
|
+
begin
|
148
|
+
message.transaction[:qm].abort(message.transaction[:tid])
|
149
|
+
rescue Object=>ex
|
150
|
+
puts "unreceive failed: #{ex.message}"
|
151
|
+
ensure
|
152
|
+
Thread.current[::ReliableMsg::Client::THREAD_CURRENT_TX] = nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
class Subscription
|
159
|
+
attr_accessor :name, :headers, :count
|
160
|
+
|
161
|
+
def initialize(destination, headers={}, count=1)
|
162
|
+
@destination, @headers, @count = destination, headers, count
|
163
|
+
end
|
164
|
+
|
165
|
+
def add
|
166
|
+
@count += 1
|
167
|
+
end
|
168
|
+
|
169
|
+
def remove
|
170
|
+
@count -= 1
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
class Message
|
176
|
+
attr_accessor :id, :body, :headers, :command, :transaction
|
177
|
+
|
178
|
+
def initialize id, body, headers, destination_name, command='MESSAGE', transaction=nil
|
179
|
+
@id, @body, @headers, @command, @transaction = id, body, headers, command, transaction
|
180
|
+
headers['destination'] = destination_name
|
181
|
+
end
|
182
|
+
|
183
|
+
def to_s
|
184
|
+
"<ReliableMessaging::Message id='#{id}' body='#{body}' headers='#{headers.inspect}' command='#{command}' >"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|