22require 'retriable'
33
44class L1RpcPrefetcher
5+ include Memery
56 def initialize ( ethereum_client :,
67 ahead : ENV . fetch ( 'L1_PREFETCH_FORWARD' , Rails . env . test? ? 5 : 200 ) . to_i ,
78 threads : ENV . fetch ( 'L1_PREFETCH_THREADS' , 2 ) . to_i )
@@ -17,19 +18,20 @@ def initialize(ethereum_client:,
1718 end
1819
1920 def ensure_prefetched ( from_block )
20- to_block = from_block + @ahead
21+ # Check current chain tip first
22+ latest = get_latest_block_number
23+
24+ # Don't prefetch beyond chain tip
25+ to_block = [ from_block + @ahead , latest ] . min
26+
2127 # Only create promises for blocks we don't have yet
2228 blocks_to_fetch = ( from_block ..to_block ) . reject { |n | @promises . key? ( n ) }
2329
2430 return if blocks_to_fetch . empty?
2531
26- # Only enqueue a reasonable number at once to avoid overwhelming the promise system
27- max_to_enqueue = [ @threads * 10 , 50 ] . min
28-
29- to_enqueue = blocks_to_fetch . first ( max_to_enqueue )
30- Rails . logger . debug "Enqueueing #{ to_enqueue . size } of #{ blocks_to_fetch . size } blocks: #{ to_enqueue . first } ..#{ to_enqueue . last } "
32+ Rails . logger . debug "Enqueueing #{ blocks_to_fetch . size } blocks: #{ blocks_to_fetch . first } ..#{ blocks_to_fetch . last } "
3133
32- to_enqueue . each { |block_number | enqueue_single ( block_number ) }
34+ blocks_to_fetch . each { |block_number | enqueue_single ( block_number ) }
3335 end
3436
3537 def fetch ( block_number )
@@ -104,6 +106,11 @@ def shutdown
104106
105107 private
106108
109+ def get_latest_block_number
110+ @eth . get_block_number
111+ end
112+ memoize :get_latest_block_number , ttl : 12 . seconds
113+
107114 def enqueue_single ( block_number )
108115 @promises . compute_if_absent ( block_number ) do
109116 Rails . logger . debug "Creating promise for block #{ block_number } "
0 commit comments