Commits

Kenneth Jørgensen  committed 059c54d

Implemented optional secondary message on proxy errors. This allows for some custom error checking to take place.

  • Participants
  • Parent commits c2a527a

Comments (0)

Files changed (2)

File spec/core/EventMessageSpec.coffee

 	describe "error proxy", ->
 		msg = null
 		msgNoReply = null
+		errorMsg = null
 		replier = null
 		handler = null
 		beforeEach ->
 			handler = sinon.spy()
 			msg = new EventMessage "address", null, replier
 			msgNoReply = new EventMessage "address"
+			errorMsg = new EventMessage
+			errorMsg.status = "error"
+			errorMsg.error = "Error"
 
 		it "should propagate own errors unless it has a reply handler", ->
-			# msg has an error
+			# msg has an error:
 			# msg.proxyErrors (reply) =>
 			# data on `reply` should also be propagated.
 
 				expect(reply).toBe msg
 
 		it "should propagate reply errors unless it has a reply handler", ->
-			# reply has an error
+			# reply has an error:
 			# msg.proxyErrors (reply) =>
 			# data on `reply` should also be propagated.
-			errorMsg = new EventMessage
-			errorMsg.status = "error"
-			errorMsg.error = "Error"
+
 			# No reply should throw the exception directly.
 			proxyFuncNoReply = msgNoReply.proxyErrors handler
 			testNoReply = -> proxyFuncNoReply errorMsg
 				expect(reply.error).toBe "Error"
 
 		it "should propagate thrown errors unless it has a reply handler", ->
-			# Supplied handler threw an error
+			# Supplied handler threw an error:
 			# msg.proxy (reply) =>
 			handler = sinon.spy -> throw new Error "Error"
 			# No reply should throw the exception directly.
 				reply = replier.getCall(0).args[0]
 				expect(reply.status).toBe "error"
 				expect(reply.error.split("\n")[0]).toBe "Error: Error :: Error: Error"
+
+		it "should accept an optional message an proxy error unless it has a reply handler", ->
+			# otherMsg has an error:
+			# msg.proxy otherMsg, (reply) =>
+
+			# No reply should throw the exception directly.
+			testNoReply = -> msgNoReply.proxyErrors errorMsg, handler
+			expect(testNoReply).toThrow "Error"
+			expect(handler.callCount).toBe 0
+			# With reply handler should pass the error along.
+			msg.proxyErrors errorMsg, handler
+			waitsFor (-> replier.called), "Replier never called", 100
+			runs ->
+				expect(replier.callCount).toBe 1
+				expect(handler.callCount).toBe 0
+				reply = replier.getCall(0).args[0]
+				expect(reply).toBe errorMsg

File src/core/EventMessage.coffee

 		@reply msg
 		return @
 
-	# Returns an event handler which will automatically catch and propagate errors,
+	# Returns a wrapping event handler which will automatically catch and propagate errors,
 	# removing the need to constantly check incoming messages for errors.
-	#     msg.proxyErrors (reply) ->
-	# Reply will never be an error message, as this would be sent back to the reply handler of message.
-	# If not reply handler is present on the message, errors are thrown instead.
-	proxyErrors: (handler) ->
+	# Example usage:
+	#
+	#     @send "address", msg.proxyErrors otherMsg, (reply) ->
+	#
+	# In the above example, proxyErrors will check msg and otherMsg for errors, and pass them to the reply handler
+	# for msg. If no errors are detected, it will execute the supplied handler inside a try/catch block, and pass
+	# any errors back through msg.
+	# If no reply handler exists on msg, errors will be rethrown, or no try/catch block will be used.
+	# otherMsg is optional.
+	proxyErrors: (otherMsg, handler) ->
+		unless otherMsg instanceof EventMessage and _.isFunction handler
+			if _.isFunction otherMsg
+				handler = otherMsg
+				otherMsg = undefined
+			else
+				throw new Error "Optional otherMsg must be an EventMessage and handler must be a function, msg:#{typeof otherMsg}, handler:#{typeof handler}"
 		# If we don't have a reply handler, just return a passthrough function.
 		unless _.isFunction @_replyHandler
 			# Throw error if we have one.
 			if @isError()
 				throw @error
+			if otherMsg? and otherMsg.isError()
+				throw otherMsg.error
 			# Create and return handler.
 			return (msg) ->
 				# Pass message errors.
 				if msg.isError()
 					throw msg.error
 				# No error, pass to handler.
-				handler msg
+				handler msg if _.isFunction handler
 		# If we have a reply handler, we need to be more sophisticated.
 		else
 			# Pass errors on self.
 			if @isError()
 				@reply @
 				return
+			if otherMsg? and otherMsg.isError()
+				@reply otherMsg
 			# Create and return handler.
 			return (msg) =>
 				# Pass message errors.
 					@reply msg
 					return
 				# Setup try/catch block and execute handler.
-				try
-					handler msg
-				catch err
-					@replyError err
-					return
+				if _.isFunction handler
+					try
+						handler msg
+					catch err
+						@replyError err
+						return
 
 	# ## `isSuccess()`
 	# Returns true if this message is marked successful, which is the default state.