Class: Bunny::Concurrent::ExceptionAccumulator

Inherits:
Object
  • Object
show all
Defined in:
lib/bunny/concurrent/exception_accumulator.rb

Overview

A thread-safe exception accumulator that stores exceptions for later retrieval instead of immediately raising them in the calling thread.

This is the default session error handler in Bunny. When errors occur in background threads (such as the reader loop or transport), they are stored in the accumulator rather than being raised asynchronously in the thread that created the session.

This prevents dangerous control flow interruptions that can occur when exceptions are raised asynchronously via Thread#raise.

Examples:

Checking for accumulated exceptions

conn = Bunny.new
conn.start
# ... do work ...
if conn.exception_occurred?
  exceptions = conn.exceptions
  # handle exceptions appropriately
end

See Also:

Instance Method Summary collapse

Constructor Details

#initializeExceptionAccumulator

Returns a new instance of ExceptionAccumulator.



28
29
30
31
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 28

def initialize
  @exceptions = []
  @mutex = Mutex.new
end

Instance Method Details

#allArray<Exception>

Returns all accumulated exceptions.

Returns:



67
68
69
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 67

def all
  @mutex.synchronize { @exceptions.dup }
end

#any?Boolean

Returns true if any exceptions have been accumulated.

Returns:

  • (Boolean)


46
47
48
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 46

def any?
  @mutex.synchronize { @exceptions.any? }
end

#clearArray<Exception>

Clears all accumulated exceptions.

Returns:

  • (Array<Exception>)

    the exceptions that were cleared



82
83
84
85
86
87
88
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 82

def clear
  @mutex.synchronize do
    cleared = @exceptions.dup
    @exceptions.clear
    cleared
  end
end

#countInteger

Returns the number of accumulated exceptions.

Returns:

  • (Integer)


60
61
62
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 60

def count
  @mutex.synchronize { @exceptions.count }
end

#empty?Boolean

Returns true if no exceptions have been accumulated.

Returns:

  • (Boolean)


53
54
55
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 53

def empty?
  @mutex.synchronize { @exceptions.empty? }
end

#popException?

Returns and removes the first accumulated exception (FIFO order). Returns nil if no exceptions have been accumulated.

Returns:



75
76
77
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 75

def pop
  @mutex.synchronize { @exceptions.shift }
end

#raise(exception) ⇒ Object

Called by background threads to record an exception. This method is compatible with Thread#raise interface.

Parameters:

  • exception (Exception)

    the exception to accumulate



37
38
39
40
41
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 37

def raise(exception)
  @mutex.synchronize do
    @exceptions << exception
  end
end

#raise_all!Object

Raises all accumulated exceptions wrapped in a single exception if any exist, clearing the accumulator.

Raises:



103
104
105
106
107
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 103

def raise_all!
  exceptions = clear
  return if exceptions.empty?
  Kernel.raise AccumulatedExceptions.new(exceptions)
end

#raise_first!Object

Raises the first accumulated exception if any exist, removing it from the accumulator. Does nothing if no exceptions have been accumulated.

Raises:

  • (Exception)

    the first accumulated exception



94
95
96
97
# File 'lib/bunny/concurrent/exception_accumulator.rb', line 94

def raise_first!
  exception = pop
  Kernel.raise exception if exception
end