UNPKG

@azure/cosmos

Version:
227 lines (226 loc) • 9.6 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var defaultQueryExecutionContext_exports = {}; __export(defaultQueryExecutionContext_exports, { DefaultQueryExecutionContext: () => DefaultQueryExecutionContext }); module.exports = __toCommonJS(defaultQueryExecutionContext_exports); var import_logger = require("@azure/logger"); var import_common = require("../common/index.js"); var import_queryMetrics = require("../queryMetrics/index.js"); var import_headerUtils = require("./headerUtils.js"); var import_DiagnosticNodeInternal = require("../diagnostics/DiagnosticNodeInternal.js"); var import_diagnostics = require("../utils/diagnostics.js"); var import_CosmosDbDiagnosticLevel = require("../diagnostics/CosmosDbDiagnosticLevel.js"); const logger = (0, import_logger.createClientLogger)("ClientContext"); var STATES = /* @__PURE__ */ ((STATES2) => { STATES2["start"] = "start"; STATES2["inProgress"] = "inProgress"; STATES2["ended"] = "ended"; return STATES2; })(STATES || {}); class DefaultQueryExecutionContext { static STATES = STATES; resources; // TODO: any resources currentIndex; currentPartitionIndex; fetchFunctions; options; // TODO: any options continuationToken; // TODO: any continuation get continuation() { return this.continuationToken; } state; nextFetchFunction; correlatedActivityId; /** * Provides the basic Query Execution Context. * This wraps the internal logic query execution using provided fetch functions * * @param clientContext - Is used to read the partitionKeyRanges for split proofing * @param query - A SQL query. * @param options - Represents the feed options. * @param fetchFunctions - A function to retrieve each page of data. * An array of functions may be used to query more than one partition. * @hidden */ constructor(options, fetchFunctions, correlatedActivityId) { this.resources = []; this.currentIndex = 0; this.currentPartitionIndex = 0; this.fetchFunctions = Array.isArray(fetchFunctions) ? fetchFunctions : [fetchFunctions]; this.options = options || {}; this.continuationToken = this.options.continuationToken || this.options.continuation || void 0; this.state = DefaultQueryExecutionContext.STATES.start; this.correlatedActivityId = correlatedActivityId; } /** * Execute a provided callback on the next element in the execution context. */ async nextItem(diagnosticNode) { ++this.currentIndex; const response = await this.current(diagnosticNode); return response; } /** * Retrieve the current element on the execution context. */ async current(diagnosticNode) { if (this.currentIndex < this.resources.length) { return { result: this.resources[this.currentIndex], headers: (0, import_headerUtils.getInitialHeader)() }; } if (this._canFetchMore()) { const { result: resources, headers } = await this.fetchMore(diagnosticNode); this.resources = resources; if (this.resources.length === 0) { if (!this.continuationToken && this.currentPartitionIndex >= this.fetchFunctions.length) { this.state = DefaultQueryExecutionContext.STATES.ended; return { result: void 0, headers }; } else { return this.current(diagnosticNode); } } return { result: this.resources[this.currentIndex], headers }; } else { this.state = DefaultQueryExecutionContext.STATES.ended; return { result: void 0, headers: (0, import_headerUtils.getInitialHeader)() }; } } /** * Determine if there are still remaining resources to processs based on * the value of the continuation token or the elements remaining on the current batch in the execution context. * * @returns true if there is other elements to process in the DefaultQueryExecutionContext. */ hasMoreResults() { return this.state === DefaultQueryExecutionContext.STATES.start || this.continuationToken !== void 0 || this.currentIndex < this.resources.length - 1 || this.currentPartitionIndex < this.fetchFunctions.length; } /** * Fetches the next batch of the feed and pass them as an array to a callback */ async fetchMore(diagnosticNode) { return (0, import_diagnostics.addDiagnosticChild)( async (childDiagnosticNode) => { if (this.currentPartitionIndex >= this.fetchFunctions.length) { return { headers: (0, import_headerUtils.getInitialHeader)(), result: void 0 }; } const originalContinuation = this.options.continuationToken || this.options.continuation; this.options.continuationToken = this.continuationToken; if (this.currentPartitionIndex >= this.fetchFunctions.length) { return { headers: (0, import_headerUtils.getInitialHeader)(), result: void 0 }; } let resources; let responseHeaders; try { let p; if (this.nextFetchFunction !== void 0) { logger.verbose("using prefetch"); p = this.nextFetchFunction; this.nextFetchFunction = void 0; } else { logger.verbose("using fresh fetch"); p = this.fetchFunctions[this.currentPartitionIndex]( childDiagnosticNode, this.options, this.correlatedActivityId ); } const response = await p; resources = response.result; childDiagnosticNode.recordQueryResult(resources, import_CosmosDbDiagnosticLevel.CosmosDbDiagnosticLevel.debugUnsafe); responseHeaders = response.headers; this.continuationToken = responseHeaders[import_common.Constants.HttpHeaders.Continuation]; if (!this.continuationToken) { ++this.currentPartitionIndex; } if (this.options && this.options.bufferItems === true) { const fetchFunction = this.fetchFunctions[this.currentPartitionIndex]; this.nextFetchFunction = fetchFunction ? fetchFunction( childDiagnosticNode, { ...this.options, continuationToken: this.continuationToken }, this.correlatedActivityId ) : void 0; } } catch (err) { this.state = DefaultQueryExecutionContext.STATES.ended; throw err; } this.state = DefaultQueryExecutionContext.STATES.inProgress; this.currentIndex = 0; this.options.continuationToken = originalContinuation; this.options.continuation = originalContinuation; if (import_common.Constants.HttpHeaders.QueryMetrics in responseHeaders) { const delimitedString = responseHeaders[import_common.Constants.HttpHeaders.QueryMetrics]; let queryMetrics = import_queryMetrics.QueryMetrics.createFromDelimitedString(delimitedString); if (import_common.Constants.HttpHeaders.RequestCharge in responseHeaders) { const requestCharge = Number(responseHeaders[import_common.Constants.HttpHeaders.RequestCharge]) || 0; queryMetrics = new import_queryMetrics.QueryMetrics( queryMetrics.retrievedDocumentCount, queryMetrics.retrievedDocumentSize, queryMetrics.outputDocumentCount, queryMetrics.outputDocumentSize, queryMetrics.indexHitDocumentCount, queryMetrics.totalQueryExecutionTime, queryMetrics.queryPreparationTimes, queryMetrics.indexLookupTime, queryMetrics.documentLoadTime, queryMetrics.vmExecutionTime, queryMetrics.runtimeExecutionTimes, queryMetrics.documentWriteTime, new import_queryMetrics.ClientSideMetrics(requestCharge) ); } responseHeaders[import_common.Constants.HttpHeaders.QueryMetrics] = {}; responseHeaders[import_common.Constants.HttpHeaders.QueryMetrics]["0"] = queryMetrics; } return { result: resources, headers: responseHeaders }; }, diagnosticNode, import_DiagnosticNodeInternal.DiagnosticNodeType.DEFAULT_QUERY_NODE, { queryMethodIdentifier: "fetchMore" } ); } _canFetchMore() { const res = this.state === DefaultQueryExecutionContext.STATES.start || this.continuationToken && this.state === DefaultQueryExecutionContext.STATES.inProgress || this.currentPartitionIndex < this.fetchFunctions.length && this.state === DefaultQueryExecutionContext.STATES.inProgress; return res; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { DefaultQueryExecutionContext });