@@ -8,7 +8,7 @@ import LRUCache from 'lru-cache'
8
8
import Common from '@ethereumjs/common'
9
9
// note: relative path only valid in .js file in dist
10
10
const { version : pVersion } = require ( '../../package.json' )
11
- import { pk2id , createDeferred , formatLogId } from '../util'
11
+ import { pk2id , createDeferred , formatLogId , buffer2int } from '../util'
12
12
import { Peer , DISCONNECT_REASONS , Capabilities } from './peer'
13
13
import { DPT , PeerInfo } from '../dpt'
14
14
@@ -31,6 +31,7 @@ export interface RLPxOptions {
31
31
export class RLPx extends EventEmitter {
32
32
_privateKey : Buffer
33
33
_id : Buffer
34
+
34
35
_timeout : number
35
36
_maxPeers : number
36
37
_clientId : Buffer
@@ -39,11 +40,14 @@ export class RLPx extends EventEmitter {
39
40
_common : Common
40
41
_listenPort : number | null
41
42
_dpt : DPT | null
43
+
42
44
_peersLRU : LRUCache < string , boolean >
43
45
_peersQueue : { peer : PeerInfo ; ts : number } [ ]
44
46
_server : net . Server | null
45
47
_peers : Map < string , net . Socket | Peer >
48
+
46
49
_refillIntervalId : NodeJS . Timeout
50
+ _refillIntervalSelectionCounter : number = 0
47
51
48
52
constructor ( privateKey : Buffer , options : RLPxOptions ) {
49
53
super ( )
@@ -80,9 +84,11 @@ export class RLPx extends EventEmitter {
80
84
if ( this . _getOpenSlots ( ) > 0 ) return this . _connectToPeer ( peer )
81
85
this . _peersQueue . push ( { peer : peer , ts : 0 } ) // save to queue
82
86
} )
83
- this . _dpt . on ( 'peer:removed' , ( peer : any ) => {
87
+ this . _dpt . on ( 'peer:removed' , ( peer : PeerInfo ) => {
84
88
// remove from queue
85
- this . _peersQueue = this . _peersQueue . filter ( ( item : any ) => ! item . peer . id . equals ( peer . id ) )
89
+ this . _peersQueue = this . _peersQueue . filter (
90
+ ( item ) => ! ( item . peer . id ! as Buffer ) . equals ( peer . id as Buffer )
91
+ )
86
92
} )
87
93
}
88
94
@@ -96,7 +102,9 @@ export class RLPx extends EventEmitter {
96
102
this . _peers = new Map ( )
97
103
this . _peersQueue = [ ]
98
104
this . _peersLRU = new LRUCache ( { max : 25000 } )
99
- this . _refillIntervalId = setInterval ( ( ) => this . _refillConnections ( ) , ms ( '10s' ) )
105
+ const REFILL_INTERVALL = ms ( '10s' )
106
+ const refillIntervalSubdivided = Math . floor ( REFILL_INTERVALL / 10 )
107
+ this . _refillIntervalId = setInterval ( ( ) => this . _refillConnections ( ) , refillIntervalSubdivided )
100
108
}
101
109
102
110
listen ( ...args : any [ ] ) {
@@ -259,17 +267,27 @@ export class RLPx extends EventEmitter {
259
267
_refillConnections ( ) {
260
268
if ( ! this . _isAlive ( ) ) return
261
269
debug (
262
- `refill connections.. queue size: ${ this . _peersQueue . length } , peers: ${
270
+ `refill connections.. (selector ${ this . _refillIntervalSelectionCounter } ) peers: ${
263
271
this . _peers . size
264
- } , open slots: ${ this . _getOpenSlots ( ) } `
272
+ } , queue size: ${ this . _peersQueue . length } , open slots: ${ this . _getOpenSlots ( ) } `
265
273
)
274
+ // Rotating selection counter going in loop from 0..9
275
+ this . _refillIntervalSelectionCounter = ( this . _refillIntervalSelectionCounter + 1 ) % 10
266
276
267
- this . _peersQueue = this . _peersQueue . filter ( ( item : any ) => {
277
+ this . _peersQueue = this . _peersQueue . filter ( ( item ) => {
268
278
if ( this . _getOpenSlots ( ) === 0 ) return true
269
279
if ( item . ts > Date . now ( ) ) return true
270
280
271
- this . _connectToPeer ( item . peer )
272
- return false
281
+ // Randomly distributed selector based on peer ID
282
+ // to decide on subdivided execution
283
+ const selector = buffer2int ( ( item . peer . id ! as Buffer ) . slice ( 0 , 1 ) ) % 10
284
+ if ( selector === this . _refillIntervalSelectionCounter ) {
285
+ this . _connectToPeer ( item . peer )
286
+ return false
287
+ } else {
288
+ // Still keep peer in queue
289
+ return true
290
+ }
273
291
} )
274
292
}
275
293
}
0 commit comments