@@ -44,6 +44,20 @@ function getTxPollIntervalMs(): number {
4444 return Number ( process . env . SOROBAN_TX_POLL_INTERVAL_MS ?? 1_000 ) ;
4545}
4646
47+ const DEFAULT_RPC_HEALTH_CACHE_TTL_MS = 10_000 ;
48+
49+ let rpcHealthCache : { ok : boolean ; expiresAt : number } | null = null ;
50+ let rpcHealthPromise : Promise < boolean > | null = null ;
51+
52+ function getRpcHealthCacheTtlMs ( ) : number {
53+ return Number ( process . env . SOROBAN_RPC_HEALTH_CACHE_TTL_MS ?? DEFAULT_RPC_HEALTH_CACHE_TTL_MS ) ;
54+ }
55+
56+ export function resetRpcHealthCache ( ) : void {
57+ rpcHealthCache = null ;
58+ rpcHealthPromise = null ;
59+ }
60+
4761export class RpcTimeoutError extends Error {
4862 constructor ( label : string , timeoutMs : number ) {
4963 super ( `${ label } timed out after ${ timeoutMs } ms` ) ;
@@ -139,12 +153,36 @@ async function executeRpc<T>(label: string, operation: (server: rpc.Server) => P
139153 * unreachable Soroban RPC endpoint can't hang the health check.
140154 */
141155export async function checkRpcHealth ( timeoutMs = 3_000 ) : Promise < boolean > {
142- try {
143- await withRpcTimeout ( 'soroban rpc health check' , ( ) => executeRpc ( 'soroban rpc health check' , ( server ) => server . getHealth ( ) ) , timeoutMs ) ;
144- return true ;
145- } catch {
146- return false ;
156+ const now = Date . now ( ) ;
157+ const ttlMs = getRpcHealthCacheTtlMs ( ) ;
158+
159+ if ( rpcHealthCache && now < rpcHealthCache . expiresAt ) {
160+ return rpcHealthCache . ok ;
147161 }
162+
163+ if ( rpcHealthPromise ) {
164+ return rpcHealthPromise ;
165+ }
166+
167+ rpcHealthPromise = ( async ( ) => {
168+ try {
169+ const ok = await withRpcTimeout (
170+ 'soroban rpc health check' ,
171+ ( ) => executeRpc ( 'soroban rpc health check' , ( server ) => server . getHealth ( ) ) ,
172+ timeoutMs ,
173+ ) ;
174+ const result = Boolean ( ok ) ;
175+ rpcHealthCache = { ok : result , expiresAt : Date . now ( ) + ttlMs } ;
176+ return result ;
177+ } catch {
178+ rpcHealthCache = { ok : false , expiresAt : Date . now ( ) + ttlMs } ;
179+ return false ;
180+ } finally {
181+ rpcHealthPromise = null ;
182+ }
183+ } ) ( ) ;
184+
185+ return rpcHealthPromise ;
148186}
149187
150188export function setServer ( server : rpc . Server ) : void {
0 commit comments