UNPKG

@nozbe/watermelondb

Version:

Build powerful React Native and React web apps that scale from hundreds to tens of thousands of records and remain fast

167 lines (166 loc) 6.73 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _common = require("../utils/common"); /* eslint-disable no-use-before-define */ var ReaderInterfaceImpl = /*#__PURE__*/function () { function ReaderInterfaceImpl(queue, item) { this.__workQueue = queue; this.__workItem = item; } var _proto = ReaderInterfaceImpl.prototype; _proto.__validateQueue = function () { (0, _common.invariant)(this.__workQueue._queue[0] === this.__workItem, 'Illegal call on a reader/writer that should no longer be running'); }; _proto.callReader = function (reader) { this.__validateQueue(); return this.__workQueue.subAction(reader); }; return ReaderInterfaceImpl; }(); var WriterInterfaceImpl = /*#__PURE__*/function (_ReaderInterfaceImpl) { function WriterInterfaceImpl() { return _ReaderInterfaceImpl.apply(this, arguments) || this; } (0, _inheritsLoose2.default)(WriterInterfaceImpl, _ReaderInterfaceImpl); var _proto2 = WriterInterfaceImpl.prototype; _proto2.callWriter = function (writer) { this.__validateQueue(); return this.__workQueue.subAction(writer); }; _proto2.batch = function (...records) { this.__validateQueue(); return this.__workQueue._db.batch(records); }; return WriterInterfaceImpl; }(ReaderInterfaceImpl); var actionInterface = function (queue, item) { return item.isWriter ? new WriterInterfaceImpl(queue, item) : new ReaderInterfaceImpl(queue, item); }; var WorkQueue = exports.default = /*#__PURE__*/function () { function WorkQueue(db) { this._queue = []; this._subActionIncoming = false; this._db = db; } var _proto3 = WorkQueue.prototype; _proto3.enqueue = function (work, description, isWriter) { var _this = this; // If a subAction was scheduled using subAction(), database.write/read() calls skip the line if (this._subActionIncoming) { this._subActionIncoming = false; var currentWork = this._queue[0]; if (!currentWork.isWriter) { (0, _common.invariant)(!isWriter, 'Cannot call a writer block from a reader block'); } return work(actionInterface(this, currentWork)); } return new Promise(function (resolve, reject) { var workItem = { work: work, isWriter: isWriter, resolve: resolve, reject: reject, description: description }; if ('production' !== process.env.NODE_ENV && _this._queue.length) { setTimeout(function () { var queue = _this._queue; var current = queue[0]; if (current === workItem || !queue.includes(workItem)) { return; } var enqueuedKind = isWriter ? 'writer' : 'reader'; var currentKind = current.isWriter ? 'writer' : 'reader'; _common.logger.warn("The ".concat(enqueuedKind, " you're trying to run (").concat(description || 'unnamed', ") can't be performed yet, because there are ").concat(queue.length, " other readers/writers in the queue.\n\nCurrent ").concat(currentKind, ": ").concat(current.description || 'unnamed', ".\n\nIf everything is working fine, you can safely ignore this message (queueing is working as expected). But if your readers/writers are not running, it's because the current ").concat(currentKind, " is stuck.\nRemember that if you're calling a reader/writer from another reader/writer, you must use callReader()/callWriter(). See docs for more details.")); _common.logger.log("Enqueued ".concat(enqueuedKind, ":"), work); _common.logger.log("Running ".concat(currentKind, ":"), current.work); }, 1500); } _this._queue.push(workItem); if (1 === _this._queue.length) { _this._executeNext(); } }); }; _proto3.subAction = function (work) { try { this._subActionIncoming = true; var promise = work(); (0, _common.invariant)(!this._subActionIncoming, 'callReader/callWriter call must call a reader/writer synchronously'); return promise; } catch (error) { this._subActionIncoming = false; return Promise.reject(error); } }; _proto3._executeNext = function () { return new Promise(function ($return, $error) { var _this2, workItem, work, resolve, reject, isWriter, workPromise; _this2 = this; workItem = this._queue[0]; ({ work: work, resolve: resolve, reject: reject, isWriter: isWriter } = workItem); var $Try_2_Post = function () { try { this._queue.shift(); if (this._queue.length) { setTimeout(function () { return _this2._executeNext(); }, 0); } return $return(); } catch ($boundEx) { return $error($boundEx); } }.bind(this); var $Try_2_Catch = function $Try_2_Catch(error) { try { reject(error); return $Try_2_Post(); } catch ($boundEx) { return $error($boundEx); } }; try { workPromise = work(actionInterface(this, workItem)); if ('production' !== process.env.NODE_ENV) { (0, _common.invariant)(workPromise instanceof Promise, "The function passed to database.".concat(isWriter ? 'write' : 'read', "() or a method marked as @").concat(isWriter ? 'writer' : 'reader', " must be asynchronous (marked as 'async' or always returning a promise) (in: ").concat(workItem.description || 'unnamed', ")")); } return Promise.resolve(workPromise).then(function ($await_3) { try { resolve($await_3); return $Try_2_Post(); } catch ($boundEx) { return $Try_2_Catch($boundEx); } }, $Try_2_Catch); } catch (error) { $Try_2_Catch(error) } }.bind(this)); }; _proto3._abortPendingWork = function () { (0, _common.invariant)(1 <= this._queue.length, '_abortPendingWork can only be called from a reader/writer'); var workToAbort = this._queue.splice(1); // leave only the caller on the queue workToAbort.forEach(function ({ reject: reject }) { reject(new Error('Reader/writer has been aborted because the database was reset')); }); }; return (0, _createClass2.default)(WorkQueue, [{ key: "isWriterRunning", get: function get() { var [item] = this._queue; return Boolean(item && item.isWriter); } }]); }();