Backend cleanup (#146)
* Add ServerRegistration, begin refactoring to match frontend * move graphData logic into ServerRegistration * move ping updates/history into ServerRegistration * start updating main app entry methods * fix default rates.updateMojangStatus * fix record loading delays on freshly booted instances * move database loading logic to method + callback * use data in frontend for type lookup instead of ping * cleanup app.js * reorganize methods to improve flow * avoid useless mojang updates, remove legacy fields * rename legacy fields for consistency * finish restructure around App model * ensure versions are sorted by release order * filter errors sent to frontend to avoid data leaks * fix version listing behavior on frontend * 5.1.0
This commit is contained in:
134
lib/database.js
134
lib/database.js
@ -1,47 +1,105 @@
|
||||
/**
|
||||
* THIS IS LEGACY, UNMAINTAINED CODE
|
||||
* IT MAY (AND LIKELY DOES) CONTAIN BUGS
|
||||
* USAGE IS NOT RECOMMENDED
|
||||
*/
|
||||
var util = require('./util');
|
||||
const sqlite = require('sqlite3')
|
||||
|
||||
exports.setup = function() {
|
||||
var sqlite = require('sqlite3');
|
||||
class Database {
|
||||
constructor (app) {
|
||||
this._app = app
|
||||
this._sql = new sqlite.Database('database.sql')
|
||||
}
|
||||
|
||||
var db = new sqlite.Database('database.sql');
|
||||
ensureIndexes () {
|
||||
this._sql.serialize(() => {
|
||||
this._sql.run('CREATE TABLE IF NOT EXISTS pings (timestamp BIGINT NOT NULL, ip TINYTEXT, playerCount MEDIUMINT)')
|
||||
this._sql.run('CREATE INDEX IF NOT EXISTS ip_index ON pings (ip, playerCount)')
|
||||
this._sql.run('CREATE INDEX IF NOT EXISTS timestamp_index on PINGS (timestamp)')
|
||||
})
|
||||
}
|
||||
|
||||
db.serialize(function() {
|
||||
db.run('CREATE TABLE IF NOT EXISTS pings (timestamp BIGINT NOT NULL, ip TINYTEXT, playerCount MEDIUMINT)');
|
||||
db.run('CREATE INDEX IF NOT EXISTS ip_index ON pings (ip, playerCount)');
|
||||
db.run('CREATE INDEX IF NOT EXISTS timestamp_index on PINGS (timestamp)');
|
||||
});
|
||||
loadGraphPoints (graphDuration, callback) {
|
||||
// Query recent pings
|
||||
const endTime = new Date().getTime()
|
||||
const startTime = endTime - graphDuration
|
||||
|
||||
exports.log = function(ip, timestamp, playerCount) {
|
||||
var insertStatement = db.prepare('INSERT INTO pings (timestamp, ip, playerCount) VALUES (?, ?, ?)');
|
||||
this.getRecentPings(startTime, endTime, pingData => {
|
||||
const graphPointsByIp = []
|
||||
|
||||
db.serialize(function() {
|
||||
insertStatement.run(timestamp, ip, playerCount);
|
||||
});
|
||||
for (const row of pingData) {
|
||||
// Avoid loading outdated records
|
||||
// This shouldn't happen and is mostly a sanity measure
|
||||
if (startTime - row.timestamp <= graphDuration) {
|
||||
// Load into temporary array
|
||||
// This will be culled prior to being pushed to the serverRegistration
|
||||
let graphPoints = graphPointsByIp[row.ip]
|
||||
if (!graphPoints) {
|
||||
graphPoints = graphPointsByIp[row.ip] = []
|
||||
}
|
||||
|
||||
insertStatement.finalize();
|
||||
};
|
||||
graphPoints.push([row.timestamp, row.playerCount])
|
||||
}
|
||||
}
|
||||
|
||||
exports.getTotalRecord = function(ip, callback) {
|
||||
db.all("SELECT MAX(playerCount), timestamp FROM pings WHERE ip = ?", [
|
||||
ip
|
||||
], function(err, data) {
|
||||
callback(data[0]['MAX(playerCount)'], data[0]['timestamp']);
|
||||
});
|
||||
};
|
||||
Object.keys(graphPointsByIp).forEach(ip => {
|
||||
// Match IPs to serverRegistration object
|
||||
for (const serverRegistration of this._app.serverRegistrations) {
|
||||
if (serverRegistration.data.ip === ip) {
|
||||
const graphPoints = graphPointsByIp[ip]
|
||||
|
||||
exports.queryPings = function(duration, callback) {
|
||||
var currentTime = util.getCurrentTimeMs();
|
||||
// Push the data into the instance and cull if needed
|
||||
serverRegistration.loadGraphPoints(graphPoints)
|
||||
|
||||
db.all("SELECT * FROM pings WHERE timestamp >= ? AND timestamp <= ?", [
|
||||
currentTime - duration,
|
||||
currentTime
|
||||
], function(err, data) {
|
||||
callback(data);
|
||||
});
|
||||
};
|
||||
};
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
callback()
|
||||
})
|
||||
}
|
||||
|
||||
loadRecords (callback) {
|
||||
let completedTasks = 0
|
||||
|
||||
this._app.serverRegistrations.forEach(serverRegistration => {
|
||||
// Find graphPeaks
|
||||
// This pre-computes the values prior to clients connecting
|
||||
serverRegistration.findNewGraphPeak()
|
||||
|
||||
// Query recordData
|
||||
// When complete increment completeTasks to know when complete
|
||||
this.getRecord(serverRegistration.data.ip, (playerCount, timestamp) => {
|
||||
serverRegistration.recordData = {
|
||||
playerCount: playerCount,
|
||||
timestamp: timestamp
|
||||
}
|
||||
|
||||
// Check if completedTasks hit the finish value
|
||||
// Fire callback since #readyDatabase is complete
|
||||
if (++completedTasks === this._app.serverRegistrations.length) {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getRecentPings (startTime, endTime, callback) {
|
||||
this._sql.all('SELECT * FROM pings WHERE timestamp >= ? AND timestamp <= ?', [
|
||||
startTime,
|
||||
endTime
|
||||
], (_, data) => callback(data))
|
||||
}
|
||||
|
||||
getRecord (ip, callback) {
|
||||
this._sql.all('SELECT MAX(playerCount), timestamp FROM pings WHERE ip = ?', [
|
||||
ip
|
||||
], (_, data) => callback(data[0]['MAX(playerCount)'], data[0].timestamp))
|
||||
}
|
||||
|
||||
insertPing (ip, timestamp, playerCount) {
|
||||
const statement = this._sql.prepare('INSERT INTO pings (timestamp, ip, playerCount) VALUES (?, ?, ?)')
|
||||
this._sql.serialize(() => {
|
||||
statement.run(timestamp, ip, playerCount)
|
||||
})
|
||||
statement.finalize()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Database
|
||||
|
Reference in New Issue
Block a user