@geut/permanent-seeder-database
Version:
Permanent Seeder Database
124 lines (110 loc) • 3.3 kB
JavaScript
const assert = require('assert')
const Database = require('./database')
const sub = require('subleveldown')
const AutoIndex = require('level-auto-index')
class MetricsDatabase extends Database {
constructor (params) {
super(params)
// create local indexes
this.metrics = sub(this._db, 'metrics', { valueEncoding: 'json' })
this.idx = {
key: sub(this._db, 'metrics-key'),
timestamp: sub(this._db, 'metrics-timestamp'),
event: sub(this._db, 'metrics-event')
}
this.by = {}
this.by.timestamp = AutoIndex(this.metrics, this.idx.timestamp, (datum = {}) => {
return datum.key + '!' + datum.timestamp
})
this.by.event = AutoIndex(this.metrics, this.idx.event, (datum = {}) => {
return datum.key + '!' + datum.event
})
}
_buildKey (keyParts) {
return ['metrics', ...keyParts].join('!')
}
_cleanKeyData (data = {}) {
assert(Buffer.isBuffer(data.key) || typeof data.key === 'string', 'key should be string or buffer')
const key = typeof data.key === 'string' ? data.key : data.key.toString('hex')
return {
...data,
key
}
}
async onPreSet (key, data) {
const cleanedData = this._cleanKeyData(data)
await this.metrics.put(key, cleanedData)
return cleanedData
}
/**
*
* @param {object} data keyRecord to add
*
* @returns {boolean} true if existent and key was updated
*/
async add (data) {
await this.set(data.key, data.timestamp, data.event, data)
}
/**
*
* @param {object} data keyRecord to update
* @param {boolean} createIfNotExists create keyRecord if not exists
*
* @returns {boolean} true if not existent and key was created
*/
async update (data, createIfNotExists = false) {
const existent = await this.get(data.key, data.timestamp, data.event)
if (!existent && !createIfNotExists) {
throw new Error('Key not created')
}
await this.set(data.key, data.timestamp, data.event, data)
return !existent
}
async filterByTimestamp (key, query) {
assert(key, 'key is required')
return new Promise((resolve, reject) => {
const stream = this.by.timestamp.createValueStream({
gte: key
})
const out = []
stream
.on('data', data => {
if (!query) {
if (data.key.toString('hex') === key) {
out.push(data)
}
} else {
if (data.key.toString('hex') === key && data.timestamp >= query) {
out.push(data)
}
}
})
.on('end', () => resolve(out))
.on('error', reject)
})
}
async filterByEvent (key, query) {
assert(key, 'key is required')
return new Promise((resolve, reject) => {
const stream = this.by.event.createValueStream({
gte: key
})
const out = []
stream
.on('data', data => {
if (!query) {
if (data.key.toString('hex') === key) {
out.push(data)
}
} else {
if (data.key.toString('hex') === key && data.event === query) {
out.push(data)
}
}
})
.on('end', () => resolve(out))
.on('error', reject)
})
}
}
module.exports = MetricsDatabase