UNPKG

@configurator/ravendb

Version:
254 lines 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DocumentStore = void 0; const uuid_1 = require("uuid"); const BluebirdPromise = require("bluebird"); const Exceptions_1 = require("../Exceptions"); const RequestExecutor_1 = require("../Http/RequestExecutor"); const LogUtil_1 = require("../Utility/LogUtil"); const DocumentStoreBase_1 = require("./DocumentStoreBase"); const MaintenanceOperationExecutor_1 = require("./Operations/MaintenanceOperationExecutor"); const OperationExecutor_1 = require("./Operations/OperationExecutor"); const DocumentSession_1 = require("./Session/DocumentSession"); const BulkInsertOperation_1 = require("./BulkInsertOperation"); const DatabaseChanges_1 = require("./Changes/DatabaseChanges"); const DatabaseSmuggler_1 = require("./Smuggler/DatabaseSmuggler"); const MultiDatabaseHiLoIdGenerator_1 = require("./Identity/MultiDatabaseHiLoIdGenerator"); const TypeUtil_1 = require("../Utility/TypeUtil"); const log = (0, LogUtil_1.getLogger)({ module: "DocumentStore" }); class DocumentStore extends DocumentStoreBase_1.DocumentStoreBase { constructor(urls, database, authOptions) { super(); this._log = (0, LogUtil_1.getLogger)({ module: "DocumentStore-" + Math.floor(Math.random() * 1000) }); this._databaseChanges = new Map(); this._requestExecutors = new Map(); this._database = database; this.authOptions = authOptions; this.urls = Array.isArray(urls) ? urls : [urls]; } _getDatabaseChangesCacheKey(options) { return options.databaseName.toLowerCase() + "/" + (options.nodeTag || "<null>"); } get identifier() { if (this._identifier) { return this._identifier; } if (!this._urls) { return null; } const urlsString = this._urls.join(", "); if (this._database) { return `${urlsString} DB: ${this._database}`; } return urlsString; } set identifier(identifier) { this._identifier = identifier; } get hiLoIdGenerator() { return this._multiDbHiLo; } dispose() { this._log.info("Dispose."); this.emit("beforeDispose"); this._databaseChanges.forEach(change => change.dispose()); const disposeChain = BluebirdPromise.resolve(); disposeChain .then(() => { if (this._multiDbHiLo) { return Promise.resolve() .then(() => this._multiDbHiLo.returnUnusedRange()) .catch(err => this._log.warn("Error returning unused ID range.", err)); } }) .then(() => { this._disposed = true; this.subscriptions.dispose(); return new BluebirdPromise((resolve, reject) => { let listenersExecCallbacksCount = 0; const listenersCount = this.listenerCount("afterDispose"); if (listenersCount === 0) { resolve(); } else { this.emit("afterDispose", () => { if (listenersCount === ++listenersExecCallbacksCount) { resolve(); } }); } }) .timeout(5000) .catch((err) => this._log.warn(`Error handling 'afterDispose'`, err)); }) .then(() => { this._log.info(`Disposing request executors ${this._requestExecutors.size}`); this._requestExecutors.forEach((executor, db) => { try { executor.dispose(); } catch (err) { this._log.warn(err, `Error disposing request executor.`); } }); }) .finally(() => this.emit("executorsDisposed")); } openSession(databaseOrSessionOptions) { if (!databaseOrSessionOptions) { const sessionOptions = { disableAtomicDocumentWritesInClusterWideTransaction: this.conventions.disableAtomicDocumentWritesInClusterWideTransaction }; return this.openSession(sessionOptions); } this.assertInitialized(); this._ensureNotDisposed(); if (typeof (databaseOrSessionOptions) === "string") { return this.openSession({ database: databaseOrSessionOptions, disableAtomicDocumentWritesInClusterWideTransaction: this.conventions.disableAtomicDocumentWritesInClusterWideTransaction }); } databaseOrSessionOptions = databaseOrSessionOptions || {}; const sessionOpts = databaseOrSessionOptions; const sessionId = (0, uuid_1.v4)(); const session = new DocumentSession_1.DocumentSession(this, sessionId, sessionOpts); this.registerEvents(session); this.emit("sessionCreated", { session }); return session; } getRequestExecutor(database) { this.assertInitialized(); database = this.getEffectiveDatabase(database); const databaseLower = database.toLowerCase(); let executor = this._requestExecutors.get(databaseLower); if (executor) { return executor; } const createRequestExecutor = () => { const requestExecutor = RequestExecutor_1.RequestExecutor.create(this.urls, database, { authOptions: this.authOptions, documentConventions: this.conventions }); this.registerEvents(requestExecutor); return requestExecutor; }; const createRequestExecutorForSingleNode = () => { const forSingleNode = RequestExecutor_1.RequestExecutor.createForSingleNodeWithConfigurationUpdates(this.urls[0], database, { authOptions: this.authOptions, documentConventions: this.conventions }); this.registerEvents(forSingleNode); return forSingleNode; }; if (!this.conventions.disableTopologyUpdates) { executor = createRequestExecutor(); } else { executor = createRequestExecutorForSingleNode(); } this._log.info(`New request executor for database ${database}`); this._requestExecutors.set(databaseLower, executor); return executor; } requestTimeout(timeoutInMs, database) { this.assertInitialized(); database = this.getEffectiveDatabase(database); if (!database) { (0, Exceptions_1.throwError)("InvalidOperationException", "Cannot use requestTimeout without a default database defined " + "unless 'database' parameter is provided. Did you forget to pass 'database' parameter?"); } const requestExecutor = this.getRequestExecutor(database); const oldTimeout = requestExecutor.defaultTimeout; requestExecutor.defaultTimeout = timeoutInMs; return { dispose: () => requestExecutor.defaultTimeout = oldTimeout }; } initialize() { if (this._initialized) { return this; } this._assertValidConfiguration(); RequestExecutor_1.RequestExecutor.validateUrls(this.urls, this.authOptions); try { if (!this.conventions.documentIdGenerator) { const generator = new MultiDatabaseHiLoIdGenerator_1.MultiDatabaseHiLoIdGenerator(this); this._multiDbHiLo = generator; this.conventions.documentIdGenerator = (dbName, entity) => generator.generateDocumentId(dbName, entity); } this.conventions.freeze(); this._initialized = true; } catch (e) { this.dispose(); throw e; } return this; } _assertValidConfiguration() { if (!this._urls || !this._urls.length) { (0, Exceptions_1.throwError)("InvalidArgumentException", "Document store URLs cannot be empty"); } super._assertValidConfiguration(); } changes(database, nodeTag) { this.assertInitialized(); const changesOptions = { databaseName: database || this.database, nodeTag }; const cacheKey = this._getDatabaseChangesCacheKey(changesOptions); if (this._databaseChanges.has(cacheKey)) { return this._databaseChanges.get(cacheKey); } const newChanges = this._createDatabaseChanges(changesOptions); this._databaseChanges.set(cacheKey, newChanges); return newChanges; } _createDatabaseChanges(node) { return new DatabaseChanges_1.DatabaseChanges(this.getRequestExecutor(node.databaseName), node.databaseName, () => this._databaseChanges.delete(this._getDatabaseChangesCacheKey(node)), node.nodeTag); } getLastDatabaseChangesStateException(database, nodeTag) { const node = { databaseName: database || this.database, nodeTag }; const cacheKey = this._getDatabaseChangesCacheKey(node); const databaseChanges = this._databaseChanges.get(cacheKey); if (databaseChanges) { return databaseChanges.lastConnectionStateException; } return null; } get maintenance() { this.assertInitialized(); if (!this._maintenanceOperationExecutor) { this._maintenanceOperationExecutor = new MaintenanceOperationExecutor_1.MaintenanceOperationExecutor(this); } return this._maintenanceOperationExecutor; } get smuggler() { if (!this._smuggler) { this._smuggler = new DatabaseSmuggler_1.DatabaseSmuggler(this); } return this._smuggler; } get operations() { if (!this._operationExecutor) { this._operationExecutor = new OperationExecutor_1.OperationExecutor(this); } return this._operationExecutor; } bulkInsert(databaseOrOptions, optionalOptions) { this.assertInitialized(); const database = TypeUtil_1.TypeUtil.isString(databaseOrOptions) ? this.getEffectiveDatabase(databaseOrOptions) : this.getEffectiveDatabase(null); const options = TypeUtil_1.TypeUtil.isString(databaseOrOptions) ? optionalOptions : databaseOrOptions; return new BulkInsertOperation_1.BulkInsertOperation(database, this, options); } } exports.DocumentStore = DocumentStore; //# sourceMappingURL=DocumentStore.js.map