main
1# frozen_string_literal: true
2
3module Net
4 module Hippie
5 # Thread-safe connection pool with LRU eviction.
6 class ConnectionPool
7 def initialize(max_size: 100, dns_ttl: 300)
8 @max_size = max_size
9 @dns_ttl = dns_ttl
10 @connections = {}
11 @monitor = Monitor.new
12 end
13
14 def checkout(key, &block)
15 reuse(key) || create(key, &block)
16 end
17
18 def close_all
19 @monitor.synchronize do
20 @connections.each_value(&:close)
21 @connections.clear
22 end
23 end
24
25 private
26
27 def reuse(key)
28 @monitor.synchronize do
29 return nil unless @connections.key?(key)
30
31 conn = @connections.delete(key)
32 return @connections[key] = conn unless conn.stale?(@dns_ttl)
33
34 conn.close
35 nil
36 end
37 end
38
39 def create(key)
40 conn = yield
41 @monitor.synchronize do
42 existing = reuse(key)
43 if existing
44 conn.close
45 return existing
46 end
47 evict_lru if @connections.size >= @max_size
48 @connections[key] = conn
49 end
50 end
51
52 def evict_lru
53 key, conn = @connections.first
54 conn.close
55 @connections.delete(key)
56 end
57 end
58 end
59end