mirror of
https://github.com/zoriya/flood.git
synced 2025-12-06 07:16:18 +00:00
Add history collection
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
server/db/users.js
|
||||
server/db/history
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"keymirror": "^0.1.1",
|
||||
"lodash": "^3.10.1",
|
||||
"morgan": "~1.5.1",
|
||||
"nedb": "^1.7.2",
|
||||
"object-assign": "^2.0.0",
|
||||
"passport": "^0.3.2",
|
||||
"passport-http": "^0.3.0",
|
||||
|
||||
141
server/models/HistoryEra.js
Normal file
141
server/models/HistoryEra.js
Normal file
@@ -0,0 +1,141 @@
|
||||
'use strict';
|
||||
|
||||
let Datastore = require('nedb');
|
||||
|
||||
let stringUtil = require('./util/stringUtil');
|
||||
|
||||
const FILE_PATH = './server/db/history/';
|
||||
const MAX_CLEANUP_INTERVAL = 1000 * 60 * 60; // 1 hour
|
||||
const MAX_NEXT_ERA_UPDATE_INTERVAL = 1000 * 60 * 60 * 12; // 12 hours
|
||||
const REQUIRED_FIELDS = ['interval', 'maxTime', 'name'];
|
||||
|
||||
class HistoryEra {
|
||||
constructor(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
this.ready = false;
|
||||
|
||||
if (!this.hasRequiredFields(opts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.data = [];
|
||||
this.opts = opts;
|
||||
this.startedAt = Date.now();
|
||||
|
||||
this.db = this.loadDatabase(this.opts.name);
|
||||
this.removeOutdatedData(this.db);
|
||||
|
||||
let cleanupInterval = this.opts.maxTime;
|
||||
let nextEraUpdateInterval = this.opts.nextEraUpdateInterval;
|
||||
|
||||
if (cleanupInterval === 0 || cleanupInterval > MAX_CLEANUP_INTERVAL) {
|
||||
cleanupInterval = MAX_CLEANUP_INTERVAL;
|
||||
}
|
||||
|
||||
if (nextEraUpdateInterval && nextEraUpdateInterval > MAX_NEXT_ERA_UPDATE_INTERVAL) {
|
||||
nextEraUpdateInterval = MAX_NEXT_ERA_UPDATE_INTERVAL;
|
||||
}
|
||||
|
||||
this.startAutoCleanup(cleanupInterval, this.db);
|
||||
|
||||
if (nextEraUpdateInterval) {
|
||||
this.startNextEraUpdate(nextEraUpdateInterval, this.db);
|
||||
}
|
||||
}
|
||||
|
||||
addData(data) {
|
||||
if (!this.ready) {
|
||||
console.warn('database is not ready');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`insert data in ${this.opts.name}`);
|
||||
|
||||
this.db.insert({
|
||||
ts: Date.now(),
|
||||
up: data.upload,
|
||||
dn: data.download
|
||||
});
|
||||
}
|
||||
|
||||
cleanup(db) {
|
||||
this.removeOutdatedData(db);
|
||||
db.persistence.compactDatafile();
|
||||
}
|
||||
|
||||
hasRequiredFields(opts) {
|
||||
let requirementsMet = true;
|
||||
|
||||
REQUIRED_FIELDS.forEach(function (field) {
|
||||
if (opts[field] == null) {
|
||||
console.warn(`historyEra requires ${field}`);
|
||||
requirementsMet = false;
|
||||
}
|
||||
});
|
||||
|
||||
return requirementsMet;
|
||||
}
|
||||
|
||||
loadDatabase(dbName) {
|
||||
let db = new Datastore({
|
||||
autoload: true,
|
||||
filename: `${FILE_PATH}${dbName}.db`
|
||||
});
|
||||
|
||||
this.ready = true;
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
removeOutdatedData(db) {
|
||||
if (this.opts.maxTime > 0) {
|
||||
let minTimestamp = Date.now() - this.opts.maxTime;
|
||||
db.remove({ts: {$lt: minTimestamp}}, {multi: true}, (err, numRemoved) => {
|
||||
console.log(`removed ${numRemoved} entries from ${this.opts.name}`)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
startAutoCleanup(interval, db) {
|
||||
this.autoCleanupInterval = setInterval(
|
||||
this.cleanup.bind(this, db), interval
|
||||
);
|
||||
}
|
||||
|
||||
startNextEraUpdate(interval, currentDB, nextDB) {
|
||||
this.nextEraUpdateInterval = setInterval(
|
||||
this.updateNextEra.bind(this, currentDB, nextDB), interval
|
||||
);
|
||||
}
|
||||
|
||||
stopAutoCleanup() {
|
||||
clearInterval(this.autoCleanupInterval);
|
||||
this.autoCleanupInterval = null;
|
||||
}
|
||||
|
||||
stopNextEraUpdate(interval, db) {
|
||||
clearInterval(this.nextEraUpdateInterval);
|
||||
this.nextEraUpdateInterval = null;
|
||||
}
|
||||
|
||||
updateNextEra(currentDB, nextDB) {
|
||||
let minTimestamp = Date.now() - this.opts.nextEraUpdateInterval;
|
||||
currentDB.find({ts: {$gte: minTimestamp}}, (err, docs) => {
|
||||
let downTotal = 0;
|
||||
let upTotal = 0;
|
||||
|
||||
docs.forEach(function (doc) {
|
||||
downTotal += parseInt(doc.dn);
|
||||
upTotal += parseInt(doc.up);
|
||||
});
|
||||
|
||||
this.opts.nextEra.addData({
|
||||
download: (downTotal / docs.length).toFixed(1),
|
||||
upload: (upTotal / docs.length).toFixed(1)
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HistoryEra;
|
||||
@@ -241,25 +241,22 @@ var client = {
|
||||
},
|
||||
|
||||
getTransferStats: function(callback) {
|
||||
try {
|
||||
var request = clientUtil.createMulticallRequest(
|
||||
clientUtil.defaults.clientPropertyMethods
|
||||
);
|
||||
var request = clientUtil.createMulticallRequest(
|
||||
clientUtil.defaults.clientPropertyMethods
|
||||
);
|
||||
|
||||
request = [request];
|
||||
request = [request];
|
||||
|
||||
rTorrent.get('system.multicall', request)
|
||||
.then(function(data) {
|
||||
callback(null, clientUtil.mapClientProps(
|
||||
clientUtil.defaults.clientProperties,
|
||||
data
|
||||
));
|
||||
}, function(error) {
|
||||
callback(error, null);
|
||||
});
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
rTorrent.get('system.multicall', request)
|
||||
.then(function(data) {
|
||||
var parsedData = clientUtil.mapClientProps(
|
||||
clientUtil.defaults.clientProperties,
|
||||
data
|
||||
);
|
||||
callback(null, parsedData);
|
||||
}, function(error) {
|
||||
callback(error, null);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
74
server/models/collectHistory.js
Normal file
74
server/models/collectHistory.js
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
var Datastore = require('nedb');
|
||||
|
||||
var client = require('./client');
|
||||
var HistoryEra = require('./HistoryEra');
|
||||
|
||||
let pollInterval = null;
|
||||
|
||||
let yearSnapshot = new HistoryEra({
|
||||
interval: 1000 * 60 * 60 * 24 * 7, // 7 days
|
||||
name: 'yearSnapshot',
|
||||
maxTime: 0 // 365 days
|
||||
});
|
||||
|
||||
let monthSnapshot = new HistoryEra({
|
||||
interval: 1000 * 60 * 60 * 12, // 12 hours
|
||||
maxTime: 1000 * 60 * 60 * 24 * 365, // 365 days
|
||||
name: 'monthSnapshot',
|
||||
nextEraUpdateInterval: 1000 * 60 * 60 * 24 * 7, // 7 days
|
||||
nextEra: yearSnapshot
|
||||
});
|
||||
|
||||
let weekSnapshot = new HistoryEra({
|
||||
interval: 1000 * 60 * 60 * 4, // 4 hours
|
||||
maxTime: 1000 * 60 * 60 * 24 * 7 * 24, // 24 weeks
|
||||
name: 'weekSnapshot',
|
||||
nextEraUpdateInterval: 1000 * 60 * 60 * 12, // 12 hours
|
||||
nextEra: monthSnapshot
|
||||
});
|
||||
|
||||
let daySnapshot = new HistoryEra({
|
||||
interval: 1000 * 60 * 60, // 60 minutes
|
||||
maxTime: 1000 * 60 * 60 * 24 * 30, // 30 days
|
||||
name: 'daySnapshot',
|
||||
nextEraUpdateInterval: 1000 * 60 * 60 * 4, // 4 hours
|
||||
nextEra: weekSnapshot
|
||||
});
|
||||
|
||||
let hourSnapshot = new HistoryEra({
|
||||
interval: 1000 * 60 * 15, // 15 minutes
|
||||
maxTime: 1000 * 60 * 60 * 24, // 24 hours
|
||||
name: 'hourSnapshot',
|
||||
nextEraUpdateInterval: 1000 * 60 * 60, // 60 minutes
|
||||
nextEra: daySnapshot
|
||||
});
|
||||
|
||||
let thirtyMinSnapshot = new HistoryEra({
|
||||
interval: 1000 * 20, // 20 seconds
|
||||
maxTime: 1000 * 60 * 30, // 30 minutes
|
||||
name: 'thirtyMinSnapshot',
|
||||
nextEraUpdateInterval: 1000 * 60 * 15, // 15 minutes
|
||||
nextEra: hourSnapshot
|
||||
});
|
||||
|
||||
let fiveMinSnapshot = new HistoryEra({
|
||||
interval: 1000 * 5, // 5 seconds
|
||||
maxTime: 1000 * 60 * 5, // 5 minutes
|
||||
name: 'fiveMinSnapshot',
|
||||
nextEraUpdateInterval: 1000 * 20, // 20 seconds
|
||||
nextEra: thirtyMinSnapshot
|
||||
});
|
||||
|
||||
pollInterval = setInterval(function() {
|
||||
client.getTransferStats(function (err, data) {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
fiveMinSnapshot.addData({
|
||||
upload: data.uploadRate,
|
||||
download: data.downloadRate
|
||||
});
|
||||
});
|
||||
}, 1000 * 5);
|
||||
9
server/models/util/stringUtil.js
Normal file
9
server/models/util/stringUtil.js
Normal file
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
let stringUtil = {
|
||||
capitalize: function (string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = stringUtil;
|
||||
@@ -5,6 +5,8 @@ var Strategy = require('passport-http').BasicStrategy;
|
||||
|
||||
var users = require('../db/users');
|
||||
|
||||
var collectHistory = require('../models/collectHistory');
|
||||
|
||||
passport.use(new Strategy(
|
||||
function(username, password, callback) {
|
||||
users.findByUsername(username, function(err, user) {
|
||||
|
||||
Reference in New Issue
Block a user