Skip to content

Commit

Permalink
Discourage feature use by making it hard to use
Browse files Browse the repository at this point in the history
It is no longer documented publicly, and overriding the default behavior
requires monkey-patching a private method, which should hopefully
discourage any library usage.
  • Loading branch information
grddev committed Oct 28, 2015
1 parent c64a0fe commit 2808a40
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 130 deletions.
33 changes: 3 additions & 30 deletions lib/ione/future.rb
Expand Up @@ -739,32 +739,11 @@ def failed?
end
end

class <<self
# Set the global listener for handling uncaught errors in other registered
# future listeners. The listener will be called with the error that failed
# the future as sole argument.
#
# Errors raised from the global listener will be ignored.
#
# By default, the global error handler does nothing.
#
# @example
# Future.on_listener_error do do |error|
# LOGGER.warn("Uncaught error: #{error} (#{error.class})")
# end
#
# @yieldparam [Object] error the uncaught error from the listener dispatch
def on_listener_error(&listener_error_handler)
@listener_error_handler = listener_error_handler
nil
end
private

# @private
attr_reader :listener_error_handler
def discard_error(e)
end

private

def call_listener(listener)
begin
n = listener.arity
Expand All @@ -778,13 +757,7 @@ def call_listener(listener)
listener.call(@value, @error, self)
end
rescue => e
begin
if (error_handler = Ione::Future.listener_error_handler)
error_handler.call(e)
end
rescue
# swallowed
end
discard_error(e)
end
end
end
Expand Down
100 changes: 0 additions & 100 deletions spec/ione/future_spec.rb
Expand Up @@ -127,20 +127,6 @@ module Ione
StandardError.new('bork')
end

let :listener_error_handler do
double(:listener_error_handler)
end

before do
@old_error_handler = Ione::Future.listener_error_handler
listener_error_handler.stub(:call)
Ione::Future.on_listener_error { |error| listener_error_handler.call(error) }
end

after do
Ione::Future.on_listener_error(&@old_error_handler)
end

def async(*context, &listener)
Thread.start(*context, &listener)
end
Expand Down Expand Up @@ -344,22 +330,6 @@ def delayed(*context, &listener)
err.message.should == 'bork'
end

it 'notifies the global error listener when one raises an error' do
future.on_complete { |f| raise IoError, 'Blurgh' }
future.on_complete { |f| 'foo' }
promise.fulfill('bar')
listener_error_handler.should have_received(:call).with(kind_of(IoError))
end

it 'notifies all listeners when the promise is fulfilled, even when one raises an error and the global error listener raises an error' do
value = nil
listener_error_handler.stub(:call).and_raise(RuntimeError, 'bork')
future.on_complete { |f| raise 'Blurgh' }
future.on_complete { |f| value = f.value }
promise.fulfill('bar')
value.should == 'bar'
end

it 'notifies listeners registered after the promise was fulfilled' do
f, v, e = nil, nil, nil
promise.fulfill('bar')
Expand All @@ -383,18 +353,6 @@ def delayed(*context, &listener)
expect { future.on_complete { raise 'blurgh' } }.to_not raise_error
end

it 'notifies the global error listener when one raises an error when future already failed' do
promise.fail(error)
expect { future.on_complete { raise IoError, 'blurgh' } }.to_not raise_error
listener_error_handler.should have_received(:call).with(kind_of(IoError))
end

it 'does not raise any error when the global error listener fails when future already failed' do
promise.fail(error)
listener_error_handler.stub(:call).and_raise(RuntimeError, 'bork')
expect { future.on_complete { raise 'blurgh' } }.to_not raise_error
end

it 'returns nil' do
future.on_complete { :foo }.should be_nil
end
Expand Down Expand Up @@ -430,22 +388,6 @@ def delayed(*context, &listener)
value.should == 'bar'
end

it 'notifies the global error listener when one raises an error' do
future.on_value { |v| raise IoError, 'Blurgh' }
future.on_value { |v| 'foo' }
promise.fulfill('bar')
listener_error_handler.should have_received(:call).with(kind_of(IoError))
end

it 'notifies all listeners when the promise is fulfilled, even when one raises an error and the global error listener raises an error' do
value = nil
listener_error_handler.stub(:call).and_raise(RuntimeError, 'bork')
future.on_value { |v| raise 'Blurgh' }
future.on_value { |v| value = v }
promise.fulfill('bar')
value.should == 'bar'
end

it 'notifies listeners registered after the promise was resolved' do
v1, v2 = nil, nil
promise.fulfill('bar')
Expand All @@ -460,18 +402,6 @@ def delayed(*context, &listener)
expect { future.on_value { |v| raise 'blurgh' } }.to_not raise_error
end

it 'notifies the global error listener when one raises an error when future already resolved' do
promise.fulfill('bar')
expect { future.on_value { raise IoError, 'blurgh' } }.to_not raise_error
listener_error_handler.should have_received(:call).with(kind_of(IoError))
end

it 'does not raise any error when the global error listener fails when future already resolved' do
promise.fulfill('bar')
listener_error_handler.stub(:call).and_raise(RuntimeError, 'bork')
expect { future.on_value { raise 'blurgh' } }.to_not raise_error
end

it 'returns nil' do
future.on_value { :foo }.should be_nil
end
Expand Down Expand Up @@ -502,24 +432,6 @@ def delayed(*context, &listener)
e.message.should eql(error.message)
end

it 'notifies the global error listener when one raises an error' do
e = nil
future.on_failure { |err| raise IoError, 'Blurgh' }
future.on_failure { |err| e = err }
promise.fail(error)
listener_error_handler.should have_received(:call).with(kind_of(IoError))
e.message.should eql(error.message)
end

it 'notifies all listeners when the promise is fulfilled, even when one raises an error and the global error listener raises an error' do
e = nil
listener_error_handler.stub(:call).and_raise(RuntimeError, 'bork')
future.on_failure { |err| raise 'Blurgh' }
future.on_failure { |err| e = err }
promise.fail(error)
e.message.should eql(error.message)
end

it 'notifies new listeners even when already failed' do
e1, e2 = nil, nil
promise.fail(error)
Expand All @@ -534,18 +446,6 @@ def delayed(*context, &listener)
expect { future.on_failure { |e| raise 'Blurgh' } }.to_not raise_error
end

it 'notifies the global error listener when one raises an error when future already failed' do
promise.fail(error)
expect { future.on_failure { raise IoError, 'blurgh' } }.to_not raise_error
listener_error_handler.should have_received(:call).with(kind_of(IoError))
end

it 'does not raise any error when the global error listener fails when future already failed' do
promise.fail(error)
listener_error_handler.stub(:call).and_raise(RuntimeError, 'bork')
expect { future.on_failure { raise 'blurgh' } }.to_not raise_error
end

it 'returns nil' do
future.on_failure { :foo }.should be_nil
end
Expand Down

0 comments on commit 2808a40

Please sign in to comment.