Skip to content

Commit

Permalink
bring in auto instantiation for Receiver#flunk
Browse files Browse the repository at this point in the history
The receiver implementation should know about its domain and direct the
engine via the flunk method. In other words, the receiver implementation
knows what is a remote error [class] or not and calls flunk accordingly.

The ReceivedError class is at the disposal of receiver implementations to
wrap remote errors with unknown classes or any error that is simply, remote.

The name "ReceivedError" could be changed to "RemoteError" or "WrappedError",
let's keep that open for a week. "ReceivedError" sounds OK because it's
useful along with a Receiver.

Let's not try to make flunk too smart.
  • Loading branch information
jmettraux committed May 3, 2013
1 parent 86c0837 commit 81abe4d
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 21 deletions.
28 changes: 21 additions & 7 deletions lib/ruote/receiver/base.rb
Expand Up @@ -25,6 +25,15 @@

module Ruote

# Used to extract a backtrace if present as the last item of a list
# of arguments. Modifies the argument list if found...
#
def self.pop_trace(args)

l = args.last
( ! l.is_a?(Array)) || l.find { |e| ( ! e.is_a?(String)) } ? nil : args.pop
end

#
# For remote/received errors, errors whose class is unknown in
# the ruote worker process.
Expand All @@ -34,12 +43,15 @@ class ReceivedError < StandardError
attr_reader :classname
attr_reader :arguments

def initialize(classname, args)
def initialize(classname, *args)

super(args.first)
trace = Ruote.pop_trace(args)

super("#{classname}: #{args.first}")

@classname = classname
@arguments = args
set_backtrace(trace)
end
end

Expand Down Expand Up @@ -99,18 +111,20 @@ def reply(workitem)
def flunk(workitem, error_class_or_instance_or_message, *err_arguments)

err = error_class_or_instance_or_message
trace = err_arguments.last.is_a?(Array) ? err_arguments.pop : nil
trace = Ruote.pop_trace(err_arguments)

err =
case err
when Exception
err
when /^[A-Za-z:]+Error$/
ReceivedError.new(err, err_arguments)
when String
RuntimeError.new(err)
when Class
err.new(*err_arguments)
when String
begin
Ruote.constantize(err).new(*err_arguments)
rescue #NameError # rescue instanciation errors too
RuntimeError.new(err)
end
else
ArgumentError.new(
"flunk() failed, cannot bring back err from #{err.inspect}")
Expand Down
63 changes: 49 additions & 14 deletions test/functional/ft_25_receiver.rb
Expand Up @@ -259,18 +259,6 @@ def on_workitem
end
end

class ::MultipleArgumentsError < RuntimeError

def initialize(a, b)
@a = a
@b = b
end

def message
"#{@a} #{@b}"
end
end

def test_backtrace_flunk

@dashboard.register :alpha, BacktraceFlunkParticipant
Expand Down Expand Up @@ -321,7 +309,14 @@ def test_exception_instance_flunk
class NonInstantiationFlunkParticipant < Ruote::Participant

def on_workitem
flunk(workitem, 'SomeUnknownError', 'out of order', [ 'some backtrace' ])
#flunk(
# workitem, 'SomeUnknownConstant', 'out of order', [ 'some backtrace' ])
#
# Rather
#
flunk(
workitem,
Ruote::ReceivedError.new('SomeConstant', 'out of order', [ 'trace' ]))
end
end

Expand All @@ -338,13 +333,53 @@ def test_non_instantiation_flunk

assert_equal 'error_intercepted', r['action']
assert_equal 'Ruote::ReceivedError', r['error']['class']
assert_equal 'SomeConstant: out of order', r['error']['message']
assert_match 'trace', r['error']['trace'].first

ps = @dashboard.ps(wfid)
assert_equal String, ps.errors.first.at.class
end

class AutoInstantiationFlunkParticipant < Ruote::Participant

def on_workitem
flunk(
workitem, 'ArgumentError', 'out of order', [ 'some backtrace' ])
end
end

def test_auto_instantiation_flunk

@dashboard.register :alpha, AutoInstantiationFlunkParticipant

wfid =
@dashboard.launch(Ruote.define do
alpha
end)

r = @dashboard.wait_for(wfid)

assert_equal 'error_intercepted', r['action']
assert_equal 'ArgumentError', r['error']['class']
assert_equal 'out of order', r['error']['message']
assert_match 'some backtrace', r['error']['trace'].first
assert_match 'trace', r['error']['trace'].first

ps = @dashboard.ps(wfid)
assert_equal String, ps.errors.first.at.class
end

class ::MultipleArgumentsError < RuntimeError

def initialize(a, b)
@a = a
@b = b
end

def message
"#{@a} #{@b}"
end
end

class MultipleArgumentsFlunkParticipant < Ruote::Participant

def on_workitem
Expand Down

0 comments on commit 81abe4d

Please sign in to comment.