@@ -4,9 +4,10 @@ import (
44 "context"
55 "fmt"
66 "log"
7- "strconv "
7+ "log/slog "
88 "time"
99
10+ "github.com/wille/haprovider/internal/eth"
1011 "github.com/wille/haprovider/internal/rpc"
1112)
1213
@@ -18,6 +19,8 @@ const (
1819
1920 // Internal JSON-RPC error
2021 EthErrorInternalError = - 32603
22+
23+ BlockLagTolerance = 50
2124)
2225
2326type Healthcheck func (ctx context.Context , p * Endpoint , e * Provider , read rpc.ReaderFunc ) error
@@ -58,8 +61,24 @@ func EthereumHealthCheck(ctx context.Context, p *Endpoint, e *Provider, read rpc
5861 return err
5962 }
6063
61- if _ , ok := res .Result .(string ); ! ok {
62- return fmt .Errorf ("block number is not a string" )
64+ if currentBlockHex , ok := res .Result .(string ); ok {
65+ currentBlock , err := eth .ParseHexNumber (currentBlockHex )
66+ if err != nil {
67+ return fmt .Errorf ("failed to parse block number: %v (%s)" , err , currentBlockHex )
68+ }
69+
70+ if e .highestBlock != 0 && currentBlock < e .highestBlock - BlockLagTolerance {
71+ log := slog .With ("provider" , e .Name , "endpoint" , p .Name )
72+ log .Warn ("node is behind" , "currentBlock" , currentBlock , "highestBlock" , e .highestBlock )
73+
74+ return fmt .Errorf ("node is behind: currentBlock=%d, highestBlock=%d" , currentBlock , e .highestBlock )
75+ }
76+
77+ if currentBlock > e .highestBlock {
78+ e .highestBlock = currentBlock
79+ }
80+ } else {
81+ return fmt .Errorf ("block number is not a string: %v" , res .Result )
6382 }
6483
6584 res , err = read (ctx , rpc .NewRequest ("ha_syncing" , "eth_syncing" , nil ), true )
@@ -71,8 +90,8 @@ func EthereumHealthCheck(ctx context.Context, p *Endpoint, e *Provider, read rpc
7190 currentBlockHex := m ["currentBlock" ].(string )
7291 highestBlockHex := m ["highestBlock" ].(string )
7392
74- currentBlock , _ := strconv . ParseUint (currentBlockHex , 16 , 64 )
75- highestBlock , _ := strconv . ParseUint (highestBlockHex , 16 , 64 )
93+ currentBlock , _ := eth . ParseHexNumber (currentBlockHex )
94+ highestBlock , _ := eth . ParseHexNumber (highestBlockHex )
7695
7796 return fmt .Errorf ("node is not synced: currentBlock=%d, highestBlock=%d" , currentBlock , highestBlock )
7897 }
@@ -102,7 +121,16 @@ func SolanaHealthcheck(ctx context.Context, endpoint *Endpoint, provider *Provid
102121 return err
103122 }
104123
105- if _ , ok := res .Result .(float64 ); ! ok {
124+ if bf , ok := res .Result .(float64 ); ! ok {
125+ blockHeight := uint64 (bf )
126+
127+ if blockHeight > provider .highestBlock {
128+ provider .highestBlock = blockHeight
129+ }
130+
131+ if blockHeight < provider .highestBlock - BlockLagTolerance {
132+ return fmt .Errorf ("node is behind: currentBlock=%d, highestBlock=%d" , blockHeight , provider .highestBlock )
133+ }
106134 return fmt .Errorf ("block height is not a number: %v" , res .Result )
107135 }
108136
0 commit comments