@@ -52,15 +52,18 @@ function isPrivateIP(ip) {
52
52
) ;
53
53
}
54
54
55
- module . exports = {
55
+ const MAX_QUEUE_SIZE = 500 ;
56
56
57
- _uniqueKeys : new Set ( ) ,
57
+ class GeoIP {
58
58
59
- _store : new Map ( /* <ip>: <result> */ ) ,
59
+ constructor ( ) {
60
+ this . _uniqueKeys = new Set ( ) ;
61
+ this . _store = [ ] ;
62
+ }
60
63
61
64
// lookup ip address to geo location
62
65
async put ( arg , extra = { } ) {
63
- if ( typeof arg !== 'string' ) {
66
+ if ( typeof arg !== 'string' || ! arg ) {
64
67
return ;
65
68
}
66
69
@@ -85,50 +88,45 @@ module.exports = {
85
88
try {
86
89
const geoInfo = await getGeoInfo ( ip ) ;
87
90
const { lat, lon : lng , query } = geoInfo ;
88
- if ( ! this . _store . get ( ip ) ) {
89
- // merge hostname and ip by the same geo location
90
- const item = this . findItemByPosition ( lat , lng ) ;
91
- if ( item ) {
92
- const oldValue = item . value ;
93
- const newValue = {
94
- ...oldValue ,
95
- ips : oldValue . ips . concat ( [ query ] ) ,
96
- } ;
97
- if ( oldValue . hostname && extra . hostname ) {
98
- newValue . hostname = oldValue . hostname . concat ( extra . hostname ) ;
91
+
92
+ // merge hostname and ip by the same geo location
93
+ const item = this . _store . find ( ( v ) => v . lat === lat && v . lng === lng ) ;
94
+ if ( item ) {
95
+ item . ips . push ( query ) ;
96
+ if ( item . ips . length > 20 ) {
97
+ item . ips . shift ( ) ;
98
+ }
99
+ if ( item . hostname && extra . hostname ) {
100
+ item . hostname . push ( extra . hostname ) ;
101
+ if ( item . hostname . length > 20 ) {
102
+ item . hostname . shift ( ) ;
99
103
}
100
- this . _store . set ( item . key , newValue ) ;
101
- } else {
102
- const obj = _ . pick ( geoInfo , [ 'as' , 'city' , 'country' , 'lat' , 'org' , 'regionName' ] ) ;
103
- obj [ 'ips' ] = [ query ] ;
104
- obj [ 'lng' ] = lng ;
105
- this . _store . set ( ip , Object . assign ( { } , obj , extra ) ) ;
106
104
}
107
- return ;
105
+ } else {
106
+ const obj = _ . pick ( geoInfo , [ 'as' , 'city' , 'country' , 'lat' , 'org' , 'regionName' ] ) ;
107
+ obj [ 'ips' ] = [ query ] ;
108
+ obj [ 'lng' ] = lng ;
109
+ this . _store . push ( Object . assign ( { } , obj , extra ) ) ;
110
+ if ( this . _store . length > MAX_QUEUE_SIZE ) {
111
+ this . _store . shift ( ) ;
112
+ }
108
113
}
109
114
} catch ( err ) {
110
115
logger . error ( err . message ) ;
116
+ this . _uniqueKeys . delete ( arg ) ;
111
117
}
112
- this . _uniqueKeys . delete ( arg ) ;
113
- } ,
118
+ }
114
119
115
120
// return all resolved ip and its geo location
116
121
getStore ( ) {
117
122
return this . _store ;
118
- } ,
123
+ }
119
124
120
125
clear ( ) {
121
126
this . _uniqueKeys . clear ( ) ;
122
- this . _store . clear ( ) ;
123
- } ,
127
+ this . _store = [ ] ;
128
+ }
124
129
125
- findItemByPosition ( lat , lng ) {
126
- for ( const [ key , value ] of this . _store ) {
127
- if ( lat === value . lat && lng === value . lng ) {
128
- return { key, value } ;
129
- }
130
- }
131
- return null ;
132
- } ,
130
+ }
133
131
134
- } ;
132
+ module . exports = GeoIP ;
0 commit comments