rservicebus 0.0.01 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|