rservicebus 0.0.01 → 0.0.2
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/LICENSE +1 -1
- data/README.md +48 -0
- data/bin/{rservicebus2 → rservicebus} +2 -1
- data/lib/rservicebus.rb +15 -54
- data/lib/rservicebus/Agent.rb +21 -0
- data/lib/rservicebus/Config.rb +125 -0
- data/lib/rservicebus/ErrorMessage.rb +14 -0
- data/lib/rservicebus/HandlerLoader.rb +100 -0
- data/lib/rservicebus/Host.rb +340 -0
- data/lib/rservicebus/Message.rb +29 -0
- data/lib/rservicebus/Subscription.rb +13 -0
- data/lib/rservicebus/helper_functions.rb +8 -81
- metadata +23 -150
- checksums.yaml +0 -7
- data/bin/return_messages_to_source_queue +0 -114
- data/bin/rsb_ctl +0 -38
- data/bin/rservicebus2-create +0 -107
- data/bin/rservicebus2-init +0 -104
- data/bin/rservicebus2-transport +0 -16
- data/bin/send_empty_message +0 -15
- data/lib/rservicebus/agent.rb +0 -54
- data/lib/rservicebus/appresource.rb +0 -65
- data/lib/rservicebus/appresource/dir.rb +0 -29
- data/lib/rservicebus/appresource/file.rb +0 -8
- data/lib/rservicebus/appresource/fluiddb.rb +0 -24
- data/lib/rservicebus/appresource_configure.rb +0 -33
- data/lib/rservicebus/audit.rb +0 -28
- data/lib/rservicebus/circuitbreaker.rb +0 -79
- data/lib/rservicebus/config.rb +0 -168
- data/lib/rservicebus/cron_manager.rb +0 -76
- data/lib/rservicebus/endpointmapping.rb +0 -72
- data/lib/rservicebus/errormessage.rb +0 -14
- data/lib/rservicebus/handler_loader.rb +0 -162
- data/lib/rservicebus/handler_manager.rb +0 -131
- data/lib/rservicebus/host.rb +0 -487
- data/lib/rservicebus/message.rb +0 -78
- data/lib/rservicebus/message/statisticoutput.rb +0 -7
- data/lib/rservicebus/message/subscription.rb +0 -10
- data/lib/rservicebus/message/verboseoutput.rb +0 -7
- data/lib/rservicebus/monitor.rb +0 -61
- data/lib/rservicebus/monitor/csvdir.rb +0 -52
- data/lib/rservicebus/monitor/dir.rb +0 -139
- data/lib/rservicebus/monitor/dirnotifier.rb +0 -101
- data/lib/rservicebus/monitor/message.rb +0 -11
- data/lib/rservicebus/monitor/xmldir.rb +0 -11
- data/lib/rservicebus/monitor_configure.rb +0 -71
- data/lib/rservicebus/mq.rb +0 -98
- data/lib/rservicebus/mq/beanstalk.rb +0 -72
- data/lib/rservicebus/resource_manager.rb +0 -69
- data/lib/rservicebus/saga/base.rb +0 -17
- data/lib/rservicebus/saga/data.rb +0 -20
- data/lib/rservicebus/saga/manager.rb +0 -128
- data/lib/rservicebus/saga_loader.rb +0 -118
- data/lib/rservicebus/saga_storage.rb +0 -18
- data/lib/rservicebus/saga_storage/dir.rb +0 -87
- data/lib/rservicebus/saga_storage/inmemory.rb +0 -37
- data/lib/rservicebus/sendat_manager.rb +0 -33
- data/lib/rservicebus/sendat_storage.rb +0 -20
- data/lib/rservicebus/sendat_storage/file.rb +0 -37
- data/lib/rservicebus/sendat_storage/inmemory.rb +0 -20
- data/lib/rservicebus/state_manager.rb +0 -30
- data/lib/rservicebus/state_storage.rb +0 -18
- data/lib/rservicebus/state_storage/dir.rb +0 -66
- data/lib/rservicebus/state_storage/inmemory.rb +0 -25
- data/lib/rservicebus/statistic_manager.rb +0 -86
- data/lib/rservicebus/stats.rb +0 -68
- data/lib/rservicebus/subscription_manager.rb +0 -31
- data/lib/rservicebus/subscription_storage.rb +0 -39
- data/lib/rservicebus/subscription_storage/file.rb +0 -42
- data/lib/rservicebus/subscription_storage/redis.rb +0 -69
- data/lib/rservicebus/subscription_storage_configure.rb +0 -19
- data/lib/rservicebus/test.rb +0 -2
- data/lib/rservicebus/test/bus.rb +0 -32
- data/lib/rservicebus/transporter.rb +0 -142
- data/lib/rservicebus/usermessage/withpayload.rb +0 -10
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
RServiceBus is copyrighted free software by all contributors, see logs in
|
2
2
|
revision control for names and email addresses of all of them.
|
3
3
|
|
4
4
|
You can redistribute it and/or modify it under either the terms of the
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#RServiceBus
|
2
|
+
|
3
|
+
A Ruby implementation of NServiceBus
|
4
|
+
|
5
|
+
Where I started this project to increase my knowledge of NServiceBus, it is now
|
6
|
+
proving to be a workable framework.
|
7
|
+
|
8
|
+
|
9
|
+
##Principles
|
10
|
+
*Why are you doing it and what can go wrong
|
11
|
+
*Dont solve infrastructure problems with software
|
12
|
+
*Infrastructure in this case refers to anything not specific to the application domain
|
13
|
+
|
14
|
+
##Points of view in the framework
|
15
|
+
* Bus
|
16
|
+
* Handler
|
17
|
+
* Client
|
18
|
+
|
19
|
+
#Platform
|
20
|
+
* Messages
|
21
|
+
* MessageHandler
|
22
|
+
* MessageHandling
|
23
|
+
* Queues
|
24
|
+
* Transport
|
25
|
+
* Transactions
|
26
|
+
|
27
|
+
##Message
|
28
|
+
* Yaml
|
29
|
+
* Unique Message ID's
|
30
|
+
|
31
|
+
##Queues
|
32
|
+
* Durable
|
33
|
+
* Store & Forward
|
34
|
+
* Queues specified by config, determined by message type
|
35
|
+
|
36
|
+
##Transport
|
37
|
+
* RabbitMQ
|
38
|
+
|
39
|
+
##MessageHandler
|
40
|
+
* Name by convention - Handler name matchs filename
|
41
|
+
* Handlers are dynamically loaded
|
42
|
+
* If a handler fails to load, the service wont start - infrastructure problem
|
43
|
+
|
44
|
+
##MessageHandling
|
45
|
+
* Transactions are good, use them
|
46
|
+
* Given transactions, the first to do on error is retry
|
47
|
+
* Once we've used up retry, put the message on an error queue to process later - it's a logic problem
|
48
|
+
|
data/lib/rservicebus.rb
CHANGED
@@ -1,59 +1,20 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require "rubygems"
|
2
|
+
require 'beanstalk-client'
|
3
|
+
require "yaml"
|
4
|
+
require "uuidtools"
|
5
|
+
require "redis"
|
6
|
+
require "json"
|
7
|
+
|
8
|
+
require "rservicebus/helper_functions"
|
9
|
+
require "rservicebus/Agent"
|
10
|
+
require "rservicebus/ErrorMessage"
|
11
|
+
require "rservicebus/Message"
|
12
|
+
require "rservicebus/Subscription"
|
13
|
+
require "rservicebus/HandlerLoader"
|
14
|
+
require "rservicebus/Host"
|
3
15
|
|
4
|
-
# Don't buffer stdout
|
5
|
-
$stdout.sync = true
|
6
16
|
|
7
|
-
|
8
|
-
require 'yaml'
|
9
|
-
require 'uuidtools'
|
10
|
-
require 'json'
|
11
|
-
require 'uri'
|
12
|
-
|
13
|
-
require 'rservicebus/helper_functions'
|
14
|
-
require 'rservicebus/errormessage'
|
15
|
-
require 'rservicebus/handler_loader'
|
16
|
-
require 'rservicebus/handler_manager'
|
17
|
-
require 'rservicebus/appresource_configure'
|
18
|
-
require 'rservicebus/mq'
|
19
|
-
require 'rservicebus/host'
|
20
|
-
require 'rservicebus/config'
|
21
|
-
require 'rservicebus/endpointmapping'
|
22
|
-
require 'rservicebus/stats'
|
23
|
-
require 'rservicebus/statistic_manager'
|
24
|
-
require 'rservicebus/audit'
|
25
|
-
|
26
|
-
require 'rservicebus/message'
|
27
|
-
require 'rservicebus/message/subscription'
|
28
|
-
require 'rservicebus/message/statisticoutput'
|
29
|
-
require 'rservicebus/message/verboseoutput'
|
30
|
-
|
31
|
-
require 'rservicebus/usermessage/withpayload'
|
32
|
-
|
33
|
-
require 'rservicebus/state_manager'
|
34
|
-
require 'rservicebus/cron_manager'
|
35
|
-
require 'rservicebus/circuitbreaker'
|
36
|
-
|
37
|
-
require 'rservicebus/appresource'
|
38
|
-
require 'rservicebus/resource_manager'
|
39
|
-
|
40
|
-
require 'rservicebus/subscription_manager'
|
41
|
-
require 'rservicebus/subscription_storage'
|
42
|
-
require 'rservicebus/subscription_storage_configure'
|
43
|
-
|
44
|
-
require 'rservicebus/monitor_configure'
|
45
|
-
|
46
|
-
require 'rservicebus/agent'
|
47
|
-
|
48
|
-
require 'rservicebus/saga_loader.rb'
|
49
|
-
require 'rservicebus/saga/manager.rb'
|
50
|
-
require 'rservicebus/saga/data.rb'
|
51
|
-
require 'rservicebus/saga/base.rb'
|
52
|
-
|
53
|
-
require 'rservicebus/saga_storage'
|
17
|
+
module RServiceBus
|
54
18
|
|
55
|
-
require 'rservicebus/sendat_manager'
|
56
19
|
|
57
|
-
# Initial definition of the namespace
|
58
|
-
module RServiceBus
|
59
20
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RServiceBus
|
2
|
+
require 'beanstalk-client'
|
3
|
+
|
4
|
+
class Agent
|
5
|
+
@beanstalk
|
6
|
+
|
7
|
+
def initialize()
|
8
|
+
@beanstalk = Beanstalk::Pool.new(['localhost:11300'])
|
9
|
+
end
|
10
|
+
|
11
|
+
def sendMsg(messageObj, queueName, returnAddress=nil)
|
12
|
+
msg = RServiceBus::Message.new( messageObj, returnAddress )
|
13
|
+
serialized_object = YAML::dump(msg)
|
14
|
+
|
15
|
+
@beanstalk.use( queueName )
|
16
|
+
@beanstalk.put( serialized_object )
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module RServiceBus
|
2
|
+
|
3
|
+
class Config
|
4
|
+
#host:
|
5
|
+
## @appName: CreateUser
|
6
|
+
## errorQueueName: error
|
7
|
+
#
|
8
|
+
|
9
|
+
attr_reader :appName, :handlerPathList
|
10
|
+
@config
|
11
|
+
@appName
|
12
|
+
|
13
|
+
@handlerPathList
|
14
|
+
|
15
|
+
def getValue( name, default=nil )
|
16
|
+
if ENV[name].nil? then
|
17
|
+
return default
|
18
|
+
end
|
19
|
+
|
20
|
+
return ENV[name]
|
21
|
+
end
|
22
|
+
|
23
|
+
def loadMessageEndpointMappings( host )
|
24
|
+
mapping = self.getValue( "RSERVICEBUS_MESSAGEENDPOINTMAPPINGS" )
|
25
|
+
|
26
|
+
messageEndpointMappings=Hash.new
|
27
|
+
if !mapping.nil? then
|
28
|
+
mapping.split( ";" ).each do |line|
|
29
|
+
match = line.match( /(.+):(.+)/ )
|
30
|
+
messageEndpointMappings[match[0]] = match[1]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
host.messageEndpointMappings=messageEndpointMappings
|
35
|
+
end
|
36
|
+
|
37
|
+
def loadHandlerPathList(host)
|
38
|
+
path = self.getValue( "RSERVICEBUS_MESSAGEHANDLERPATH", "MessageHandler" )
|
39
|
+
|
40
|
+
@handlerPathList = Array.new
|
41
|
+
path.split( ";" ).each do |path|
|
42
|
+
path = path.strip.chomp( "/" )
|
43
|
+
@handlerPathList << path
|
44
|
+
end
|
45
|
+
|
46
|
+
host.handlerPathList = @handlerPathList
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def loadHostSection( host )
|
51
|
+
path = self.getValue( "RSERVICEBUS_APPNAME", "RServiceBus" )
|
52
|
+
localQueueName = self.getValue( "RSERVICEBUS_APPNAME", "RServiceBus" )
|
53
|
+
# @appName = self.getValue( "host", "appName", "RServiceBus" )
|
54
|
+
# host.appName = @appName
|
55
|
+
host.localQueueName = @appName
|
56
|
+
host.errorQueueName = self.getValue( "host", "errorQueueName", "error" )
|
57
|
+
host.maxRetries = self.getValue( "host", "maxRetries", 5 )
|
58
|
+
host.forwardReceivedMessagesTo = self.getValue( "host", "forwardReceivedMessagesTo", nil )
|
59
|
+
|
60
|
+
self.loadHandlerPathList(host)
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def configureLogging( host )
|
65
|
+
logger = Logger.new "rservicebus." + @appName
|
66
|
+
loggingLevel = self.getLoggingLevel()
|
67
|
+
|
68
|
+
if self.getValue( "logger", "stdout", true ) != false then
|
69
|
+
Outputter.stdout.level = loggingLevel
|
70
|
+
logger.outputters = Outputter.stdout
|
71
|
+
end
|
72
|
+
|
73
|
+
fileName = self.getValue( "logger", "fileName", @appName + ".log" );
|
74
|
+
if fileName != false then
|
75
|
+
file = FileOutputter.new(@appName + ".file", :filename => fileName,:trunc => false)
|
76
|
+
file.level = loggingLevel
|
77
|
+
file.formatter = PatternFormatter.new(:pattern => self.getValue( "logger", "fileFormat", "[%l] %d :: %m" ))
|
78
|
+
logger.add( file )
|
79
|
+
end
|
80
|
+
host.logger = logger
|
81
|
+
end
|
82
|
+
|
83
|
+
def processConfig( host )
|
84
|
+
self.loadHostSection(host)
|
85
|
+
self.configureLogging(host)
|
86
|
+
self.loadMessageEndpointMappings( host )
|
87
|
+
|
88
|
+
|
89
|
+
return self
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
class ConfigFromFile<Config
|
96
|
+
|
97
|
+
def getConfigurationFilePath(configFilePath)
|
98
|
+
configFilePath = configFilePath.nil? ? "RServiceBus.yml" : configFilePath
|
99
|
+
if File.exists?(configFilePath) == false then
|
100
|
+
puts "Config file could not be found at: " + configFilePath
|
101
|
+
puts "(You can specifiy a config file with: ruby RServiceBus [your config file path]"
|
102
|
+
abort()
|
103
|
+
end
|
104
|
+
|
105
|
+
return configFilePath
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def initialize(configFilePath )
|
110
|
+
configFilePath = self.getConfigurationFilePath(configFilePath)
|
111
|
+
@config = YAML.load_file(configFilePath)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
class ConfigFromYAMLObject<Config
|
117
|
+
|
118
|
+
def initialize(config )
|
119
|
+
@config = config
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module RServiceBus
|
2
|
+
|
3
|
+
class HandlerLoader
|
4
|
+
|
5
|
+
attr_reader :messageName, :handler
|
6
|
+
|
7
|
+
@host
|
8
|
+
|
9
|
+
@baseDir
|
10
|
+
@filepath
|
11
|
+
|
12
|
+
@requirePath
|
13
|
+
@handlerName
|
14
|
+
|
15
|
+
@messageName
|
16
|
+
@handler
|
17
|
+
|
18
|
+
def initialize( baseDir, filePath, host )
|
19
|
+
@host = host
|
20
|
+
|
21
|
+
@baseDir = baseDir
|
22
|
+
@filePath = filePath
|
23
|
+
end
|
24
|
+
|
25
|
+
def getMessageName( baseDir, fileName )
|
26
|
+
name = fileName.sub( baseDir + "/", "" )
|
27
|
+
if name.count( "/" ) == 0 then
|
28
|
+
return name.match( /(.+)\./ )[1]
|
29
|
+
end
|
30
|
+
|
31
|
+
if name.count( "/" ) == 1 then
|
32
|
+
return name.match( /\/(.+)\./ )[1]
|
33
|
+
end
|
34
|
+
|
35
|
+
puts "Filepath, " + fileName + ", not in the expected format."
|
36
|
+
puts "Expected format either,"
|
37
|
+
puts "MessageHandler/Hello.rb, or"
|
38
|
+
puts "MessageHandler/Hello/One.rb, or"
|
39
|
+
abort();
|
40
|
+
end
|
41
|
+
|
42
|
+
def getRequirePath( filePath )
|
43
|
+
if File.exists?( filePath ) then
|
44
|
+
return filePath.sub( ".rb", "")
|
45
|
+
end
|
46
|
+
|
47
|
+
if File.exists?( "./" + filePath ) then
|
48
|
+
return "./" + filePath.sub( ".rb", "")
|
49
|
+
end
|
50
|
+
|
51
|
+
abort( "Filepath, " + filePath + ", given for MessageHandler require doesn't exist" );
|
52
|
+
end
|
53
|
+
|
54
|
+
def parseFilepath
|
55
|
+
@requirePath = self.getRequirePath( @filePath )
|
56
|
+
@messageName = self.getMessageName( @baseDir, @filePath )
|
57
|
+
@handlerName = @filePath.sub( ".rb", "").sub( @baseDir, "MessageHandler" ).gsub( "/", "_" )
|
58
|
+
|
59
|
+
puts @handlerName
|
60
|
+
puts @filePath + ":" + @messageName + ":" + @handlerName
|
61
|
+
end
|
62
|
+
|
63
|
+
def loadHandlerFromFile
|
64
|
+
require @requirePath
|
65
|
+
begin
|
66
|
+
@handler = Object.const_get(@handlerName).new();
|
67
|
+
rescue Exception => e
|
68
|
+
puts "Expected class name: " + @handlerName + ", not found after require: " + @requirePath
|
69
|
+
puts "**** Check in " + @filePath + " that the class is named : " + @handlerName
|
70
|
+
puts "( In case its not that )"
|
71
|
+
raise e
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def setBusAttributeIfRequested
|
76
|
+
if defined?( @handler.Bus ) then
|
77
|
+
@handler.Bus = @host
|
78
|
+
puts "Bus attribute set for: " + @handlerName
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def loadHandler()
|
83
|
+
begin
|
84
|
+
self.parseFilepath
|
85
|
+
self.loadHandlerFromFile
|
86
|
+
self.setBusAttributeIfRequested
|
87
|
+
puts "Loaded Handler: " + @handlerName + ", for, " + @messageName
|
88
|
+
rescue Exception => e
|
89
|
+
puts "Exception loading handler from file: " + @filePath
|
90
|
+
puts e.message
|
91
|
+
puts e.backtrace[0]
|
92
|
+
|
93
|
+
abort()
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,340 @@
|
|
1
|
+
module RServiceBus
|
2
|
+
|
3
|
+
class Host
|
4
|
+
|
5
|
+
@appName
|
6
|
+
|
7
|
+
@handlerPathList
|
8
|
+
@handlerList
|
9
|
+
|
10
|
+
@errorQueueName
|
11
|
+
@maxRetries
|
12
|
+
|
13
|
+
@localQueueName
|
14
|
+
|
15
|
+
@forwardReceivedMessagesTo
|
16
|
+
@forwardReceivedMessagesToQueue
|
17
|
+
|
18
|
+
@messageEndpointMappings
|
19
|
+
|
20
|
+
@subscriptions
|
21
|
+
|
22
|
+
@beanstalk
|
23
|
+
|
24
|
+
@verbose
|
25
|
+
|
26
|
+
def log(string, ver=false)
|
27
|
+
type = ver ? "VERB" : "INFO"
|
28
|
+
if @verbose || !ver then
|
29
|
+
timestamp = Time.new.strftime( "%Y-%m-%d %H:%M:%S" )
|
30
|
+
puts "[#{type}] #{timestamp} :: #{string}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def getValue( name, default=nil )
|
35
|
+
value = ENV["#{name}"].nil? ? default : ENV["#{name}"];
|
36
|
+
self.log "Env value: #{name}: #{value}", true
|
37
|
+
return value
|
38
|
+
end
|
39
|
+
|
40
|
+
def loadMessageEndpointMappings()
|
41
|
+
mapping = self.getValue( "MESSAGE_ENDPOINT_MAPPINGS" )
|
42
|
+
|
43
|
+
messageEndpointMappings=Hash.new
|
44
|
+
if !mapping.nil? then
|
45
|
+
mapping.split( ";" ).each do |line|
|
46
|
+
match = line.match( /(.+):(.+)/ )
|
47
|
+
messageEndpointMappings[match[0]] = match[1]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
@messageEndpointMappings=messageEndpointMappings
|
52
|
+
|
53
|
+
return self
|
54
|
+
end
|
55
|
+
|
56
|
+
def loadHandlerPathList()
|
57
|
+
path = self.getValue( "MSGHANDLERPATH", "MessageHandler" )
|
58
|
+
handlerPathList = Array.new
|
59
|
+
path.split( ";" ).each do |path|
|
60
|
+
path = path.strip.chomp( "/" )
|
61
|
+
handlerPathList << path
|
62
|
+
end
|
63
|
+
|
64
|
+
@handlerPathList = handlerPathList
|
65
|
+
|
66
|
+
return self
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def loadHostSection()
|
71
|
+
@appName = self.getValue( "APPNAME", "RServiceBus" )
|
72
|
+
@localQueueName = @appName
|
73
|
+
@errorQueueName = self.getValue( "ERROR_QUEUE_NAME", "error" )
|
74
|
+
@maxRetries = self.getValue( "MAX_RETRIES", "5" ).to_i
|
75
|
+
@forwardReceivedMessagesTo = self.getValue( "FORWARD_RECEIVED_MESSAGES_TO" )
|
76
|
+
|
77
|
+
return self
|
78
|
+
end
|
79
|
+
|
80
|
+
def loadContracts()
|
81
|
+
if self.getValue( "CONTRACTS" ).nil? then
|
82
|
+
return self
|
83
|
+
end
|
84
|
+
|
85
|
+
self.getValue( "CONTRACTS" ).split( ";" ) do |path|
|
86
|
+
require path
|
87
|
+
end
|
88
|
+
return self
|
89
|
+
end
|
90
|
+
|
91
|
+
def configureLogging()
|
92
|
+
@verbose = !self.getValue( "VERBOSE", nil ).nil?
|
93
|
+
|
94
|
+
return self
|
95
|
+
end
|
96
|
+
|
97
|
+
def configureBeanstalk
|
98
|
+
beanstalkHost = self.getValue( "BEANSTALK", "localhost:11300" )
|
99
|
+
@beanstalk = Beanstalk::Pool.new([beanstalkHost])
|
100
|
+
|
101
|
+
return self
|
102
|
+
end
|
103
|
+
|
104
|
+
def initialize()
|
105
|
+
|
106
|
+
self.loadHostSection()
|
107
|
+
.configureLogging()
|
108
|
+
.configureBeanstalk()
|
109
|
+
.loadContracts()
|
110
|
+
.loadMessageEndpointMappings()
|
111
|
+
.loadHandlerPathList()
|
112
|
+
.loadHandlers()
|
113
|
+
.loadSubscriptions()
|
114
|
+
.sendSubscriptions()
|
115
|
+
|
116
|
+
return self
|
117
|
+
end
|
118
|
+
|
119
|
+
def loadHandlersFromPath(baseDir, subDir="")
|
120
|
+
log "Load Message Handlers from baseDir, " + baseDir + ", subDir, " + subDir
|
121
|
+
log "Checking, " + baseDir, true
|
122
|
+
|
123
|
+
@handlerList = {};
|
124
|
+
Dir[baseDir + "/" + subDir + "*"].each do |filePath|
|
125
|
+
if !filePath.end_with?( "." ) then
|
126
|
+
log "Filepath, " + filePath, true
|
127
|
+
|
128
|
+
if File.directory?( filePath ) then
|
129
|
+
self.loadHandlersFromPath( filePath.sub( baseDir ) )
|
130
|
+
else
|
131
|
+
handlerLoader = HandlerLoader.new( baseDir, filePath, self )
|
132
|
+
handlerLoader.loadHandler
|
133
|
+
|
134
|
+
if !@handlerList.has_key?( handlerLoader.messageName ) then
|
135
|
+
@handlerList[handlerLoader.messageName] = Array.new
|
136
|
+
end
|
137
|
+
|
138
|
+
@handlerList[handlerLoader.messageName] << handlerLoader.handler;
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
return self
|
144
|
+
end
|
145
|
+
|
146
|
+
def loadHandlers()
|
147
|
+
log "Load Message Handlers"
|
148
|
+
|
149
|
+
@handlerPathList.each do |path|
|
150
|
+
self.loadHandlersFromPath(path)
|
151
|
+
end
|
152
|
+
|
153
|
+
return self
|
154
|
+
end
|
155
|
+
|
156
|
+
def sendSubscriptions
|
157
|
+
log "Send Subscriptions"
|
158
|
+
@messageEndpointMappings.each do |eventName,queueName|
|
159
|
+
log "Checking, " + eventName + " for Event", true
|
160
|
+
if eventName.end_with?( "Event" ) then
|
161
|
+
log eventName + ", is an event. About to send subscription to, " + queueName, true
|
162
|
+
self.Subscribe( eventName )
|
163
|
+
log "Subscribed to, " + eventName + " at, " + queueName
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
return self
|
168
|
+
end
|
169
|
+
|
170
|
+
def loadSubscriptions
|
171
|
+
log "Load subscriptions"
|
172
|
+
@subscriptions = Hash.new
|
173
|
+
|
174
|
+
redis = Redis.new
|
175
|
+
|
176
|
+
prefix = @appName + ".Subscriptions."
|
177
|
+
subscriptions = redis.keys prefix + "*Event"
|
178
|
+
|
179
|
+
subscriptions.each do |subscriptionName|
|
180
|
+
log "Loading subscription: " + subscriptionName, true
|
181
|
+
eventName = subscriptionName.sub( prefix, "" )
|
182
|
+
@subscriptions[eventName] = Array.new
|
183
|
+
|
184
|
+
log "Loading for event: " + eventName, true
|
185
|
+
subscription = redis.smembers subscriptionName
|
186
|
+
subscription.each do |subscriber|
|
187
|
+
log "Loading subscriber, " + subscriber + " for event, " + eventName, true
|
188
|
+
@subscriptions[eventName] << subscriber
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
return self
|
193
|
+
end
|
194
|
+
|
195
|
+
def addSubscrption( eventName, queueName )
|
196
|
+
log "Adding subscrption for, " + eventName + ", to, " + queueName
|
197
|
+
redis = Redis.new
|
198
|
+
key = @appName + ".Subscriptions." + eventName
|
199
|
+
redis.sadd key, queueName
|
200
|
+
|
201
|
+
if @subscriptions[eventName].nil? then
|
202
|
+
@subscriptions[eventName] = Array.new
|
203
|
+
end
|
204
|
+
@subscriptions[eventName] << queueName
|
205
|
+
end
|
206
|
+
|
207
|
+
def run
|
208
|
+
log "Starting the Host"
|
209
|
+
|
210
|
+
log "Watching, " + @localQueueName
|
211
|
+
@beanstalk.watch( @localQueueName )
|
212
|
+
if !@forwardReceivedMessagesTo.nil? then
|
213
|
+
log "Forwarding all received messages to: " + @forwardReceivedMessagesTo.to_s
|
214
|
+
end
|
215
|
+
|
216
|
+
self.StartListeningToEndpoints
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
def StartListeningToEndpoints
|
221
|
+
log "Waiting for messages. To exit press CTRL+C"
|
222
|
+
|
223
|
+
loop do
|
224
|
+
job = @beanstalk.reserve
|
225
|
+
body = job.body
|
226
|
+
retries = @maxRetries
|
227
|
+
begin
|
228
|
+
@msg = YAML::load(body)
|
229
|
+
if @msg.msg.class.name == "RServiceBus::Subscription" then
|
230
|
+
self.addSubscrption( @msg.msg.eventName, @msg.returnAddress )
|
231
|
+
else
|
232
|
+
self.HandleMessage()
|
233
|
+
if !@forwardReceivedMessagesTo.nil? then
|
234
|
+
self._SendAlreadyWrappedAndSerialised(body,@forwardReceivedMessagesTo)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
job.delete
|
238
|
+
rescue Exception => e
|
239
|
+
retry if (retries -= 1) > 0
|
240
|
+
|
241
|
+
errorString = e.message + ". " + e.backtrace[0]
|
242
|
+
log errorString
|
243
|
+
|
244
|
+
@msg.addErrorMsg( @localQueueName, errorString )
|
245
|
+
serialized_object = YAML::dump(@msg)
|
246
|
+
self._SendAlreadyWrappedAndSerialised(serialized_object, @errorQueueName)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def HandleMessage()
|
252
|
+
msgName = @msg.msg.class.name
|
253
|
+
handlerList = @handlerList[msgName]
|
254
|
+
|
255
|
+
if handlerList == nil then
|
256
|
+
log "No handler found for: " + msgName
|
257
|
+
raise "No Handler Found"
|
258
|
+
else
|
259
|
+
log "Handler found for: " + msgName, true
|
260
|
+
handlerList.each do |handler|
|
261
|
+
begin
|
262
|
+
handler.Handle( @msg.msg )
|
263
|
+
rescue Exception => e
|
264
|
+
log "An error occured in Handler: " + handler.class.name
|
265
|
+
raise e
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def _SendAlreadyWrappedAndSerialised( serialized_object, queueName )
|
272
|
+
log "Bus._SendAlreadyWrappedAndSerialised", true
|
273
|
+
|
274
|
+
@beanstalk.use( queueName )
|
275
|
+
@beanstalk.put( serialized_object )
|
276
|
+
end
|
277
|
+
|
278
|
+
def _SendNeedsWrapping( msg, queueName )
|
279
|
+
log "Bus._SendNeedsWrapping", true
|
280
|
+
|
281
|
+
rMsg = RServiceBus::Message.new( msg, @localQueueName )
|
282
|
+
serialized_object = YAML::dump(rMsg)
|
283
|
+
log "Sending: " + msg.class.name + " to: " + queueName, true
|
284
|
+
self._SendAlreadyWrappedAndSerialised( serialized_object, queueName )
|
285
|
+
end
|
286
|
+
|
287
|
+
def Reply( msg )
|
288
|
+
log "Reply with: " + msg.class.name + " To: " + @msg.returnAddress, true
|
289
|
+
|
290
|
+
self._SendNeedsWrapping( msg, @msg.returnAddress )
|
291
|
+
end
|
292
|
+
|
293
|
+
|
294
|
+
def Send( msg )
|
295
|
+
log "Bus.Send", true
|
296
|
+
|
297
|
+
|
298
|
+
msgName = msg.class.name
|
299
|
+
if !@messageEndpointMappings.has_key?( msgName ) then
|
300
|
+
log "No end point mapping found for: " + msgName
|
301
|
+
log "**** Check in RServiceBus.yml that the section MessageEndpointMappings contains an entry named : " + msgName
|
302
|
+
raise "No end point mapping found for: " + msgName
|
303
|
+
end
|
304
|
+
|
305
|
+
queueName = @messageEndpointMappings[msgName]
|
306
|
+
|
307
|
+
self._SendNeedsWrapping( msg, queueName )
|
308
|
+
end
|
309
|
+
|
310
|
+
def Publish( msg )
|
311
|
+
log "Bus.Publish", true
|
312
|
+
|
313
|
+
|
314
|
+
subscription = @subscriptions[msg.class.name]
|
315
|
+
if subscription.nil? then
|
316
|
+
log "No subscribers for event, " + msg.class.name
|
317
|
+
return
|
318
|
+
end
|
319
|
+
|
320
|
+
subscription.each do |subscriber|
|
321
|
+
self._SendNeedsWrapping( msg, subscriber )
|
322
|
+
end
|
323
|
+
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
def Subscribe( eventName )
|
328
|
+
log "Bus.Subscribe: " + eventName, true
|
329
|
+
|
330
|
+
|
331
|
+
queueName = @messageEndpointMappings[eventName]
|
332
|
+
subscription = Subscription.new( eventName )
|
333
|
+
|
334
|
+
|
335
|
+
self._SendNeedsWrapping( subscription, queueName )
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|