Class: ExceptionCatcher

Inherits:
Object show all
Defined in:
lib/util/exception_catcher.rb

Overview

ExceptionCatcher makes it easy to execute multiple operations even though any might fail with exception

  • executed tasks can be named to make it easier to identify which tasks failed

  • collects result and exceptions for each executed task

  • raises a MultipleExceptions exception if there were more than one exception

    catcher = ExceptionCatcher.new
    catcher.catch(1){raise "1"}
    catcher.catch(2){raise "2"}
    catcher.catch(3){"ok!"}
    catcher.exception(1) # -> exception object raised by the task 1
    catcher.exception(2) # -> exception object raise by the task 2
    catcher.result(3) # -> "ok!"
    catcher.check # raises a MultipleExceptions exception
    

Defined Under Namespace

Classes: MultipleExceptions

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeExceptionCatcher



36
37
38
39
40
41
# File 'lib/util/exception_catcher.rb', line 36

def initialize
  @mutex = Mutex.new
  @results = {}
  @exceptions = {}
  @tasks = []
end

Instance Attribute Details

#exceptionsObject (readonly)

Returns the value of attribute exceptions.



34
35
36
# File 'lib/util/exception_catcher.rb', line 34

def exceptions
  @exceptions
end

#mutexObject (readonly)

Returns the value of attribute mutex.



34
35
36
# File 'lib/util/exception_catcher.rb', line 34

def mutex
  @mutex
end

#resultsObject (readonly)

Returns the value of attribute results.



34
35
36
# File 'lib/util/exception_catcher.rb', line 34

def results
  @results
end

#tasksObject (readonly)

Returns the value of attribute tasks.



34
35
36
# File 'lib/util/exception_catcher.rb', line 34

def tasks
  @tasks
end

Instance Method Details

#catch(task = nil, &block) ⇒ Object?

Catches exceptions thrown by block



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/util/exception_catcher.rb', line 47

def catch(task=nil, &block)
  if task.nil?
    task = block
  end
  @mutex.synchronize do
    @tasks << task
  end
  begin
    result = block.call
    @mutex.synchronize do
      @results[task]=result
    end
    result
  rescue Exception => e
    @mutex.synchronize do
      @exceptions[task]=e
    end
    nil
  end
end

#checkObject

Checks if there has been exceptions and raises the original exception if there has been one exception and MultipleExceptions if there has been many exceptions



90
91
92
93
94
95
96
97
98
99
# File 'lib/util/exception_catcher.rb', line 90

def check
  @mutex.synchronize do
    if @exceptions.size == 1
      e = @exceptions.values.first
      raise e.class, e.message, e.backtrace
    elsif @exceptions.size > 1
      raise MultipleExceptions.new("Caught #{@exceptions.size} exceptions!").catcher(self)
    end
  end
end

#exception(task) ⇒ Object?



78
79
80
81
82
# File 'lib/util/exception_catcher.rb', line 78

def exception(task)
  @mutex.synchronize do
    @exceptions[task]
  end
end

#exceptions?bool



85
86
87
# File 'lib/util/exception_catcher.rb', line 85

def exceptions?
  @exceptions.size > 0
end

#result(task) ⇒ Object?



70
71
72
73
74
# File 'lib/util/exception_catcher.rb', line 70

def result(task)
  @mutex.synchronize do
    @results[task]
  end
end