UNPKG

hyperlog-index

Version:
110 lines (98 loc) 2.95 kB
var through = require('through2') var inherits = require('inherits') var EventEmitter = require('events').EventEmitter module.exports = Ix inherits(Ix, EventEmitter) var SEQ = 'seq' function Ix (opts) { if (!(this instanceof Ix)) return new Ix(opts) var self = this EventEmitter.call(self) self.setMaxListeners(Infinity) self._change = -1 self._latest = 0 self._live = false self._pending = 0 self._paused = false self.map = opts.map self.log = opts.log self.db = opts.db self.log.on('preadd', function (node) { self._pending++ }) self.log.on('add', function (node) { self._latest = Math.max(node.change, self._latest) if (--self._pending === 0) self.emit('_ready') }) self.log.on('reject', function (node) { if (--self._pending === 0) self.emit('_ready') }) self.db.get(SEQ, function (err, value) { self.log.ready(function f () { if (self._paused) { return self.once('resume', function () { self.log.ready(f) }) } self._change = Number(value || 0) var r = self.log.createReadStream({ since: value }) r.on('error', function (err) { self.emit('error', err) }) var t = through.obj(write, end) t.on('error', function (err) { self.emit('error', err) }) r.pipe(t) }) }) function write (row, enc, next) { if (self._paused) { return self.once('resume', function () { write(row, enc, next) }) } self._latest = Math.max(row.change, self._latest) self.emit('row', row) self.map(row, function (err) { if (err) return next(err) self.db.put(SEQ, String(row.change), function (err) { if (err) return next(err) self._change = row.change self.emit('change', self._change) next() }) }) } function end () { if (self._paused) return self.once('resume', end) self._live = true self._latest = self._change self.emit('live') self.log.ready(function f () { if (self._paused) { return self.once('resume', function () { self.log.ready(f) }) } var r = self.log.createReadStream({ live: true, since: self._change }) r.pipe(through.obj(write)) r.on('error', function (err) { self.emit('error', err) }) }) } } Ix.prototype.ready = function (fn) { var self = this if (self._paused) { self.once('resume', function () { self.ready(fn) }) } else if (!self._live) { self.once('live', function () { self.ready(fn) }) } else if (self._pending > 0) { self.once('_ready', function () { self.ready(fn) }) } else if (self._latest !== self._change) { self.once('change', function () { self.ready(fn) }) } else process.nextTick(fn) } Ix.prototype.pause = function () { var p = this._paused this._paused = true if (!p) this.emit('pause') } Ix.prototype.resume = function () { var p = this._paused this._paused = false if (p) this.emit('resume') }