rservicebus 0.0.6 → 0.0.7

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.
@@ -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: