diff --git a/src/pushStats/apiFunctions.js b/src/pushStats/apiFunctions.js index 334190a..33c78bf 100644 --- a/src/pushStats/apiFunctions.js +++ b/src/pushStats/apiFunctions.js @@ -77,16 +77,26 @@ function getRequestOptions(info, path, method = 'GET', body = {}) { 'Content-Length': Buffer.byteLength(JSON.stringify(body)), }; + const slashPos = info.host.indexOf('/'); + let realPath = path; + let realHost = info.host; + if (slashPos !== -1) { + let hostPath = info.host.substring(slashPos + 1); + if (hostPath[hostPath.length - 1] !== '/' && path[0] !== '/') hostPath += '/'; + realPath = hostPath + path; + realHost = info.host.substring(0, slashPos); + } + if (info.username) headers['X-Username'] = info.username; if (info.token) headers['X-Token'] = info.token; return { - host: info.host, + host: realHost, port: info.port, - path, + path: realPath, method, headers, body, - isHTTPS: info.type === 'mmo', + isHTTPS: info.type === 'mmo' || info.type === 'season', }; } @@ -131,7 +141,7 @@ async function req(options) { return Promise.race([executeReq, maxTime]) .then((result) => { if (result === 'Timeout') { - logger.log('info', 'Timeout hit!', new Date(), JSON.stringify(options), reqBody); + logger.log('info', { data: 'Timeout hit!', options }); return undefined; } if (typeof result === 'string' && result.startsWith('Rate limit exceeded')) { diff --git a/src/pushStats/index.js b/src/pushStats/index.js index 6f6c4d9..7fe2d46 100644 --- a/src/pushStats/index.js +++ b/src/pushStats/index.js @@ -65,22 +65,22 @@ class ManageStats { */ async handleUsers(host, hostUsers) { console.log(`[${host}] Handling Users`); + const now = new Date(); + + const beginningOfMinute = now.getSeconds() < 15; + if (host === 'screeps.com' && !beginningOfMinute) { + console.log(`[${host}] not the right time to get stats, skipping`); + return; + } - const beginningOfMinute = new Date().getSeconds() < 15; /** @type {(Promise)[]} */ const getStatsFunctions = []; for (const user of hostUsers) { try { if (user.host !== host) continue; - const rightMinuteForShard = new Date().getMinutes() % user.shards.length === 0; - const shouldContinue = !beginningOfMinute || !rightMinuteForShard; - if (user.type === 'mmo' && shouldContinue) continue; - if (user.type === 'season' && shouldContinue) continue; - - for (const shard of user.shards) { - getStatsFunctions.push(this.getStats(user, shard)); - } + const shard = user.shards[now.getMinutes() % user.shards.length]; + getStatsFunctions.push(this.getStats(user, shard)); } catch (error) { logger.error(error); } @@ -181,6 +181,10 @@ class ManageStats { ? await ApiFunc.getMemory(userinfo, shard) : await ApiFunc.getSegmentMemory(userinfo, shard); + if (!stats) { + logger.error(`Failed to grab memory from ${userinfo.username} in ${shard}`); + return; + } if (Object.keys(stats).length === 0) return; console.log(`Got memory from ${userinfo.username} in ${shard}`); diff --git a/src/pushStats/users.js b/src/pushStats/users.js index ef3b781..1ad2c9c 100644 --- a/src/pushStats/users.js +++ b/src/pushStats/users.js @@ -5,39 +5,52 @@ const SERVER_PORT = parseInt(/** @type {string} */ (process.env.SERVER_PORT), 10 /** * Check whether there's a server nearby - * @returns {Promise<[string, number]>} + * @returns {Promise<[string, number] | undefined>} */ async function checkLocalhostServer() { + console.log('Checking for local server'); const hosts = [ 'localhost', 'host.docker.internal', '172.17.0.1', ]; - /** @type {Promise<[string, number]>[]} */ + /** @type {Promise<[string, number] | undefined>[]} */ const promises = []; for (const host of hosts) { const p = new Promise((resolve, reject) => { const sock = new net.Socket(); - sock.setTimeout(2500); - console.log(`[${host}:${SERVER_PORT}] attempting connection`); + function kill() { + sock.removeAllListeners(); + sock.end(); + sock.destroy(); + sock.unref(); + } + sock.setTimeout(200); sock - .on('connect', () => { - sock.destroy(); + .once('connect', () => { + kill(); resolve([host, SERVER_PORT]); }) - .on('error', () => { - sock.destroy(); - reject(); + .once('error', () => { + kill(); + reject(new Error('Error connecting to server')); }) - .on('timeout', () => { - sock.destroy(); - reject(); + .once('timeout', () => { + kill(); + reject(new Error('Timeout connecting to server')); }) .connect(SERVER_PORT, host); }); promises.push(p); } - return Promise.any(promises); + promises.push(new Promise((resolve) => { setTimeout(() => resolve(undefined), 1000); })); + const server = await Promise.any(promises); + if (server) { + console.log(`Found server at ${server[0]}:${server[1]}`); + } else { + console.log('No server found'); + } + return server; } /** @@ -78,6 +91,9 @@ export default async function loadUsers() { if (!user.host) { try { if (user.type === 'private') { + if (!localServer) { + throw new Error('no local server available, and host unspecified'); + } [user.host, user.port] = localServer; } else { [user.host, user.port] = getHostInfoFromType(user.type); @@ -101,5 +117,6 @@ export default async function loadUsers() { } validUsers.push(user); } + console.log(`Loaded ${validUsers.length} users (out of ${users.length})`); return validUsers; }