2020-04-21 22:59:53 +00:00
|
|
|
const sqlite = require('sqlite3')
|
|
|
|
|
|
|
|
class Database {
|
|
|
|
constructor (app) {
|
|
|
|
this._app = app
|
|
|
|
this._sql = 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)')
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-05-08 07:06:39 +00:00
|
|
|
loadGraphPoints (graphDuration, callback) {
|
|
|
|
// Query recent pings
|
|
|
|
const endTime = new Date().getTime()
|
|
|
|
const startTime = endTime - graphDuration
|
|
|
|
|
2020-05-08 07:07:59 +00:00
|
|
|
this.getRecentPings(startTime, endTime, pingData => {
|
2020-04-21 22:59:53 +00:00
|
|
|
const graphPointsByIp = []
|
|
|
|
|
|
|
|
for (const row of pingData) {
|
2020-05-08 06:54:04 +00:00
|
|
|
// 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] = []
|
2020-04-21 22:59:53 +00:00
|
|
|
}
|
2020-05-08 06:54:04 +00:00
|
|
|
|
|
|
|
graphPoints.push([row.timestamp, row.playerCount])
|
2020-04-21 22:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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]
|
|
|
|
|
|
|
|
// Push the data into the instance and cull if needed
|
|
|
|
serverRegistration.loadGraphPoints(graphPoints)
|
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-05-08 07:06:39 +00:00
|
|
|
getRecentPings (startTime, endTime, callback) {
|
|
|
|
this._sql.all('SELECT * FROM pings WHERE timestamp >= ? AND timestamp <= ?', [
|
|
|
|
startTime,
|
|
|
|
endTime
|
2020-04-21 22:59:53 +00:00
|
|
|
], (_, 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 (?, ?, ?)')
|
2020-05-08 08:41:19 +00:00
|
|
|
statement.run(timestamp, ip, playerCount)
|
2020-04-21 22:59:53 +00:00
|
|
|
statement.finalize()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = Database
|