UNPKG

dbjs-level

Version:
139 lines (129 loc) 4.52 kB
'use strict'; var assign = require('es5-ext/object/assign') , setPrototypeOf = require('es5-ext/object/set-prototype-of') , d = require('d') , lazy = require('d/lazy') , deferred = require('deferred') , resolve = require('path').resolve , mkdir = require('fs2/mkdir') , rmdir = require('fs2/rmdir') , ReducedStorage = require('dbjs-persistence/reduced-storage') , nextTick = process.nextTick, create = Object.create , getOpts = { fillCache: false }; var LevelReducedStorage = module.exports = function (driver) { if (!(this instanceof LevelReducedStorage)) return new LevelReducedStorage(driver); ReducedStorage.call(this, driver); this.dbPath = resolve(driver.dbPath, '_reduced'); }; setPrototypeOf(LevelReducedStorage, ReducedStorage); LevelReducedStorage.prototype = Object.create(ReducedStorage.prototype, assign({ constructor: d(LevelReducedStorage), // Any data __get: d(function (ns, path) { return this._get_(ns + (path ? ('/' + path) : '')); }), __store: d(function (ns, path, data) { return this._store_(ns + (path ? ('/' + path) : ''), data); }), __getObject: d(function (ns, keyPaths) { return this.reducedDb(function (db) { var def, result; def = deferred(); result = create(null); db.createReadStream({ gte: ns, lte: ns + '/\uffff' }) .on('data', function (data) { var index, path; if (keyPaths) { index = data.key.indexOf('/'); path = (index !== -1) ? data.key.slice(index + 1) : null; if (!keyPaths.has(path)) return; // filtered } index = data.value.indexOf('.'); result[data.key] = { stamp: Number(data.value.slice(0, index)), value: data.value.slice(index + 1) }; }).on('error', def.reject).on('end', function () { def.resolve(result); }); return def.promise; }); }), // Storage import/export __exportAll: d(function (destStorage) { var count = 0; var promise = deferred( this.reducedDb(function (db) { var def, promises = []; def = deferred(); db.createReadStream().on('data', function (record) { var index, ns, path, data; if (!(++count % 1000)) promise.emit('progress'); index = record.value.indexOf('.'); data = { value: record.value.slice(index + 1), stamp: Number(record.value.slice(0, index)) }; index = record.key.indexOf('/'); ns = (index === -1) ? record.key : record.key.slice(0, index); path = (index === -1) ? null : record.key.slice(index + 1); promises.push(destStorage._storeRaw(ns, path, data)); }.bind(this)).on('error', function (err) { def.reject(err); }).on('end', function () { def.resolve(deferred.map(promises)); }); return def.promise; }) )(Function.prototype); return promise; }), __clear: d(function () { return this.__close()(function () { if (this.hasOwnProperty('reducedDb')) { return rmdir(this.dbPath, { recursive: true, force: true, loose: true }); } }.bind(this))(function () { delete this.reducedDb; }.bind(this)); }), __drop: d(function () { return this.__clear(); }), // Connection related __close: d(function () { return deferred(this.hasOwnProperty('reducedDb') && this.reducedDb.invokeAsync('close')); }), // Driver specific _get_: d(function (key) { return this.reducedDb.invokeAsync('get', key, getOpts)(function (value) { var index = value.indexOf('.'); return { stamp: Number(value.slice(0, index)), value: value.slice(index + 1) }; }, function (err) { if (err.notFound) return; throw err; }); }), _store_: d(function (key, data) { return this._reducedDbBatch_(function (batch) { batch.put(key, data.stamp + '.' + data.value); })(this._reducedDbBatchDeferred_.promise); }), _makeDb_: d(function (path) { return mkdir(path, { intermediate: true })(function () { return this.driver.levelConstructor(path, this.driver._dbOptions); }.bind(this)); }) }, lazy({ reducedDb: d(function () { return this._makeDb_(this.dbPath); }), _reducedDbBatchDeferred_: d(function () { return deferred(); }), _reducedDbBatch_: d(function () { return this.reducedDb(function (db) { var batch = db.batch(); nextTick(function () { var def = this._reducedDbBatchDeferred_; delete this._reducedDbBatch_; delete this._reducedDbBatchDeferred_; batch.write(function (err) { if (err) def.reject(err); else def.resolve(); }); }.bind(this)); return batch; }.bind(this)); }) })));