UNPKG

mongo-oplog2

Version:
217 lines 15.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Events = exports.MongoOplogStatus = exports.OplogEvents = exports.createInstance = exports.MongoOplog = exports.FilteredMongoOplog = exports.prettify = exports.getTimestamp = exports.getOpName = void 0; const util_1 = require("util"); const mongodb_1 = require("mongodb"); const eventemitter_1 = require("./eventemitter"); const filter_1 = require("./filter"); const stream_1 = require("./stream"); const util_2 = require("./util"); var util_3 = require("./util"); Object.defineProperty(exports, "getOpName", { enumerable: true, get: function () { return util_3.getOpName; } }); Object.defineProperty(exports, "getTimestamp", { enumerable: true, get: function () { return util_3.getTimestamp; } }); Object.defineProperty(exports, "prettify", { enumerable: true, get: function () { return util_3.prettify; } }); var filter_2 = require("./filter"); Object.defineProperty(exports, "FilteredMongoOplog", { enumerable: true, get: function () { return filter_2.FilteredMongoOplog; } }); const debug = util_1.debuglog("mongo-oplog2"); const reErr = /cursor (killed or )?timed out/; /** * Allows tailing the MongoDB oplog. */ class MongoOplogImpl extends eventemitter_1.default { /** * @param uriOrDb a connection string or existing database connection * @param opts options for the `MongoOplog` instance. Any options not * beyond thosed used by `MongoOplog` will be stored and * passed along to the `mongodb` driver when creating a * database connection. */ constructor(uriOrDb, opts = {}) { super(); this.ignore = false; this.pretty = false; this.uri = ""; if (!uriOrDb || typeof uriOrDb === "string") { this.uri = uriOrDb || "mongodb://127.0.0.1/local"; const dbOpts = opts.mongo || {}; if (!('useUnifiedTopology' in dbOpts)) { dbOpts.useUnifiedTopology = true; } this.dbOpts = dbOpts; } this.tailing = false; this.pretty = !!opts.pretty; this.ns = opts.ns || ""; this.collectionName = opts.coll || ""; this._ts = util_2.getTimestamp(opts.since || 0); this._oplogFilter = opts.filter || void 0; } /** * Returns `true` if database is connected; false otherwise. */ get connected() { return !!this._db; } /** * The database connection. */ get db() { return this._db; } /** * The underlying MongoDB cursor stream. */ get stream() { return this._stream; } /** * Last processed timestamp. */ get ts() { return this._ts; } /** * Returns an event emitter that will emit database events for the specified * name space. * @param ns namespace for the filter. */ filter(ns = "") { return new filter_1.FilteredMongoOplog(this, ns); } /** * Stop tailing the oplog, disconnect from the database, and emit the * "destroy" event. */ async destroy() { await this.stop(); await this.disconnect(); this.removeAllListeners(); this.emit("destroy"); return this; } /** * If a timestamp is not provided then returns `true` if either no * document was found or the `ts` value of the document matches the * internally tracked ts; `false` otherwise. * If timestamp is provided returs `true` only if the document returned * matches the specified timestamp. If `null` is returned an Error is * raised. If a document is returned but the `ts` property does not match * the specified `ts` returns `false`. * @param ts optional timestamp to check, if not supplied use internal */ async isCurrent(ts) { const db = await this.connect(); const doc = await stream_1.getLastDoc(db, this.ns, this.collectionName); if (!doc) { if (ts) { throw new Error("ERR_NO_DOC"); } return true; } if (doc.ts.equals(ts || this._ts)) { return true; } return false; } /** * Stop tailing the oplog and destroy the underlying cursor. Tailing * can be resumed by calling the `tail` function. */ async stop() { if (this._stream) { this._stream.destroy(); delete this._stream; } this.tailing = false; debug("streaming stopped"); return this; } /** * Start tailing the oplog. */ async tail() { const onError = async (err) => { await this.stop(); if (reErr.test(err.message)) { debug("cursor timedout - retailing: %j", err); await this.stop(); await this.disconnect(); return this.tail(); } else { debug("oplog error: %j", err); this.emit("error", err); } }; try { if (this.tailing || this._stream) { return this._stream; } this.tailing = true; if (!this._db) { await this.connect(); } this._stream = await stream_1.getStream({ db: this._db, ns: this.ns, ts: this.ts, coll: this.collectionName, filter: this._oplogFilter, }); debug("stream started"); this._stream.on("end", () => { debug("stream ended"); this.emit("end"); this.emit("tail-end"); }); this._stream.on("error", onError); this._stream.on("data", (doc) => { if (this.ignore) { return; } this._ts = doc.ts; const opName = util_2.getOpName(doc.op); const outDoc = this.pretty ? util_2.prettify(doc) : doc; debug("incoming data: %j", doc); debug("outgoing data: %j", outDoc); this.emit("op", outDoc); this.emit(opName, outDoc); }); this.emit("tail-start"); return this._stream; } catch (err) { return onError(err); } } /** * Connect to the database. */ async connect() { if (this._db) { return this._db; } this._client = await mongodb_1.MongoClient.connect(this.uri, this.dbOpts); debug("Connected to oplog database."); this.emit("connect"); this._db = this._client.db('local'); return this._db; } /** * Disconnect from the database by calling `close`. * If database connection is externally supplied do NOT call `close`. */ async disconnect() { if (!this._db) { debug("refusing to disconnect unconnected db."); return; } if (this._client) { await this._client.close(true); } this._db = void 0; this.emit("disconnect"); } } exports.MongoOplog = MongoOplogImpl; function createInstance(uriOrDb, opts = {}) { return new exports.MongoOplog(uriOrDb, opts); } exports.createInstance = createInstance; exports.OplogEvents = Object.freeze(["delete", "insert", "op", "update", "noop"]); exports.MongoOplogStatus = Object.freeze([ "connect", "disconnect", "destroy", "end", "error", "tail-start", "tail-end" ]); exports.Events = Object.freeze([...exports.OplogEvents, ...exports.MongoOplogStatus]); exports.default = createInstance; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0JBQWdDO0FBQ2hDLHFDQUFnRjtBQUVoRixpREFBMEM7QUFDMUMscUNBQThDO0FBQzlDLHFDQUFpRDtBQUNqRCxpQ0FBdUc7QUFDdkcsK0JBQXFGO0FBQTVFLGlHQUFBLFNBQVMsT0FBQTtBQUFFLG9HQUFBLFlBQVksT0FBQTtBQUE0QixnR0FBQSxRQUFRLE9BQUE7QUFDcEUsbUNBQThDO0FBQXJDLDRHQUFBLGtCQUFrQixPQUFBO0FBRTNCLE1BQU0sS0FBSyxHQUFHLGVBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUN2QyxNQUFNLEtBQUssR0FBRywrQkFBK0IsQ0FBQztBQW1COUM7O0dBRUc7QUFDSCxNQUFNLGNBQ1UsU0FBUSxzQkFBOEI7SUFlbEQ7Ozs7OztPQU1HO0lBQ0gsWUFBWSxPQUFnQixFQUFFLE9BQThCLEVBQVM7UUFDakUsS0FBSyxFQUFFLENBQUM7UUFyQlosV0FBTSxHQUFZLEtBQUssQ0FBQztRQUN4QixXQUFNLEdBQVksS0FBSyxDQUFDO1FBSWhCLFFBQUcsR0FBVyxFQUFFLENBQUM7UUFpQnJCLElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO1lBQ3pDLElBQUksQ0FBQyxHQUFHLEdBQUcsT0FBTyxJQUFJLDJCQUEyQixDQUFDO1lBQ2xELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxDQUFDLG9CQUFvQixJQUFJLE1BQU0sQ0FBQyxFQUFFO2dCQUNuQyxNQUFNLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDO2FBQ3BDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7U0FDeEI7UUFDRCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNyQixJQUFJLENBQUMsTUFB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