@@ -2,7 +2,7 @@ const config = require('config');
2
2
const SteamUser = require ( 'steam-user' ) ;
3
3
const GlobalOffensive = require ( 'globaloffensive' ) ;
4
4
const SteamTotp = require ( 'steam-totp' ) ;
5
- const _ = require ( 'lodash ' ) ;
5
+ const async = require ( 'async ' ) ;
6
6
const logger = require ( './Logger' ) ;
7
7
const Encryption = require ( './Encryption' ) ;
8
8
@@ -73,31 +73,70 @@ accounts.forEach((account) => {
73
73
clients . push ( {
74
74
client,
75
75
csgo,
76
+ busySince : null ,
76
77
} ) ;
77
78
} ) ;
78
79
80
+ setInterval ( ( ) => {
81
+ for ( let i = 0 ; i < clients . length ; i += 1 ) {
82
+ // Mark clients as not busy if they have been busy for more than 10 seconds.
83
+ if ( clients [ i ] . busySince && Date . now ( ) > ( clients [ i ] . busySince + 10000 ) ) {
84
+ clients [ i ] . busySince = null ;
85
+ logger . info ( `Marked client ${ i } as not busy after 10 second timeout` ) ;
86
+ }
87
+ }
88
+ } , 1000 ) ;
89
+
79
90
class Inspector {
80
91
static getClients ( ) {
81
92
return clients ;
82
93
}
83
94
84
95
static inspect ( url , timeoutMs = 3000 ) {
85
96
return new Promise ( ( resolve , reject ) => {
86
- const client = _ . sample ( _ . filter ( clients , ( ( x ) => x . csgo . haveGCSession ) ) ) ;
87
-
88
- if ( _ . isUndefined ( client ) ) {
89
- reject (
90
- new Error ( 'There is currently no client available with an active game coordinator connection' ) ,
91
- ) ;
97
+ // We'll want a timeout of at least 1500 ms.
98
+ if ( timeoutMs < 1500 ) {
99
+ throw new Error ( 'The specified timeout must be at least 1500 ms' ) ;
92
100
}
93
101
94
- client . csgo . inspectItem ( url , ( item ) => {
95
- resolve ( item ) ;
96
- } ) ;
97
-
102
+ // Make sure that the promise is rejected after the timeout.
98
103
setTimeout ( ( ) => {
99
104
reject ( new Error ( `Inspection timed out after ${ timeoutMs } ms` ) ) ;
100
105
} , timeoutMs ) ;
106
+
107
+ // Set the retry interval and the number of retries.
108
+ // We subtract 1000 ms from the `timeoutMs` because we'll need some time
109
+ // for the inspection too.
110
+ const retryInterval = 100 ;
111
+ const retryTimes = Math . round ( ( timeoutMs - 1000 / retryInterval ) ) ;
112
+
113
+ // Find an index of a client that is currently not busy and has a GC connection.
114
+ async
115
+ . retry ( { times : retryTimes , interval : retryInterval } , async ( ) => {
116
+ const index = clients . findIndex (
117
+ ( client ) => client . busySince === null && client . csgo . haveGCSession ,
118
+ ) ;
119
+
120
+ if ( index === - 1 ) {
121
+ throw new Error (
122
+ 'There is currently no client available with an active game coordinator connection' ,
123
+ ) ;
124
+ }
125
+
126
+ return index ;
127
+ } )
128
+ . then ( ( index ) => {
129
+ // Mark the client as busy so that it won't be used for other inspections.
130
+ // If the inspection succeeds, `busySince` will be cleared immediately.
131
+ // If the inspection times out, `busySince` will be cleared after within
132
+ // 1 second after the timeout.
133
+ clients [ index ] . busySince = Date . now ( ) ;
134
+
135
+ clients [ index ] . csgo . inspectItem ( url , ( item ) => {
136
+ clients [ index ] . busySince = null ;
137
+ resolve ( item ) ;
138
+ } ) ;
139
+ } ) ;
101
140
} ) ;
102
141
}
103
142
}
0 commit comments