rservicebus2 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE +64 -0
- data/bin/return_messages_to_source_queue +114 -0
- data/bin/rsb_ctl +38 -0
- data/bin/rservicebus2 +14 -0
- data/bin/rservicebus2-create +107 -0
- data/bin/rservicebus2-init +104 -0
- data/bin/rservicebus2-transport +16 -0
- data/bin/send_empty_message +15 -0
- data/lib/rservicebus.rb +59 -0
- data/lib/rservicebus/agent.rb +54 -0
- data/lib/rservicebus/appresource.rb +65 -0
- data/lib/rservicebus/appresource/dir.rb +29 -0
- data/lib/rservicebus/appresource/file.rb +8 -0
- data/lib/rservicebus/appresource/fluiddb.rb +24 -0
- data/lib/rservicebus/appresource_configure.rb +33 -0
- data/lib/rservicebus/audit.rb +28 -0
- data/lib/rservicebus/circuitbreaker.rb +79 -0
- data/lib/rservicebus/config.rb +168 -0
- data/lib/rservicebus/cron_manager.rb +76 -0
- data/lib/rservicebus/endpointmapping.rb +72 -0
- data/lib/rservicebus/errormessage.rb +14 -0
- data/lib/rservicebus/handler_loader.rb +162 -0
- data/lib/rservicebus/handler_manager.rb +131 -0
- data/lib/rservicebus/helper_functions.rb +85 -0
- data/lib/rservicebus/host.rb +487 -0
- data/lib/rservicebus/message.rb +78 -0
- data/lib/rservicebus/message/statisticoutput.rb +7 -0
- data/lib/rservicebus/message/subscription.rb +10 -0
- data/lib/rservicebus/message/verboseoutput.rb +7 -0
- data/lib/rservicebus/monitor.rb +61 -0
- data/lib/rservicebus/monitor/csvdir.rb +52 -0
- data/lib/rservicebus/monitor/dir.rb +139 -0
- data/lib/rservicebus/monitor/dirnotifier.rb +101 -0
- data/lib/rservicebus/monitor/message.rb +11 -0
- data/lib/rservicebus/monitor/xmldir.rb +11 -0
- data/lib/rservicebus/monitor_configure.rb +71 -0
- data/lib/rservicebus/mq.rb +98 -0
- data/lib/rservicebus/mq/beanstalk.rb +72 -0
- data/lib/rservicebus/resource_manager.rb +69 -0
- data/lib/rservicebus/saga/base.rb +17 -0
- data/lib/rservicebus/saga/data.rb +20 -0
- data/lib/rservicebus/saga/manager.rb +128 -0
- data/lib/rservicebus/saga_loader.rb +118 -0
- data/lib/rservicebus/saga_storage.rb +18 -0
- data/lib/rservicebus/saga_storage/dir.rb +87 -0
- data/lib/rservicebus/saga_storage/inmemory.rb +37 -0
- data/lib/rservicebus/sendat_manager.rb +33 -0
- data/lib/rservicebus/sendat_storage.rb +20 -0
- data/lib/rservicebus/sendat_storage/file.rb +37 -0
- data/lib/rservicebus/sendat_storage/inmemory.rb +20 -0
- data/lib/rservicebus/state_manager.rb +30 -0
- data/lib/rservicebus/state_storage.rb +18 -0
- data/lib/rservicebus/state_storage/dir.rb +66 -0
- data/lib/rservicebus/state_storage/inmemory.rb +25 -0
- data/lib/rservicebus/statistic_manager.rb +86 -0
- data/lib/rservicebus/stats.rb +68 -0
- data/lib/rservicebus/subscription_manager.rb +31 -0
- data/lib/rservicebus/subscription_storage.rb +39 -0
- data/lib/rservicebus/subscription_storage/file.rb +42 -0
- data/lib/rservicebus/subscription_storage/redis.rb +69 -0
- data/lib/rservicebus/subscription_storage_configure.rb +19 -0
- data/lib/rservicebus/test.rb +2 -0
- data/lib/rservicebus/test/bus.rb +32 -0
- data/lib/rservicebus/transporter.rb +142 -0
- data/lib/rservicebus/usermessage/withpayload.rb +10 -0
- metadata +184 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
module RServiceBus
|
2
|
+
def self.convert_dto_to_hash(obj)
|
3
|
+
hash = {}
|
4
|
+
obj.instance_variables.each do |var|
|
5
|
+
hash[var.to_s.delete('@')] = obj.instance_variable_get(var)
|
6
|
+
end
|
7
|
+
hash
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.convert_dto_to_json(obj)
|
11
|
+
convert_dto_to_hash(obj).to_json
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.log(string, ver = false)
|
15
|
+
return if check_environment_variable('TESTING')
|
16
|
+
|
17
|
+
type = ver ? 'VERB' : 'INFO'
|
18
|
+
if check_environment_variable('VERBOSE') || !ver
|
19
|
+
timestamp = Time.new.strftime('%Y-%m-%d %H:%M:%S')
|
20
|
+
puts "[#{type}] #{timestamp} :: #{string}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.rlog(string)
|
25
|
+
return unless check_environment_variable('RSBVERBOSE')
|
26
|
+
|
27
|
+
timestamp = Time.new.strftime('%Y-%m-%d %H:%M:%S')
|
28
|
+
puts "[RSB] #{timestamp} :: #{string}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create_anonymous_class(name_for_class)
|
32
|
+
new_anonymous_class = Class.new(Object)
|
33
|
+
Object.const_set(name_for_class, new_anonymous_class)
|
34
|
+
Object.const_get(name_for_class).new
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.get_value(name, default = nil)
|
38
|
+
value = (ENV[name].nil? || ENV[name] == '') ? default : ENV[name]
|
39
|
+
log "Env value: #{name}: #{value}"
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.send_msg(msg, response_queue = 'agent')
|
44
|
+
require 'rservicebus/endpointmapping'
|
45
|
+
endpoint_mapping = EndpointMapping.new
|
46
|
+
endpoint_mapping.configure
|
47
|
+
queue_name = endpoint_mapping.get(msg.class.name)
|
48
|
+
|
49
|
+
ENV['RSBMQ'] = 'beanstalk://localhost' if ENV['RSBMQ'].nil?
|
50
|
+
agent = RServiceBus::Agent.new
|
51
|
+
Audit.new(agent).audit_to_queue(msg)
|
52
|
+
agent.send_msg(msg, queue_name, response_queue)
|
53
|
+
|
54
|
+
rescue QueueNotFoundForMsg => e
|
55
|
+
msg = "\n"
|
56
|
+
msg = "#{msg}*** Queue not found for, #{e.message}\n"
|
57
|
+
msg = "#{msg}*** Ensure you have an environment variable set for this
|
58
|
+
Message Type, eg, \n"
|
59
|
+
msg = "#{msg}*** MESSAGE_ENDPOINT_MAPPINGS=#{e.message}:<QueueName>\n"
|
60
|
+
raise StandardError, msg
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.check_for_reply(queue_name)
|
64
|
+
ENV['RSBMQ'] = 'beanstalk://localhost' if ENV['RSBMQ'].nil?
|
65
|
+
agent = RServiceBus::Agent.new
|
66
|
+
msg = agent.check_for_reply(queue_name)
|
67
|
+
Audit.new(agent).audit_incoming(msg)
|
68
|
+
|
69
|
+
msg
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.tick(string)
|
73
|
+
puts "[TICK] #{Time.new.strftime('%Y-%m-%d %H:%M:%S.%6N')} ::
|
74
|
+
#{caller[0]}. #{string}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.check_environment_variable(string)
|
78
|
+
return false if ENV[string].nil?
|
79
|
+
return true if ENV[string] == true || ENV[string] =~ (/(true|t|yes|y|1)$/i)
|
80
|
+
return false if ENV[string] == false ||
|
81
|
+
ENV[string].nil? ||
|
82
|
+
ENV[string] =~ (/(false|f|no|n|0)$/i)
|
83
|
+
fail ArgumentError, "invalid value for Environment Variable: \"#{string}\""
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,487 @@
|
|
1
|
+
module RServiceBus
|
2
|
+
class NoHandlerFound < StandardError
|
3
|
+
end
|
4
|
+
class ClassNotFoundForMsg < StandardError
|
5
|
+
end
|
6
|
+
class NoMsgToProcess < StandardError
|
7
|
+
end
|
8
|
+
class PropertyNotSet < StandardError
|
9
|
+
end
|
10
|
+
|
11
|
+
# Host process for rservicebus
|
12
|
+
class Host
|
13
|
+
attr_accessor :sagaData
|
14
|
+
|
15
|
+
# Provides a thin logging veneer
|
16
|
+
# @param [String] string Log entry
|
17
|
+
# @param [Boolean] ver Indicator for a verbose log entry
|
18
|
+
def log(string, ver = false)
|
19
|
+
RServiceBus.log(string, ver)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Thin veneer for Configuring external resources
|
23
|
+
def configure_app_resource
|
24
|
+
@resource_manager = ConfigureAppResource.new
|
25
|
+
.get_resources(ENV,
|
26
|
+
self,
|
27
|
+
@state_manager,
|
28
|
+
@saga_storage)
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
# Thin veneer for Configuring SendAt
|
33
|
+
def configure_send_at_manager
|
34
|
+
@send_at_manager = SendAtManager.new(self)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Thin veneer for Configuring state
|
39
|
+
def configure_state_manager
|
40
|
+
@state_manager = StateManager.new
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# Thin veneer for Configuring state
|
45
|
+
def configure_saga_storage
|
46
|
+
string = RServiceBus.get_value('SAGA_URI')
|
47
|
+
string = 'dir:///tmp' if string.nil?
|
48
|
+
|
49
|
+
uri = URI.parse(string)
|
50
|
+
@saga_storage = SagaStorage.get(uri)
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
# Thin veneer for Configuring Cron
|
55
|
+
def configure_circuit_breaker
|
56
|
+
@circuit_breaker = CircuitBreaker.new(self)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
# Thin veneer for Configuring external resources
|
61
|
+
def configure_monitors
|
62
|
+
@monitors = ConfigureMonitor.new(self, @resource_manager).get_monitors(ENV)
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# Thin veneer for Configuring the Message Queue
|
67
|
+
def connect_to_mq
|
68
|
+
@mq = MQ.get
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
# Subscriptions are specified by adding events to the
|
73
|
+
# msg endpoint mapping
|
74
|
+
def send_subscriptions
|
75
|
+
log 'Send Subscriptions'
|
76
|
+
|
77
|
+
@endpoint_mapping.get_subscription_endpoints.each do |event_name|
|
78
|
+
subscribe(event_name)
|
79
|
+
end
|
80
|
+
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
# Load and configure Message Handlers
|
85
|
+
def load_handlers
|
86
|
+
log 'Load Message Handlers'
|
87
|
+
@handler_manager = HandlerManager.new(self, @resource_manager, @state_manager)
|
88
|
+
@handler_loader = HandlerLoader.new(self, @handler_manager)
|
89
|
+
|
90
|
+
@config.handler_path_list.each do |path|
|
91
|
+
@handler_loader.load_handlers_from_path(path)
|
92
|
+
end
|
93
|
+
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
# Load and configure Sagas
|
98
|
+
def load_sagas
|
99
|
+
log 'Load Sagas'
|
100
|
+
@saga_manager = SagaManager.new(self, @resource_manager, @saga_storage)
|
101
|
+
@saga_loader = SagaLoader.new(self, @saga_manager)
|
102
|
+
|
103
|
+
@config.saga_path_list.each do |path|
|
104
|
+
@saga_loader.load_sagas_from_path(path)
|
105
|
+
end
|
106
|
+
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
# Thin veneer for Configuring Cron
|
111
|
+
def configure_cron_manager
|
112
|
+
@cron_manager = CronManager.new(self, @handler_manager.get_list_of_msg_names)
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
# Load Contracts
|
117
|
+
def load_contracts
|
118
|
+
log 'Load Contracts'
|
119
|
+
|
120
|
+
@config.contract_list.each do |path|
|
121
|
+
require path
|
122
|
+
RServiceBus.rlog "Loaded Contract: #{path}"
|
123
|
+
end
|
124
|
+
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
# For each directory given, find and load all librarys
|
129
|
+
def load_libs
|
130
|
+
log 'Load Libs'
|
131
|
+
@config.lib_list.each do |path|
|
132
|
+
$:.unshift path
|
133
|
+
end
|
134
|
+
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
# Load, configure and initialise Subscriptions
|
139
|
+
def configure_subscriptions
|
140
|
+
subscription_storage = ConfigureSubscriptionStorage.new.get(@config.app_name, @config.subscription_uri)
|
141
|
+
@subscription_manager = SubscriptionManager.new(subscription_storage)
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
145
|
+
# Initialise statistics monitor
|
146
|
+
def configure_statistics
|
147
|
+
@stats = StatisticManager.new( self )
|
148
|
+
self
|
149
|
+
end
|
150
|
+
|
151
|
+
def initialize
|
152
|
+
RServiceBus.rlog "Current directory: #{Dir.pwd}"
|
153
|
+
@config = ConfigFromEnv.new.load_host_section
|
154
|
+
.load_contracts
|
155
|
+
.load_handler_path_list
|
156
|
+
.load_saga_path_list
|
157
|
+
.load_libs
|
158
|
+
.load_working_dir_list
|
159
|
+
|
160
|
+
connect_to_mq
|
161
|
+
|
162
|
+
@endpoint_mapping = EndpointMapping.new.configure(@mq.local_queue_name)
|
163
|
+
|
164
|
+
self.configure_statistics
|
165
|
+
.load_contracts
|
166
|
+
.load_libs
|
167
|
+
.configure_send_at_manager
|
168
|
+
.configure_state_manager
|
169
|
+
.configure_saga_storage
|
170
|
+
.configure_app_resource
|
171
|
+
.configure_circuit_breaker
|
172
|
+
.configure_monitors
|
173
|
+
.load_handlers
|
174
|
+
.load_sagas
|
175
|
+
.configure_cron_manager
|
176
|
+
.configure_subscriptions
|
177
|
+
.send_subscriptions
|
178
|
+
|
179
|
+
self
|
180
|
+
end
|
181
|
+
|
182
|
+
# Ignition
|
183
|
+
def run
|
184
|
+
log 'Starting the Host'
|
185
|
+
log "Watching, #{@mq.local_queue_name}"
|
186
|
+
$0 = "rservicebus - #{@mq.local_queue_name}"
|
187
|
+
unless @config.forward_received_messages_to.nil?
|
188
|
+
log 'Forwarding all received messages to: ' + @config.forward_received_messages_to.to_s
|
189
|
+
end
|
190
|
+
unless @config.forward_sent_messages_to.nil?
|
191
|
+
log 'Forwarding all sent messages to: ' + @config.forward_sent_messages_to.to_s
|
192
|
+
end
|
193
|
+
|
194
|
+
start_listening_to_endpoints
|
195
|
+
end
|
196
|
+
|
197
|
+
# Receive a msg, prep it, and handle any errors that may occur
|
198
|
+
# - Most of this should be queue independant
|
199
|
+
def start_listening_to_endpoints
|
200
|
+
log 'Waiting for messages. To exit press CTRL+C'
|
201
|
+
message_loop = true
|
202
|
+
retries = @config.max_retries
|
203
|
+
|
204
|
+
while message_loop
|
205
|
+
# Popping a msg off the queue should not be in the message handler,
|
206
|
+
# as it affects retry
|
207
|
+
begin
|
208
|
+
@stats.tick
|
209
|
+
if @circuit_breaker.broken
|
210
|
+
sleep 0.5
|
211
|
+
next
|
212
|
+
end
|
213
|
+
|
214
|
+
body = @mq.pop
|
215
|
+
begin
|
216
|
+
@stats.inc_total_processed
|
217
|
+
@msg = YAML.load(body)
|
218
|
+
case @msg.msg.class.name
|
219
|
+
when 'RServiceBus::MessageSubscription'
|
220
|
+
@subscription_manager.add(@msg.msg.event_name,
|
221
|
+
@msg.return_address)
|
222
|
+
when 'RServiceBus::MessageStatisticOutputOn'
|
223
|
+
@stats.output = true
|
224
|
+
log 'Turn on Stats logging'
|
225
|
+
when 'RServiceBus::MessageStatisticOutputOff'
|
226
|
+
@stats.output = false
|
227
|
+
log 'Turn off Stats logging'
|
228
|
+
when 'RServiceBus::MessageVerboseOutputOn'
|
229
|
+
ENV['VERBOSE'] = 'true'
|
230
|
+
log 'Turn on Verbose logging'
|
231
|
+
when 'RServiceBus::MessageVerboseOutputOff'
|
232
|
+
ENV.delete('VERBOSE')
|
233
|
+
log 'Turn off Verbose logging'
|
234
|
+
else
|
235
|
+
handle_message
|
236
|
+
unless @config.forward_received_messages_to.nil?
|
237
|
+
_send_already_wrapped_and_serialised(body, @config.forward_received_messages_to)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
@mq.ack
|
241
|
+
rescue ClassNotFoundForMsg => e
|
242
|
+
puts "*** Class not found for msg, #{e.message}"
|
243
|
+
puts "*** Ensure, #{e.message}, is defined in Contract.rb, most
|
244
|
+
likely as 'Class #{e.message} end"
|
245
|
+
|
246
|
+
@msg.add_error_msg(@mq.local_queue_name, e.message)
|
247
|
+
serialized_object = YAML.dump(@msg)
|
248
|
+
_send_already_wrapped_and_serialised(serialized_object,
|
249
|
+
@config.error_queue_name)
|
250
|
+
@mq.ack
|
251
|
+
rescue NoHandlerFound => e
|
252
|
+
puts "*** Handler not found for msg, #{e.message}"
|
253
|
+
puts "*** Ensure a handler named, #{e.message}, is present in the
|
254
|
+
MessageHandler directory."
|
255
|
+
|
256
|
+
@msg.add_error_msg(@mq.local_queue_name, e.message)
|
257
|
+
serialized_object = YAML.dump(@msg)
|
258
|
+
_send_already_wrapped_and_serialised(serialized_object,
|
259
|
+
@config.error_queue_name)
|
260
|
+
@mq.ack
|
261
|
+
|
262
|
+
rescue PropertyNotSet => e
|
263
|
+
# This has been re-rasied from a rescue in the handler
|
264
|
+
puts "*** #{e.message}"
|
265
|
+
# "Property, #{e.message}, not set for, #{handler.class.name}"
|
266
|
+
property_name = e.message[10, e.message.index(',', 10) - 10]
|
267
|
+
puts "*** Ensure the environment variable, RSB_#{property_name},
|
268
|
+
has been set at startup."
|
269
|
+
|
270
|
+
rescue StandardError => e
|
271
|
+
sleep 0.5
|
272
|
+
|
273
|
+
puts '*** Exception occurred'
|
274
|
+
puts e.message
|
275
|
+
puts e.backtrace
|
276
|
+
puts '***'
|
277
|
+
|
278
|
+
if retries > 0
|
279
|
+
retries -= 1
|
280
|
+
@mq.return_to_queue
|
281
|
+
else
|
282
|
+
@circuit_breaker.failure
|
283
|
+
@stats.inc_total_errored
|
284
|
+
if e.class.name == 'Beanstalk::NotConnected'
|
285
|
+
puts 'Lost connection to beanstalkd.'
|
286
|
+
puts '*** Start or Restart beanstalkd and try again.'
|
287
|
+
abort
|
288
|
+
end
|
289
|
+
|
290
|
+
if e.class.name == 'Redis::CannotConnectError'
|
291
|
+
puts 'Lost connection to redis.'
|
292
|
+
puts '*** Start or Restart redis and try again.'
|
293
|
+
abort
|
294
|
+
end
|
295
|
+
|
296
|
+
error_string = e.message + '. ' + e.backtrace.join('. ')
|
297
|
+
@msg.add_error_msg(@mq.local_queue_name, error_string)
|
298
|
+
serialized_object = YAML.dump(@msg)
|
299
|
+
_send_already_wrapped_and_serialised(serialized_object, @config.error_queue_name)
|
300
|
+
@mq.ack
|
301
|
+
retries = @config.max_retries
|
302
|
+
end
|
303
|
+
end
|
304
|
+
rescue SystemExit, Interrupt
|
305
|
+
puts 'Exiting on request ...'
|
306
|
+
message_loop = false
|
307
|
+
rescue NoMsgToProcess => e
|
308
|
+
# This exception is just saying there are no messages to process
|
309
|
+
@queue_for_msgs_to_be_sent_on_complete = []
|
310
|
+
@monitors.each(&:look)
|
311
|
+
send_queued_msgs
|
312
|
+
@queue_for_msgs_to_be_sent_on_complete = nil
|
313
|
+
|
314
|
+
@queue_for_msgs_to_be_sent_on_complete = []
|
315
|
+
@cron_manager.run
|
316
|
+
send_queued_msgs
|
317
|
+
@queue_for_msgs_to_be_sent_on_complete = nil
|
318
|
+
|
319
|
+
@send_at_manager.process
|
320
|
+
@circuit_breaker.success
|
321
|
+
|
322
|
+
rescue StandardError => e
|
323
|
+
if e.message == 'SIGTERM' || e.message == 'SIGINT'
|
324
|
+
puts 'Exiting on request ...'
|
325
|
+
message_loop = false
|
326
|
+
else
|
327
|
+
puts '*** This is really unexpected.'
|
328
|
+
message_loop = false
|
329
|
+
puts 'Message: ' + e.message
|
330
|
+
puts e.backtrace
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# Send the current msg to the appropriate handlers
|
337
|
+
def handle_message
|
338
|
+
@resource_manager.begin
|
339
|
+
msg_name = @msg.msg.class.name
|
340
|
+
handler_list = @handler_manager.get_handler_list_for_msg(msg_name)
|
341
|
+
RServiceBus.rlog 'Handler found for: ' + msg_name
|
342
|
+
begin
|
343
|
+
@queue_for_msgs_to_be_sent_on_complete = []
|
344
|
+
|
345
|
+
log "Started processing msg, #{msg_name}"
|
346
|
+
handler_list.each do |handler|
|
347
|
+
begin
|
348
|
+
log "Handler, #{handler.class.name}, Started"
|
349
|
+
handler.handle(@msg.msg)
|
350
|
+
log "Handler, #{handler.class.name}, Finished"
|
351
|
+
rescue PropertyNotSet => e
|
352
|
+
raise PropertyNotSet.new( "Property, #{e.message}, not set for, #{handler.class.name}" )
|
353
|
+
rescue StandardError => e
|
354
|
+
puts "E #{e.message}"
|
355
|
+
log 'An error occurred in Handler: ' + handler.class.name
|
356
|
+
raise e
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
if @saga_manager.handle(@msg) == false && handler_list.length == 0
|
361
|
+
fail NoHandlerFound, msg_name
|
362
|
+
end
|
363
|
+
@resource_manager.commit(msg_name)
|
364
|
+
|
365
|
+
send_queued_msgs
|
366
|
+
log "Finished processing msg, #{msg_name}"
|
367
|
+
|
368
|
+
rescue StandardError => e
|
369
|
+
@resource_manager.rollback(msg_name)
|
370
|
+
@queue_for_msgs_to_be_sent_on_complete = nil
|
371
|
+
raise e
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
#######################################################################################################
|
376
|
+
# All msg sending Methods
|
377
|
+
|
378
|
+
# Sends a msg across the bus
|
379
|
+
# @param [String] serialized_object serialized RServiceBus::Message
|
380
|
+
# @param [String] queue_name endpoint to which the msg will be sent
|
381
|
+
def _send_already_wrapped_and_serialised(serialized_object, queue_name)
|
382
|
+
RServiceBus.rlog 'Bus._send_already_wrapped_and_serialised'
|
383
|
+
|
384
|
+
unless @config.forward_sent_messages_to.nil?
|
385
|
+
@mq.send(@config.forward_sent_messages_to, serialized_object)
|
386
|
+
end
|
387
|
+
|
388
|
+
@mq.send(queue_name, serialized_object)
|
389
|
+
end
|
390
|
+
|
391
|
+
# Sends a msg across the bus
|
392
|
+
# @param [RServiceBus::Message] msg msg to be sent
|
393
|
+
# @param [String] queueName endpoint to which the msg will be sent
|
394
|
+
def _send_needs_wrapping(msg, queue_name, correlation_id)
|
395
|
+
RServiceBus.rlog 'Bus._send_needs_wrapping'
|
396
|
+
|
397
|
+
r_msg = RServiceBus::Message.new(msg, @mq.local_queue_name, correlation_id)
|
398
|
+
if queue_name.index('@').nil?
|
399
|
+
q = queue_name
|
400
|
+
RServiceBus.rlog "Sending, #{msg.class.name} to, #{queue_name}"
|
401
|
+
else
|
402
|
+
parts = queue_name.split('@')
|
403
|
+
r_msg.set_remote_queue_name(parts[0])
|
404
|
+
r_msg.set_remote_host_name(parts[1])
|
405
|
+
q = 'transport-out'
|
406
|
+
RServiceBus.rlog "Sending, #{msg.class.name} to, #{queue_name}, via #{q}"
|
407
|
+
end
|
408
|
+
|
409
|
+
serialized_object = YAML.dump(r_msg)
|
410
|
+
_send_already_wrapped_and_serialised(serialized_object, q)
|
411
|
+
end
|
412
|
+
|
413
|
+
def send_queued_msgs
|
414
|
+
@queue_for_msgs_to_be_sent_on_complete.each do |row|
|
415
|
+
if row['timestamp'].nil?
|
416
|
+
_send_needs_wrapping(row['msg'], row['queue_name'], row['correlation_id'])
|
417
|
+
else
|
418
|
+
@send_at_manager.add(row)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
def queue_msg_for_send_on_complete(msg, queue_name, timestamp = nil)
|
424
|
+
correlation_id = @saga_data.nil? ? nil : @saga_data.correlation_id
|
425
|
+
correlation_id = (!@msg.nil? && !@msg.correlation_id.nil?) ? @msg.correlation_id : correlation_id
|
426
|
+
@queue_for_msgs_to_be_sent_on_complete << Hash['msg', msg, 'queue_name', queue_name, 'correlation_id', correlation_id, 'timestamp',timestamp ]
|
427
|
+
end
|
428
|
+
|
429
|
+
# Sends a msg back across the bus
|
430
|
+
# Reply queues are specified in each msg. It works like
|
431
|
+
# email, where the reply address can actually be anywhere
|
432
|
+
# @param [RServiceBus::Message] msg msg to be sent
|
433
|
+
def reply(msg)
|
434
|
+
RServiceBus.rlog 'Reply with: ' + msg.class.name + ' To: ' + @msg.return_address
|
435
|
+
@stats.inc_total_reply
|
436
|
+
|
437
|
+
queue_msg_for_send_on_complete(msg, @msg.return_address)
|
438
|
+
end
|
439
|
+
|
440
|
+
def get_endpoint_for_msg(msg_name)
|
441
|
+
queue_name = @endpoint_mapping.get(msg_name)
|
442
|
+
return queue_name unless queue_name.nil?
|
443
|
+
|
444
|
+
return @mq.local_queue_name if @handler_manager.can_msg_be_handled_locally(msg_name)
|
445
|
+
|
446
|
+
log 'No end point mapping found for: ' + msg_name
|
447
|
+
log '**** Check environment variable MessageEndpointMappings contains an entry named : ' + msg_name
|
448
|
+
raise 'No end point mapping found for: ' + msg_name
|
449
|
+
end
|
450
|
+
|
451
|
+
|
452
|
+
# Send a msg across the bus
|
453
|
+
# msg destination is specified at the infrastructure level
|
454
|
+
# @param [RServiceBus::Message] msg msg to be sent
|
455
|
+
def send( msg, timestamp=nil )
|
456
|
+
RServiceBus.rlog 'Bus.Send'
|
457
|
+
@stats.inc_total_sent
|
458
|
+
|
459
|
+
msg_name = msg.class.name
|
460
|
+
queue_name = self.get_endpoint_for_msg(msg_name)
|
461
|
+
queue_msg_for_send_on_complete(msg, queue_name, timestamp)
|
462
|
+
end
|
463
|
+
|
464
|
+
# Sends an event to all subscribers across the bus
|
465
|
+
# @param [RServiceBus::Message] msg msg to be sent
|
466
|
+
def publish(msg)
|
467
|
+
RServiceBus.rlog 'Bus.Publish'
|
468
|
+
@stats.inc_total_published
|
469
|
+
|
470
|
+
subscriptions = @subscription_manager.get(msg.class.name)
|
471
|
+
subscriptions.each do |subscriber|
|
472
|
+
queue_msg_for_send_on_complete(msg, subscriber)
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
# Sends a subscription request across the Bus
|
477
|
+
# @param [String] eventName event to be subscribes to
|
478
|
+
def subscribe(event_name)
|
479
|
+
RServiceBus.rlog 'Bus.Subscribe: ' + event_name
|
480
|
+
|
481
|
+
queue_name = get_endpoint_for_msg(event_name)
|
482
|
+
subscription = MessageSubscription.new(event_name)
|
483
|
+
|
484
|
+
_send_needs_wrapping(subscription, queue_name, nil)
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|