UNPKG

@azure/cosmos

Version:
194 lines (193 loc) 7.36 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 BaseContinuationTokenManager_exports = {}; __export(BaseContinuationTokenManager_exports, { BaseContinuationTokenManager: () => BaseContinuationTokenManager }); module.exports = __toCommonJS(BaseContinuationTokenManager_exports); var import_CompositeQueryContinuationToken = require("../../documents/ContinuationToken/CompositeQueryContinuationToken.js"); var import_PartitionRangeManager = require("../PartitionRangeManager.js"); class BaseContinuationTokenManager { ranges = []; partitionRangeManager = new import_PartitionRangeManager.PartitionRangeManager(); collectionLink; offset; limit; constructor(collectionLink, initialContinuationToken) { this.collectionLink = collectionLink; if (initialContinuationToken) { const token = (0, import_CompositeQueryContinuationToken.parseBaseContinuationToken)(initialContinuationToken); if (token?.rangeMappings) { this.ranges.push(...token.rangeMappings); } this.offset = token?.offset; this.limit = token?.limit; } } /** * Provides controlled access to partition range manager for subclasses. * This is the only protected access point needed. */ get partitionManager() { return this.partitionRangeManager; } /** * Provides controlled access to ranges for subclasses. * Made protected to allow subclass range management. */ get rangeList() { return this.ranges; } /** * Processes query results and generates continuation tokens for pagination. * Handles response data processing, range management, and token generation. * * @param pageSize - Maximum number of items to return in this page * @param isResponseEmpty - Whether the current response contains no data * @param responseResult - Optional response data containing partition mappings and query-specific data * @returns Object containing the end index for slicing results and optional continuation token for next page */ paginateResults(pageSize, isResponseEmpty, responseResult) { if (responseResult) { this.processResponseResult(responseResult); } this.removeExhaustedRangesFromRanges(); const result = this.processRangesForPagination(pageSize, isResponseEmpty); const tokenString = this.generateContinuationTokenString(); this.trimProcessedData(result.processedRanges, result.endIndex); return { endIndex: result.endIndex, continuationToken: tokenString }; } /** * Generates continuation token string using the appropriate serialization function. * This provides a common implementation that delegates to query-specific logic. */ generateContinuationTokenString() { const token = this.getCurrentContinuationToken(); if (!token) { return void 0; } const serializeFunction = this.getSerializationFunction(); return serializeFunction(token); } /** * Cleans up processed data after a page has been returned. * Handles both common and query-specific cleanup. */ trimProcessedData(processedRanges, endIndex) { processedRanges.forEach((rangeId) => { this.partitionRangeManager.removePartitionRangeMapping(rangeId); }); this.performQuerySpecificDataTrim(processedRanges, endIndex); } addPartitionKeyRangeMap(partitionKeyRangeMap) { this.partitionRangeManager.addPartitionKeyRangeMap(partitionKeyRangeMap); } /** * Processes the entire response result and updates the continuation token manager state. * This encapsulates all response handling logic in one place. */ processResponseResult(responseResult) { if (responseResult.partitionKeyRangeMap) { this.addPartitionKeyRangeMap(responseResult.partitionKeyRangeMap); } if (responseResult.updatedContinuationRanges) { this.handlePartitionRangeChanges(responseResult.updatedContinuationRanges); } this.processQuerySpecificResponse(responseResult); } /** * Compacts the ranges array in place by keeping only items that satisfy the predicate. * This preserves the same array reference while removing unwanted entries. */ compactRangesInPlace(shouldKeep) { let writeIndex = 0; for (let i = 0; i < this.ranges.length; i++) { const mapping = this.ranges[i]; if (!shouldKeep(mapping)) { continue; } this.ranges[writeIndex++] = mapping; } this.ranges.length = writeIndex; } removeExhaustedRangesFromRanges() { if (!this.ranges || !Array.isArray(this.ranges)) { return; } this.compactRangesInPlace( (mapping) => !!mapping && !(0, import_PartitionRangeManager.isPartitionExhausted)(mapping.continuationToken) ); } handlePartitionRangeChanges(updatedContinuationRanges) { if (updatedContinuationRanges && Object.keys(updatedContinuationRanges).length === 0) { return; } Object.entries(updatedContinuationRanges).forEach(([rangeKey, rangeChange]) => { this.processRangeChange(rangeKey, rangeChange); }); } processRangeChange(_rangeKey, rangeChange) { const { oldRange, newRanges, continuationToken } = rangeChange; if (newRanges.length === 1) { this.handleRangeMerge(oldRange, newRanges[0], continuationToken); } else { this.handleRangeSplit(oldRange, newRanges, continuationToken); } } handleRangeMerge(oldRange, newRange, continuationToken) { const existingMappingIndex = this.ranges.findIndex( (mapping) => mapping.queryRange.min === oldRange.min && mapping.queryRange.max === oldRange.max ); if (existingMappingIndex < 0) { return; } const existingMapping = this.ranges[existingMappingIndex]; const updatedQueryRange = { min: newRange.min, max: newRange.max }; existingMapping.queryRange = updatedQueryRange; existingMapping.continuationToken = continuationToken; } handleRangeSplit(oldRange, newRanges, continuationToken) { this.compactRangesInPlace( (mapping) => !(mapping.queryRange.min === oldRange.min && mapping.queryRange.max === oldRange.max) ); newRanges.forEach((newRange) => { this.createNewRangeMapping(newRange, continuationToken); }); } createNewRangeMapping(partitionKeyRange, continuationToken) { const queryRange = { min: partitionKeyRange.min, max: partitionKeyRange.max }; const newRangeWithToken = { queryRange, continuationToken }; this.ranges.push(newRangeWithToken); } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BaseContinuationTokenManager });