@@ -8,7 +8,6 @@ import { createSpinner } from "nanospinner";
8
8
import { MIN_HEIGHT , MIN_HEIGHT_HEADER_HASH } from "../utils/config" ;
9
9
import { Environment } from "../utils/Environment" ;
10
10
import NodeCache from "node-cache" ;
11
- import Bottleneck from "bottleneck" ;
12
11
13
12
// Constants
14
13
const FULLNODE_PORT = 8444 ;
@@ -25,17 +24,15 @@ const CACHE_DURATION = 30000; // in milliseconds
25
24
const COOLDOWN_DURATION = 300000 ; // 5 minutes in milliseconds
26
25
const MAX_PEERS_TO_FETCH = 5 ; // Maximum number of peers to fetch from DNS
27
26
const MAX_RETRIES = 3 ; // Maximum number of retry attempts
28
- const MAX_REQUESTS_PER_MINUTE = 100 ; // Per-peer rate limit
29
27
30
28
/**
31
- * Represents a peer with its reliability weight, address, and rate limiter .
29
+ * Represents a peer with its reliability weight and address .
32
30
*/
33
31
interface PeerInfo {
34
32
peer : Peer ;
35
33
weight : number ;
36
34
address : string ;
37
35
isConnected : boolean ; // Indicates if the peer is currently connected
38
- limiter : Bottleneck ; // Rate limiter for the peer
39
36
}
40
37
41
38
/**
@@ -175,7 +172,7 @@ export class FullNodePeer {
175
172
176
173
// Define prioritized peers
177
174
FullNodePeer . prioritizedPeers = [
178
- CHIA_NODES_HOST ,
175
+ ... DNS_HOSTS , // Assuming CHIA_NODES_HOST is included in DNS_HOSTS
179
176
LOCALHOST ,
180
177
] ;
181
178
@@ -348,12 +345,6 @@ export class FullNodePeer {
348
345
// Initialize or update peerInfos and availablePeers
349
346
for ( const ip of peerIPs ) {
350
347
if ( ! FullNodePeer . peerInfos . has ( ip ) ) {
351
- // Create a new Bottleneck limiter for the peer
352
- const limiter = new Bottleneck ( {
353
- maxConcurrent : 1 , // One request at a time per peer
354
- minTime : 60000 / MAX_REQUESTS_PER_MINUTE , // 600 ms between requests for 100 requests/min
355
- } ) ;
356
-
357
348
// Attempt to create a peer connection
358
349
const sslFolder = path . resolve ( os . homedir ( ) , ".dig" , "ssl" ) ;
359
350
const certFile = path . join ( sslFolder , "public_dig.crt" ) ;
@@ -391,7 +382,6 @@ export class FullNodePeer {
391
382
weight : FullNodePeer . peerWeights . get ( ip ) || 1 ,
392
383
address : ip ,
393
384
isConnected : true , // Mark as connected
394
- limiter, // Assign the limiter
395
385
} ) ;
396
386
397
387
// Add to availablePeers
@@ -457,7 +447,7 @@ export class FullNodePeer {
457
447
}
458
448
459
449
/**
460
- * Creates a proxy for the peer to handle errors, implement retries, and enforce per-peer throttling .
450
+ * Creates a proxy for the peer to handle errors, implement retries, and enforce round-robin selection .
461
451
* @param {Peer } peer - The Peer instance.
462
452
* @param {string } peerIP - The IP address of the peer.
463
453
* @param {number } [retryCount=0] - The current retry attempt.
@@ -495,65 +485,48 @@ export class FullNodePeer {
495
485
496
486
const selectedPeerInfo = FullNodePeer . peerInfos . get ( selectedPeerIP ) ! ;
497
487
498
- // Schedule the method call via the selected peer's limiter
499
- return selectedPeerInfo . limiter . schedule ( async ( ) => {
500
- const peerInfo = FullNodePeer . peerInfos . get ( selectedPeerIP ) ;
501
- if ( ! peerInfo || ! peerInfo . isConnected ) {
502
- throw new Error ( `Cannot perform operation: Peer ${ selectedPeerIP } is disconnected.` ) ;
503
- }
504
-
505
- try {
506
- // Bind the original method to the peer instance to preserve 'this'
507
- const boundMethod = originalMethod . bind ( peerInfo . peer ) ;
508
- const result = await boundMethod ( ...args ) ;
509
- // On successful operation, increase the weight slightly
510
- const currentWeight = FullNodePeer . peerWeights . get ( selectedPeerIP ) || 1 ;
511
- FullNodePeer . peerWeights . set ( selectedPeerIP , currentWeight + 0.1 ) ; // Increment weight
512
- return result ;
513
- } catch ( error : any ) {
514
- console . error ( `Peer ${ selectedPeerIP } encountered an error: ${ error . message } ` ) ;
515
-
516
- // Check if the error is related to WebSocket or Operation timed out
517
- if (
518
- error . message . includes ( "WebSocket" ) ||
519
- error . message . includes ( "Operation timed out" )
520
- ) {
521
- // Handle the disconnection and mark the peer accordingly
522
- FullNodePeer . handlePeerDisconnection ( selectedPeerIP ) ;
523
-
524
- // If maximum retries reached, throw the error
525
- if ( retryCount >= MAX_RETRIES ) {
526
- console . error ( `Max retries reached for method ${ String ( prop ) } on peer ${ selectedPeerIP } .` ) ;
527
- throw error ;
528
- }
488
+ if ( ! selectedPeerInfo || ! selectedPeerInfo . isConnected ) {
489
+ return Promise . reject ( new Error ( `Peer ${ selectedPeerIP } is disconnected.` ) ) ;
490
+ }
529
491
530
- // Attempt to select a new peer and retry the method
531
- try {
532
- console . info ( `Selecting a new peer to retry method ${ String ( prop ) } ...` ) ;
533
- const newPeer = await FullNodePeer . getBestPeer ( ) ;
492
+ try {
493
+ // Bind the original method to the peer instance to preserve 'this'
494
+ const boundMethod = originalMethod . bind ( selectedPeerInfo . peer ) ;
495
+ const result = boundMethod ( ...args ) ;
496
+ return result ;
497
+ } catch ( error : any ) {
498
+ console . error ( `Peer ${ selectedPeerIP } encountered an error: ${ error . message } ` ) ;
534
499
535
- // Extract new peer's IP address
536
- const newPeerIP = FullNodePeer . extractPeerIP ( newPeer ) ;
500
+ // Handle disconnection and retries
501
+ FullNodePeer . handlePeerDisconnection ( selectedPeerIP ) ;
537
502
538
- if ( ! newPeerIP ) {
539
- throw new Error ( "Unable to extract IP from the new peer." ) ;
540
- }
503
+ // If maximum retries reached, throw the error
504
+ if ( retryCount >= MAX_RETRIES ) {
505
+ console . error ( `Max retries reached for method ${ String ( prop ) } on peer ${ selectedPeerIP } .` ) ;
506
+ return Promise . reject ( error ) ;
507
+ }
541
508
542
- // Wrap the new peer with a proxy, incrementing the retry count
543
- const proxiedNewPeer = FullNodePeer . createPeerProxy ( newPeer , newPeerIP , retryCount + 1 ) ;
509
+ // Attempt to select a new peer and retry the method
510
+ return FullNodePeer . getBestPeer ( )
511
+ . then ( ( newPeer ) => {
512
+ // Extract new peer's IP address
513
+ const newPeerIP = FullNodePeer . extractPeerIP ( newPeer ) ;
544
514
545
- // Retry the method on the new peer
546
- return await ( proxiedNewPeer as any ) [ prop ] ( ...args ) ;
547
- } catch ( retryError : any ) {
548
- console . error ( `Retry failed on a new peer: ${ retryError . message } ` ) ;
549
- throw retryError ;
515
+ if ( ! newPeerIP ) {
516
+ throw new Error ( "Unable to extract IP from the new peer." ) ;
550
517
}
551
- } else {
552
- // For other errors, handle normally
553
- throw error ;
554
- }
555
- }
556
- } ) ;
518
+
519
+ // Wrap the new peer with a proxy, incrementing the retry count
520
+ const proxiedNewPeer = FullNodePeer . createPeerProxy ( newPeer , newPeerIP , retryCount + 1 ) ;
521
+
522
+ // Retry the method on the new peer
523
+ return ( proxiedNewPeer as any ) [ prop ] ( ...args ) ;
524
+ } )
525
+ . catch ( ( retryError : any ) => {
526
+ console . error ( `Retry failed on a new peer: ${ retryError . message } ` ) ;
527
+ return Promise . reject ( retryError ) ;
528
+ } ) ;
529
+ }
557
530
} ;
558
531
}
559
532
return originalMethod ;
0 commit comments