99 "sync/atomic"
1010 "time"
1111
12- "github.com/creachadair/jrpc2"
1312 "github.com/stellar/go/xdr"
1413 rpc "github.com/stellar/stellar-rpc/client"
1514 "github.com/stellar/stellar-rpc/protocol"
@@ -26,15 +25,16 @@ func (e *RPCLedgerMissingError) Error() string {
2625 return fmt .Sprintf ("ledger %d was not present on rpc" , e .Sequence )
2726}
2827
29- type RPCLedgerBeyondLatestError struct {}
28+ type rpcLedgerBeyondLatestError struct {}
3029
31- func (e RPCLedgerBeyondLatestError ) Error () string {
30+ func (e rpcLedgerBeyondLatestError ) Error () string {
3231 return "ledger is not available on the RPC server yet"
3332}
3433
3534// The minimum required RPC client methods used by RPCLedgerBackend.
3635type RPCLedgerGetter interface {
3736 GetLedgers (ctx context.Context , req protocol.GetLedgersRequest ) (protocol.GetLedgersResponse , error )
37+ GetHealth (ctx context.Context ) (protocol.GetHealthResponse , error ) // <-- Added
3838}
3939
4040type RPCLedgerBackend struct {
@@ -144,7 +144,7 @@ func (b *RPCLedgerBackend) GetLedger(ctx context.Context, sequence uint32) (xdr.
144144 return lcm , nil
145145 }
146146
147- var beyondErr * RPCLedgerBeyondLatestError
147+ var beyondErr * rpcLedgerBeyondLatestError
148148 if ! (errors .As (err , & beyondErr )) {
149149 return xdr.LedgerCloseMeta {}, err
150150 }
@@ -180,7 +180,7 @@ func (b *RPCLedgerBackend) PrepareRange(ctx context.Context, ledgerRange Range)
180180 _ , err := b .getBufferedLedger (ctx , ledgerRange .from )
181181 if err != nil {
182182 // beyond latest is handled later in GetLedger
183- var beyondErr * RPCLedgerBeyondLatestError
183+ var beyondErr * rpcLedgerBeyondLatestError
184184 if ! (errors .As (err , & beyondErr )) {
185185 return err
186186 }
@@ -238,7 +238,16 @@ func (b *RPCLedgerBackend) getBufferedLedger(ctx context.Context, sequence uint3
238238 return lcm , nil
239239 }
240240
241- // Ledger not in buffer, fetch a small batch from RPC starting from the requested sequence
241+ // Check if requested ledger is beyond the RPC retention window using GetHealth
242+ health , err := b .client .GetHealth (ctx )
243+ if err != nil {
244+ return xdr.LedgerCloseMeta {}, fmt .Errorf ("failed to get health from RPC: %w" , err )
245+ }
246+ if sequence > health .LatestLedger {
247+ return xdr.LedgerCloseMeta {}, & rpcLedgerBeyondLatestError {}
248+ }
249+
250+ // attempt to fetch a small batch from RPC starting from the requested sequence
242251 req := protocol.GetLedgersRequest {
243252 StartLedger : sequence ,
244253 Pagination : & protocol.LedgerPaginationOptions {
@@ -248,23 +257,11 @@ func (b *RPCLedgerBackend) getBufferedLedger(ctx context.Context, sequence uint3
248257
249258 ledgers , err := b .client .GetLedgers (ctx , req )
250259 if err != nil {
251- // InvalidRequest code is the most specific error code provided for invalid range requests.
252- // https://github.com/stellar/stellar-rpc/pull/407/
253- // if received, assume it's range problem to enable retry.
254- var rpcErr * jrpc2.Error
255- if errors .As (err , & rpcErr ) && rpcErr .Code == jrpc2 .InvalidRequest {
256- return xdr.LedgerCloseMeta {}, & RPCLedgerBeyondLatestError {}
257- }
258- return xdr.LedgerCloseMeta {}, fmt .Errorf ("failed to get ledgers starting from %d: %w" , sequence , err )
260+ return xdr.LedgerCloseMeta {}, err
259261 }
260262
261263 b .initBuffer ()
262264
263- // Check if requested ledger is beyond the RPC retention window
264- if sequence > ledgers .LatestLedger {
265- return xdr.LedgerCloseMeta {}, & RPCLedgerBeyondLatestError {}
266- }
267-
268265 // Populate buffer with new ledgers
269266 for _ , ledger := range ledgers .Ledgers {
270267 var lcm xdr.LedgerCloseMeta
0 commit comments