Class: Findbug::Storage::ConnectionPool

Inherits:
Object
  • Object
show all
Defined in:
lib/findbug/storage/connection_pool.rb

Overview

ConnectionPool manages Redis connections for Findbug.

WHY A SEPARATE POOL?

Your Rails app likely already uses Redis for:

  • Sidekiq (job queue)

  • Caching (Rails.cache)

  • Action Cable (websockets)

If Findbug shared these connections, we could:

  1. Starve your app of connections during high error rates

  2. Cause Sidekiq jobs to timeout waiting for connections

  3. Create unpredictable latency spikes

By maintaining our OWN pool, Findbug is isolated. If our pool is exhausted, only Findbug suffers - your app keeps running.

HOW CONNECTION POOLING WORKS

Without pooling:
Thread 1 → create connection → use → close
Thread 2 → create connection → use → close  (expensive!)
Thread 3 → create connection → use → close

With pooling:
Thread 1 → borrow connection → use → return to pool
Thread 2 → borrow connection → use → return to pool
Thread 3 → borrow connection → use → return to pool
                ↓
         [Pool of 5 connections]

The ‘connection_pool` gem handles:

  • Creating connections lazily (only when needed)

  • Returning connections automatically (via block)

  • Waiting for available connections (with timeout)

  • Thread-safety (multiple threads can’t corrupt state)

Class Method Summary collapse

Class Method Details

.healthy?Boolean

Check if a connection can be established

This is used by the circuit breaker to test if Redis is back up.

Returns:

  • (Boolean)

    true if Redis is reachable



93
94
95
96
97
# File 'lib/findbug/storage/connection_pool.rb', line 93

def healthy?
  with { |redis| redis.ping == "PONG" }
rescue StandardError
  false
end

.pool::ConnectionPool

Get the raw pool (for advanced usage)

Returns:

  • (::ConnectionPool)

    the underlying connection pool



73
74
75
# File 'lib/findbug/storage/connection_pool.rb', line 73

def pool
  @pool ||= create_pool
end

.shutdown!Object

Shutdown the pool (for cleanup/testing)

This closes all connections and resets the pool. Call this when shutting down your app or between tests.



82
83
84
85
# File 'lib/findbug/storage/connection_pool.rb', line 82

def shutdown!
  @pool&.shutdown { |redis| redis.close }
  @pool = nil
end

.with {|Redis| ... } ⇒ Object

Get a connection from the pool and execute a block

WHY A BLOCK?


The block pattern ensures connections are ALWAYS returned to the pool. Even if an exception occurs, the connection goes back. This prevents connection leaks.

Examples:

ConnectionPool.with do |redis|
  redis.lpush("findbug:errors", data.to_json)
end

Yields:

  • (Redis)

    a Redis connection

Returns:

  • (Object)

    the return value of the block



65
66
67
# File 'lib/findbug/storage/connection_pool.rb', line 65

def with(&block)
  pool.with(&block)
end