@@ -16,6 +16,8 @@ type State<TFilter, TBlock> = {
1616 lastFinalizedRefresh : number ;
1717 // When the last heartbeat was sent.
1818 lastHeartbeat : number ;
19+ // When the last backfill message was sent.
20+ lastBackfillMessage : number ;
1921 // Track the chain's state.
2022 chainTracker : ChainTracker ;
2123 // Heartbeat interval in milliseconds.
@@ -95,6 +97,7 @@ export class RpcDataStream<TFilter, TBlock> {
9597 cursor,
9698 lastHeartbeat : Date . now ( ) ,
9799 lastFinalizedRefresh : Date . now ( ) ,
100+ lastBackfillMessage : Date . now ( ) ,
98101 chainTracker,
99102 config : this . config ,
100103 heartbeatIntervalMs : this . heartbeatIntervalMs ,
@@ -165,9 +168,14 @@ async function* backfillFinalizedBlocks<TFilter, TBlock>(
165168 const { cursor, chainTracker, config, filter } = state ;
166169 const finalized = chainTracker . finalized ( ) ;
167170
171+ // While backfilling we want to regularly send some blocks (even if empty) so
172+ // that the client can store the cursor.
173+ const force = shouldForceBackfill ( state ) ;
174+
168175 const filterData = await config . fetchBlockRange ( {
169176 startBlock : cursor . orderKey + 1n ,
170177 finalizedBlock : finalized . orderKey ,
178+ force,
171179 filter,
172180 } ) ;
173181
@@ -179,6 +187,7 @@ async function* backfillFinalizedBlocks<TFilter, TBlock>(
179187
180188 for ( const data of filterData . data ) {
181189 state . lastHeartbeat = Date . now ( ) ;
190+ state . lastBackfillMessage = Date . now ( ) ;
182191 yield {
183192 _tag : "data" ,
184193 data : {
@@ -213,6 +222,7 @@ async function* produceNextBlock<TFilter, TBlock>(
213222
214223 const result = await state . config . fetchBlockByNumber ( {
215224 blockNumber : state . cursor . orderKey + 1n ,
225+ isAtHead : isAtHead ( state ) ,
216226 expectedParentBlockHash : currentBlockHash ,
217227 filter : state . filter ,
218228 } ) ;
@@ -325,6 +335,12 @@ function shouldSendHeartbeat(state: State<unknown, unknown>): boolean {
325335 return now - lastHeartbeat >= heartbeatIntervalMs ;
326336}
327337
338+ function shouldForceBackfill ( state : State < unknown , unknown > ) : boolean {
339+ const { lastBackfillMessage, heartbeatIntervalMs } = state ;
340+ const now = Date . now ( ) ;
341+ return now - lastBackfillMessage >= heartbeatIntervalMs ;
342+ }
343+
328344function shouldContinue ( state : State < unknown , unknown > ) : boolean {
329345 const { endingCursor } = state . options || { } ;
330346 if ( endingCursor === undefined ) return true ;
0 commit comments