Class: Bulldogger::Pending

Inherits:
Object
  • Object
show all
Defined in:
lib/bulldogger/pending.rb

Overview

Insertion-ordered, bounded map from an exception object to its captured snapshot. Bounded because most raises are caught and handled by the app and never become a test failure -- without a cap, a suite that raises-and-rescues heavily would grow this map without limit. Matches by object identity (equal?), not hash/ eql?, so an exception class that overrides those can't collide with an unrelated exception instance.

ObjectSpace::WeakMap was considered and rejected: its eviction is driven by GC timing, which we cannot observe or bound, and its membership semantics would need the same identity-matching logic this class already provides directly.

Defined Under Namespace

Classes: Entry

Instance Method Summary collapse

Constructor Details

#initialize(max_size) ⇒ Pending

Returns a new instance of Pending.



19
20
21
22
23
24
# File 'lib/bulldogger/pending.rb', line 19

def initialize(max_size)
  @max_size = max_size
  @entries = []
  @evicted = []
  @mutex = Mutex.new
end

Instance Method Details

#evicted?(exception) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/bulldogger/pending.rb', line 48

def evicted?(exception)
  @mutex.synchronize { @evicted.any? { |e| e.equal?(exception) } }
end

#get(exception) ⇒ Object



44
45
46
# File 'lib/bulldogger/pending.rb', line 44

def get(exception)
  @mutex.synchronize { find(exception)&.snapshot }
end

#put(exception, snapshot) ⇒ Object

First-write-wins: a re-raised exception (rescue; raise) fires :raise again from the rescue frame. That second capture is worth less than the first -- it points at the handler, not the bug -- so an exception already in the ring keeps its original snapshot.



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/bulldogger/pending.rb', line 30

def put(exception, snapshot)
  @mutex.synchronize do
    next if find(exception)

    @entries << Entry.new(exception, snapshot)
    next unless @entries.size > @max_size

    evicted_entry = @entries.shift
    @evicted << evicted_entry.exception
    @evicted.shift if @evicted.size > @max_size
  end
  nil
end