@azure/cosmos
Version:
Microsoft Azure Cosmos DB Service Node.js SDK for NOSQL API
227 lines (226 loc) • 9.6 kB
JavaScript
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
});