activemessaging 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|