rservicebus 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rservicebus/Agent.rb +10 -0
- data/lib/rservicebus/AppResource.rb +9 -0
- data/lib/rservicebus/Config.rb +4 -7
- data/lib/rservicebus/ConfigureAppResource.rb +1 -0
- data/lib/rservicebus/HandlerLoader.rb +139 -40
- data/lib/rservicebus/Host.rb +4 -28
- data/lib/rservicebus/Message.rb +13 -0
- data/lib/rservicebus/RedisAppResource.rb +1 -0
- data/lib/rservicebus/Test/Bus.rb +4 -4
- metadata +3 -2
data/lib/rservicebus/Agent.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module RServiceBus
|
2
2
|
require 'beanstalk-client'
|
3
3
|
|
4
|
+
#A means for a stand-alone process to interact with the bus, without being a full
|
5
|
+
#rservicebus application
|
4
6
|
class Agent
|
5
7
|
@beanstalk
|
6
8
|
|
@@ -8,6 +10,11 @@ class Agent
|
|
8
10
|
@beanstalk = Beanstalk::Pool.new(url)
|
9
11
|
end
|
10
12
|
|
13
|
+
# Put a msg on the bus
|
14
|
+
#
|
15
|
+
# @param [Object] messageObj The msg to be sent
|
16
|
+
# @param [String] queueName the name of the queue to be send the msg to
|
17
|
+
# @param [String] returnAddress the name of a queue to send replies to
|
11
18
|
def sendMsg(messageObj, queueName, returnAddress=nil)
|
12
19
|
msg = RServiceBus::Message.new( messageObj, returnAddress )
|
13
20
|
serialized_object = YAML::dump(msg)
|
@@ -16,6 +23,9 @@ class Agent
|
|
16
23
|
@beanstalk.put( serialized_object )
|
17
24
|
end
|
18
25
|
|
26
|
+
# Gives an agent a mean to receive replies
|
27
|
+
#
|
28
|
+
# @param [String] queueName the name of the queue to monitor for messages
|
19
29
|
def checkForReply( queueName )
|
20
30
|
@beanstalk.watch queueName
|
21
31
|
job = @beanstalk.reserve
|
@@ -1,12 +1,21 @@
|
|
1
1
|
require "uri"
|
2
2
|
|
3
|
+
# Wrapper base class for resources used by applications, allowing rservicebus to configure the resource
|
4
|
+
# - dependency injection.
|
5
|
+
#
|
3
6
|
class AppResource
|
4
7
|
@uri
|
5
8
|
|
9
|
+
# Resources are attached resources, and can be specified using the URI syntax.
|
10
|
+
#
|
11
|
+
# @param [String] uri a location for the resource to which we will attach, eg redis://127.0.0.1/foo
|
6
12
|
def initialize( uri )
|
7
13
|
@uri = uri
|
8
14
|
end
|
9
15
|
|
16
|
+
# The method which actually configures the resource.
|
17
|
+
#
|
18
|
+
# @return [Object] the configured object.
|
10
19
|
def getResource
|
11
20
|
raise "Method, getResource, needs to be implemented for resource"
|
12
21
|
end
|
data/lib/rservicebus/Config.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
module RServiceBus
|
2
2
|
|
3
|
+
#Collects and reports configuration information for an rservicebus host
|
3
4
|
class Config
|
4
|
-
#host:
|
5
|
-
## @appName: CreateUser
|
6
|
-
## errorQueueName: error
|
7
|
-
#
|
8
5
|
attr_reader :appName, :messageEndpointMappings, :handlerPathList, :localQueueName, :errorQueueName, :maxRetries, :forwardReceivedMessagesTo, :verbose, :beanstalkHost
|
9
6
|
|
10
7
|
@appName
|
@@ -50,7 +47,7 @@ class Config
|
|
50
47
|
end
|
51
48
|
|
52
49
|
def loadHandlerPathList()
|
53
|
-
path = self.getValue( "MSGHANDLERPATH", "MessageHandler" )
|
50
|
+
path = self.getValue( "MSGHANDLERPATH", "./MessageHandler" )
|
54
51
|
handlerPathList = Array.new
|
55
52
|
path.split( ";" ).each do |path|
|
56
53
|
path = path.strip.chomp( "/" )
|
@@ -74,11 +71,11 @@ class Config
|
|
74
71
|
end
|
75
72
|
|
76
73
|
def loadContracts()
|
77
|
-
if self.getValue( "CONTRACTS" ).nil? then
|
74
|
+
if self.getValue( "CONTRACTS", "./Contract" ).nil? then
|
78
75
|
return self
|
79
76
|
end
|
80
77
|
|
81
|
-
self.getValue( "CONTRACTS" ).split( ";" ).each do |path|
|
78
|
+
self.getValue( "CONTRACTS", "./Contract" ).split( ";" ).each do |path|
|
82
79
|
puts "Loading contracts from, #{path}"
|
83
80
|
require path
|
84
81
|
end
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module RServiceBus
|
2
2
|
|
3
|
+
#Given a directory, this class is responsible for finding
|
4
|
+
# msgnames,
|
5
|
+
# handlernames, and
|
6
|
+
# loading handlers
|
3
7
|
class HandlerLoader
|
4
8
|
|
5
|
-
attr_reader :
|
9
|
+
attr_reader :handlerList
|
6
10
|
|
7
11
|
@host
|
8
12
|
@appResources
|
@@ -16,28 +20,22 @@ class HandlerLoader
|
|
16
20
|
@messageName
|
17
21
|
@handler
|
18
22
|
|
23
|
+
@handlerList
|
24
|
+
|
25
|
+
# Constructor
|
26
|
+
#
|
27
|
+
# @param [RServiceBus::Host] host instance
|
28
|
+
# @param [Hash] appResources As hash[k,v] where k is the name of a resource, and v is the resource
|
19
29
|
def initialize( host, appResources )
|
20
30
|
@host = host
|
21
31
|
@appResources = appResources
|
32
|
+
|
33
|
+
@handlerList = Hash.new
|
22
34
|
end
|
23
35
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
return name.match( /(.+)\./ )[1]
|
28
|
-
end
|
29
|
-
|
30
|
-
if name.count( "/" ) == 1 then
|
31
|
-
return name.match( /\/(.+)\./ )[1]
|
32
|
-
end
|
33
|
-
|
34
|
-
puts "Filepath, " + fileName + ", not in the expected format."
|
35
|
-
puts "Expected format either,"
|
36
|
-
puts "MessageHandler/Hello.rb, or"
|
37
|
-
puts "MessageHandler/Hello/One.rb, or"
|
38
|
-
abort();
|
39
|
-
end
|
40
|
-
|
36
|
+
# Cleans the given path to ensure it can be used for as a parameter for the require statement.
|
37
|
+
#
|
38
|
+
# @param [String] filePath the path to be cleaned
|
41
39
|
def getRequirePath( filePath )
|
42
40
|
if !filePath.start_with?( "/" ) then
|
43
41
|
filePath = "./" + filePath
|
@@ -50,12 +48,17 @@ class HandlerLoader
|
|
50
48
|
abort( "Filepath, " + filePath + ", given for MessageHandler require doesn't exist" );
|
51
49
|
end
|
52
50
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
# Instantiate the handler named in handlerName from the file name in filePath
|
52
|
+
# Exceptions will be raised if encountered when loading handlers. This is a load time activity,
|
53
|
+
# so handlers should load correctly. As much information as possible is returned
|
54
|
+
# to enable the handler to be fixed, or configuration corrected.
|
55
|
+
#
|
56
|
+
# @param [String] handlerName name of the handler to instantiate
|
57
|
+
# @param [String] filePath the path to the file to be loaded
|
58
|
+
# @return [RServiceBus::Handler] the loader
|
59
|
+
def loadHandlerFromFile( handlerName, filePath )
|
60
|
+
requirePath = self.getRequirePath( filePath )
|
57
61
|
|
58
|
-
def loadHandlerFromFile( requirePath, handlerName, filePath )
|
59
62
|
require requirePath
|
60
63
|
begin
|
61
64
|
handler = Object.const_get(handlerName).new();
|
@@ -69,40 +72,50 @@ class HandlerLoader
|
|
69
72
|
return handler
|
70
73
|
end
|
71
74
|
|
72
|
-
|
75
|
+
# setBusAttributeIfRequested
|
76
|
+
#
|
77
|
+
# @param [RServiceBus::Handler] handler
|
78
|
+
def setBusAttributeIfRequested( handler )
|
73
79
|
if defined?( handler.Bus ) then
|
74
80
|
handler.Bus = @host
|
75
|
-
@host.log "Bus attribute set for: " +
|
81
|
+
@host.log "Bus attribute set for: " + handler.class.name
|
76
82
|
end
|
83
|
+
|
84
|
+
return self
|
77
85
|
end
|
78
86
|
|
79
|
-
|
80
|
-
|
87
|
+
# Assigns appropriate resources to writable attributes in the handler that match keys in the resource hash
|
88
|
+
#
|
89
|
+
# @param [RServiceBus::Handler] handler
|
90
|
+
# @param [Hash] appResources As hash[k,v] where k is the name of a resource, and v is the resource
|
91
|
+
def setAppResources( handler, appResources )
|
92
|
+
@host.log "Checking app resources for: #{handler.class.name}", true
|
81
93
|
appResources.each do |k,v|
|
82
94
|
if handler.class.method_defined?( k ) then
|
83
95
|
handler.instance_variable_set( "@#{k}", v.getResource() )
|
84
|
-
@host.log "App resource attribute, #{k}, set for: " +
|
96
|
+
@host.log "App resource attribute, #{k}, set for: " + handler.class.name
|
85
97
|
end
|
86
98
|
end
|
99
|
+
|
100
|
+
return self
|
87
101
|
end
|
88
102
|
|
89
|
-
|
103
|
+
# Wrapper function
|
104
|
+
#
|
105
|
+
# @param [String] filePath
|
106
|
+
# @param [String] handlerName
|
107
|
+
# @returns [RServiceBus::Handler] handler
|
108
|
+
def loadAndConfigureHandler(filePath, handlerName)
|
90
109
|
begin
|
91
|
-
requirePath = self.getRequirePath( filePath )
|
92
|
-
messageName = self.getMessageName( baseDir, filePath )
|
93
|
-
handlerName = self.getHandlerName( baseDir, filePath )
|
94
|
-
|
95
110
|
@host.log "filePath: " + filePath, true
|
96
|
-
@host.log "requirePath: " + requirePath, true
|
97
|
-
@host.log "messageName: " + messageName, true
|
98
111
|
@host.log "handlerName: " + handlerName, true
|
99
112
|
|
100
|
-
handler = self.loadHandlerFromFile(
|
101
|
-
self.setBusAttributeIfRequested( handler
|
102
|
-
self.setAppResources( handler,
|
103
|
-
@host.log "Loaded Handler: " + handlerName
|
113
|
+
handler = self.loadHandlerFromFile( handlerName, filePath )
|
114
|
+
self.setBusAttributeIfRequested( handler )
|
115
|
+
self.setAppResources( handler, @appResources )
|
116
|
+
@host.log "Loaded Handler: " + handlerName
|
104
117
|
|
105
|
-
return
|
118
|
+
return handler
|
106
119
|
rescue Exception => e
|
107
120
|
puts "Exception loading handler from file: " + filePath
|
108
121
|
puts e.message
|
@@ -113,6 +126,92 @@ class HandlerLoader
|
|
113
126
|
|
114
127
|
end
|
115
128
|
|
129
|
+
#This method is overloaded for unit tests
|
130
|
+
#
|
131
|
+
# @param [String] path directory to check
|
132
|
+
# @return [Array] a list of paths to files found in the given path
|
133
|
+
def getListOfFilesForDir( path )
|
134
|
+
return Dir[path + "/*"];
|
135
|
+
end
|
136
|
+
|
137
|
+
#Multiple handlers for the same msg can be placed inside a top level directory.
|
138
|
+
#The msg name is than taken from the directory, and the handlers from the files inside that
|
139
|
+
#directory
|
140
|
+
#
|
141
|
+
# @param [String] msgName name of message
|
142
|
+
# @param [String] baseDir directory to check for handlers of the given msgName
|
143
|
+
def loadHandlersFromSecondLevelPath(msgName, baseDir)
|
144
|
+
self.getListOfFilesForDir(baseDir).each do |filePath|
|
145
|
+
if !filePath.end_with?( "." ) then
|
146
|
+
extName = File.extname( filePath )
|
147
|
+
if !File.directory?( filePath ) &&
|
148
|
+
extName == ".rb" then
|
149
|
+
|
150
|
+
fileName = File.basename( filePath ).sub( ".rb", "" )
|
151
|
+
handlerName = "MessageHandler_#{msgName}_#{fileName}"
|
152
|
+
|
153
|
+
handler = self.loadAndConfigureHandler( filePath, handlerName )
|
154
|
+
if !@handlerList.has_key?( msgName ) then
|
155
|
+
@handlerList[msgName] = Array.new
|
156
|
+
end
|
157
|
+
|
158
|
+
@handlerList[msgName] << handler;
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
return self
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
#Extract the top level dir or file name as it is the msg name
|
168
|
+
#
|
169
|
+
# @param [String] filePath path to check - this can be a directory or file
|
170
|
+
def getMsgName( filePath )
|
171
|
+
baseName = File.basename( filePath )
|
172
|
+
extName = File.extname( baseName )
|
173
|
+
fileName = baseName.sub( extName, "" )
|
174
|
+
|
175
|
+
msgName = fileName
|
176
|
+
|
177
|
+
return msgName
|
178
|
+
end
|
179
|
+
|
180
|
+
#Load top level handlers from the given directory
|
181
|
+
#
|
182
|
+
# @param [String] baseDir directory to check - should not have trailing slash
|
183
|
+
def loadHandlersFromTopLevelPath(baseDir)
|
184
|
+
self.getListOfFilesForDir(baseDir).each do |filePath|
|
185
|
+
if !filePath.end_with?( "." ) then
|
186
|
+
|
187
|
+
msgName = self.getMsgName( filePath )
|
188
|
+
if File.directory?( filePath ) then
|
189
|
+
self.loadHandlersFromSecondLevelPath( msgName, filePath )
|
190
|
+
else
|
191
|
+
handlerName = "MessageHandler_#{msgName}"
|
192
|
+
handler = self.loadAndConfigureHandler( filePath, handlerName )
|
193
|
+
|
194
|
+
if !@handlerList.has_key?( msgName ) then
|
195
|
+
@handlerList[msgName] = Array.new
|
196
|
+
end
|
197
|
+
|
198
|
+
@handlerList[msgName] << handler;
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
return self
|
204
|
+
end
|
205
|
+
|
206
|
+
#Entry point for loading handlers
|
207
|
+
#
|
208
|
+
# @param [String] baseDir directory to check - should not have trailing slash
|
209
|
+
def loadHandlersFromPath(baseDir)
|
210
|
+
self.loadHandlersFromTopLevelPath(baseDir)
|
211
|
+
|
212
|
+
return self
|
213
|
+
end
|
214
|
+
|
116
215
|
end
|
117
216
|
|
118
217
|
end
|
data/lib/rservicebus/Host.rb
CHANGED
@@ -67,40 +67,16 @@ class Host
|
|
67
67
|
return self
|
68
68
|
end
|
69
69
|
|
70
|
-
def loadHandlersFromPath(baseDir, subDir="")
|
71
|
-
log "Load Message Handlers from baseDir, " + baseDir + ", subDir, " + subDir
|
72
|
-
log "Checking, " + baseDir, true
|
73
|
-
handlerLoader = HandlerLoader.new( self, @appResources )
|
74
|
-
|
75
|
-
@handlerList = {};
|
76
|
-
Dir[baseDir + "/" + subDir + "*"].each do |filePath|
|
77
|
-
if !filePath.end_with?( "." ) then
|
78
|
-
log "Filepath, " + filePath, true
|
79
|
-
|
80
|
-
if File.directory?( filePath ) then
|
81
|
-
self.loadHandlersFromPath( filePath.sub( baseDir ) )
|
82
|
-
else
|
83
|
-
messageName, handler = handlerLoader.loadHandler( baseDir, filePath )
|
84
|
-
|
85
|
-
if !@handlerList.has_key?( messageName ) then
|
86
|
-
@handlerList[messageName] = Array.new
|
87
|
-
end
|
88
|
-
|
89
|
-
@handlerList[messageName] << handler;
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
return self
|
95
|
-
end
|
96
|
-
|
97
70
|
def loadHandlers()
|
98
71
|
log "Load Message Handlers"
|
72
|
+
handlerLoader = HandlerLoader.new( self, @appResources )
|
99
73
|
|
100
74
|
@config.handlerPathList.each do |path|
|
101
|
-
|
75
|
+
handlerLoader.loadHandlersFromPath(path)
|
102
76
|
end
|
103
77
|
|
78
|
+
@handlerList = handlerLoader.handlerList
|
79
|
+
|
104
80
|
return self
|
105
81
|
end
|
106
82
|
|
data/lib/rservicebus/Message.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
module RServiceBus
|
2
2
|
|
3
|
+
#This is the top level message that is passed around the bus
|
3
4
|
class Message
|
4
5
|
|
5
6
|
attr_reader :returnAddress, :msgId
|
6
7
|
|
8
|
+
# Constructor
|
9
|
+
#
|
10
|
+
# @param [Object] msg The calling function msg to be sent
|
11
|
+
# @param [Object] returnAddress A queue that the receiving message handler can send replies to
|
7
12
|
def initialize( msg, returnAddress )
|
8
13
|
@_msg=YAML::dump(msg)
|
9
14
|
@returnAddress=returnAddress
|
@@ -12,10 +17,18 @@ class Message
|
|
12
17
|
@errorList = Array.new
|
13
18
|
end
|
14
19
|
|
20
|
+
# Capture information when an exception has occurred, to help with diagnosing the error.
|
21
|
+
# Once the error has been diagnosed, the msg may be able to be returned to the sourceQueue
|
22
|
+
#
|
23
|
+
# @param [Object] sourceQueue The name of the queue to return the msg to
|
24
|
+
# @param [Object] errorString A queue that the receiving message handler can send replies to
|
15
25
|
def addErrorMsg( sourceQueue, errorString )
|
16
26
|
@errorList << RServiceBus::ErrorMessage.new( sourceQueue, errorString )
|
17
27
|
end
|
18
28
|
|
29
|
+
# Convenience function
|
30
|
+
#
|
31
|
+
# @return [String]
|
19
32
|
def getLastErrorMsg
|
20
33
|
return @errorList.last
|
21
34
|
end
|
data/lib/rservicebus/Test/Bus.rb
CHANGED
@@ -6,7 +6,7 @@ class Test_Bus
|
|
6
6
|
@sendList
|
7
7
|
@replyList
|
8
8
|
@logList
|
9
|
-
|
9
|
+
|
10
10
|
def initialize
|
11
11
|
@publishList = Array.new
|
12
12
|
@sendList = Array.new
|
@@ -22,9 +22,9 @@ class Test_Bus
|
|
22
22
|
@sendList << msg
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def Reply( msg )
|
26
|
+
@replyList << msg
|
27
|
+
end
|
28
28
|
|
29
29
|
def log( string, verbose=false )
|
30
30
|
item = Hash.new
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rservicebus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A ruby implementation of NServiceBus
|
15
15
|
email: guy@guyirvine.com
|
@@ -61,3 +61,4 @@ signing_key:
|
|
61
61
|
specification_version: 3
|
62
62
|
summary: RServiceBus
|
63
63
|
test_files: []
|
64
|
+
has_rdoc:
|