rounderdb
Version:
A low-I/O, fixed size, round robin db with in-mem support. Store in RAM and sync periodically to disk.
139 lines (106 loc) • 3.44 kB
JavaScript
var RingBuffer = require('./RingBuffer.js');
var debugLog = false;
/* Sample bucket conf
{
capacity: 60, // nr _data points store before aggregation occurs to next bucket
persistence: 'RAM',
aggregationStrategy: 'average'
}
*/
function DataBucket(capacity, strategy) {
this._storage = new RingBuffer((capacity ? capacity : 60));
this._capacity = this._storage.getBufferCapacity();
this._avg = 0.0;
this._sum = 0.0;
this._max = 0.0;
this._min = 0.0;
this._lastAdded = null;
this._aggregationStretegy = (strategy ? strategy : 'average');
};
DataBucket.createInstance = function (bucketConf) {
var b = new DataBucket(bucketConf.capacity,
bucketConf.aggregationStrategy);
log("BUCKET: created bucket:" + JSON.stringify(b, null, 4));
return b;
}
DataBucket.loadInstance = function (dataObj) {
var b = new DataBucket(dataObj._capacity, dataObj._aggregationStretegy);
b._avg = dataObj._avg;
b._sum = dataObj._sum;
b._max = dataObj._max;
b._min = dataObj._min;
b._lastAdded = dataObj._lastAdded;
b._storage = RingBuffer.loadInstance(dataObj._storage);
return b;
}
DataBucket.prototype.getData = function () {
return this._storage.toArray();
};
DataBucket.prototype.lastAdded = function () {
return this._lastAdded;
};
DataBucket.prototype.getAggregationStrategy = function () {
return this._aggregationStretegy;
}
DataBucket.prototype.getBufferCapacity = function () {
return this._capacity;
};
DataBucket.prototype.average = function () {
return this._avg;
};
DataBucket.prototype.sum = function () {
return this._sum;
};
DataBucket.prototype.max = function () {
return this._max;
};
DataBucket.prototype.min = function () {
return this._min;
};
DataBucket.prototype.aggregate = function () {
if (this._aggregationStretegy == 'average')
return this.average();
else if (this._aggregationStretegy == 'sum')
return this.sum();
else if (this._aggregationStretegy == 'max')
return this.max();
else if (this._aggregationStretegy == 'min')
return this.min();
throw Error("Unsupported aggregation strategy: " + this._aggregationStrategy);
}
DataBucket.prototype.add = function (val, timeStamp) {
this._lastAdded = [val, timeStamp];
var oldSum = this._sum;
var oldTail = (!(this._storage.tail()) ? 0 : (this._storage.tail())[0]);
var oldTailIndex = this._storage._tail;
var size = this._storage.push(this._lastAdded);
if (oldTailIndex == this._storage._tail)
oldTail = 0; // edge case when filling up. Adjusted here to simplify calculation below
if (size == 1) {
this._avg = this._max = this._min = this._sum = val;
return size;
}
else {
this._sum = this._sum + val - oldTail;
this._avg = this._sum / size;
var idx = 0;
var swap = this._max;
this._max = this._min;
this._min = swap;
while (idx < this._storage.getCurrentSize()) {
var element = this._storage.getElementAt(idx);
if (element[0] > this._max)
this._max = element[0];
if (element[0] < this._min)
this._min = element[0];
idx++;
}
}
return size;
}
// Internal helpers below
var log = function (msg) {
if (debugLog)
console.log(msg);
};
module.exports = DataBucket;