rservicebus 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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,5 +1,6 @@
1
1
  require "uri"
2
2
 
3
+ #Configure AppResources for an rservicebus host
3
4
  class ConfigureAppResource
4
5
 
5
6
  def getResources( env )
@@ -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 :messageName, :handler
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
- def getMessageName( baseDir, fileName )
25
- name = fileName.sub( baseDir + "/", "" )
26
- if name.count( "/" ) == 0 then
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
- def getHandlerName( baseDir, filePath )
54
- handlerName = filePath.sub( ".rb", "").sub( baseDir, "MessageHandler" ).gsub( "/", "_" )
55
- return handlerName
56
- end
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
- def setBusAttributeIfRequested( handler, handlerName )
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: " + handlerName
81
+ @host.log "Bus attribute set for: " + handler.class.name
76
82
  end
83
+
84
+ return self
77
85
  end
78
86
 
79
- def setAppResources( handler, handlerName, appResources )
80
- @host.log "Checking app resources for: #{handlerName}", true
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: " + handlerName
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
- def loadHandler(baseDir, filePath)
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( requirePath, handlerName, filePath )
101
- self.setBusAttributeIfRequested( handler, handlerName )
102
- self.setAppResources( handler, handlerName, @appResources )
103
- @host.log "Loaded Handler: " + handlerName + ", for, " + messageName
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 messageName, handler
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
@@ -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
- self.loadHandlersFromPath(path)
75
+ handlerLoader.loadHandlersFromPath(path)
102
76
  end
103
77
 
78
+ @handlerList = handlerLoader.handlerList
79
+
104
80
  return self
105
81
  end
106
82
 
@@ -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
@@ -1,5 +1,6 @@
1
1
  require "redis"
2
2
 
3
+ #Implementation of an AppResource - Redis
3
4
  class RedisAppResource<AppResource
4
5
 
5
6
  @connection
@@ -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
- def Reply( msg )
26
- @replyList << msg
27
- end
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.6
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-19 00:00:00.000000000 Z
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: