UNPKG

rxdb

Version:

A local-first realtime NoSQL Database for JavaScript applications - https://rxdb.info/

134 lines (129 loc) 4.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TRANSACTION_FILE_NAME = exports.TRANSACTION_BLOCKED_FLAG = void 0; exports.commitTransaction = commitTransaction; exports.isTransactionTimedOut = isTransactionTimedOut; exports.runInTransaction = runInTransaction; exports.startTransaction = startTransaction; exports.startTransactionTryOnce = startTransactionTryOnce; var _googleDriveHelper = require("./google-drive-helper.js"); var _rxError = require("../../rx-error.js"); var _index = require("../utils/index.js"); var _upstream = require("./upstream.js"); var TRANSACTION_FILE_NAME = exports.TRANSACTION_FILE_NAME = 'transaction.json'; var TRANSACTION_BLOCKED_FLAG = exports.TRANSACTION_BLOCKED_FLAG = { retry: true }; async function startTransactionTryOnce(googleDriveOptions, init) { var txFileContent = await (0, _googleDriveHelper.readJsonFileContent)(googleDriveOptions, init.transactionFile.fileId); if (!isEmpty(txFileContent.content)) { // tx already existed -> retry return TRANSACTION_BLOCKED_FLAG; } var newTxContent = { createdAtClientTime: (0, _index.now)() }; var writeResult = await (0, _googleDriveHelper.fillFileIfEtagMatches)(googleDriveOptions, init.transactionFile.fileId, txFileContent.etag, newTxContent); if (writeResult.status !== 200) { return TRANSACTION_BLOCKED_FLAG; } return { etag: writeResult.etag }; } async function startTransaction(googleDriveOptions, init) { var current = await startTransactionTryOnce(googleDriveOptions, init); var attempts = 0; while (current.retry) { /** * Wait a bit. * Exponential backoff: 100, 200, 400, 800, ... */ var waitTime = Math.min(100 * 1000, 100 * Math.pow(1.5, attempts)); await (0, _index.promiseWait)(waitTime); /** * Check for timeout */ var timeoutState = await isTransactionTimedOut(googleDriveOptions, init); if (timeoutState.expired) { await (0, _googleDriveHelper.fillFileIfEtagMatches)(googleDriveOptions, init.transactionFile.fileId, timeoutState.etag, undefined); } /** * Try to get the transaction again */ current = await startTransactionTryOnce(googleDriveOptions, init); attempts = attempts + 1; } return current; } async function isTransactionTimedOut(googleDriveOptions, init) { var request = await fetch(googleDriveOptions.apiEndpoint + '/drive/v3/files/' + init.transactionFile.fileId + '?fields=modifiedTime', { headers: { Authorization: 'Bearer ' + googleDriveOptions.authToken } }); var data = await request.json(); var dateHeader = request.headers.get('date'); var serverTime = Date.parse((0, _index.ensureNotFalsy)(dateHeader, 'header time')); var transactionCreation = Date.parse((0, _index.ensureNotFalsy)(data.modifiedTime, 'tx time')); /** * By definition the HTTP Date header * only has seconds precision so if * the serverTime is "impossible", set it * to the transaction creation time. */ if (serverTime < transactionCreation) { serverTime = transactionCreation; } var transactionAge = serverTime - transactionCreation; var timeLeft = googleDriveOptions.transactionTimeout - transactionAge; return { timeLeft, transactionAge, // expired: false expired: timeLeft <= 0, etag: (0, _index.ensureNotFalsy)(data.etag, 'etag') }; } async function commitTransaction(googleDriveOptions, init, transactionInput) { if (transactionInput.retry) { throw (0, _rxError.newRxError)('GDR11', { args: { transaction: transactionInput } }); } var transaction = transactionInput; var writeResult = await (0, _googleDriveHelper.fillFileIfEtagMatches)(googleDriveOptions, init.transactionFile.fileId, transaction.etag, undefined); if (writeResult.status !== 200) { throw (0, _rxError.newRxError)('GDR11', { args: { status: writeResult.status, etag: writeResult.etag } }); } } function isEmpty(value) { if (value === undefined || value === null) return true; if (typeof value === "string") { return value.length === 0; } if (typeof value === "object" && !Array.isArray(value)) { return Object.keys(value).length === 0; } return false; } async function runInTransaction(googleDriveOptions, init, primaryPath, fn, runAfter) { var transaction = await startTransaction(googleDriveOptions, init); await (0, _upstream.processWalFile)(googleDriveOptions, init, primaryPath); var result = await fn(); await commitTransaction(googleDriveOptions, init, transaction); if (runAfter) { await runAfter(); } return result; } //# sourceMappingURL=transaction.js.map