@azure/cosmos
Version:
Microsoft Azure Cosmos DB Service Node.js SDK for NOSQL API
142 lines (141 loc) • 5.52 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 smartRoutingMapProvider_exports = {};
__export(smartRoutingMapProvider_exports, {
PARITIONKEYRANGE: () => PARITIONKEYRANGE,
SmartRoutingMapProvider: () => SmartRoutingMapProvider
});
module.exports = __toCommonJS(smartRoutingMapProvider_exports);
var import_constants = require("../common/constants.js");
var import_partitionKeyRangeCache = require("./partitionKeyRangeCache.js");
var import_QueryRange = require("./QueryRange.js");
const PARITIONKEYRANGE = import_constants.Constants.PartitionKeyRange;
class SmartRoutingMapProvider {
partitionKeyRangeCache;
constructor(clientContext) {
this.partitionKeyRangeCache = new import_partitionKeyRangeCache.PartitionKeyRangeCache(clientContext);
}
static _secondRangeIsAfterFirstRange(range1, range2) {
if (typeof range1.max === "undefined") {
throw new Error("range1 must have max");
}
if (typeof range2.min === "undefined") {
throw new Error("range2 must have min");
}
if (range1.max > range2.min) {
return false;
} else {
if (range1.max === range2.min && range1.isMaxInclusive && range2.isMinInclusive) {
return false;
}
return true;
}
}
static _isSortedAndNonOverlapping(ranges) {
for (let idx = 1; idx < ranges.length; idx++) {
const previousR = ranges[idx - 1];
const r = ranges[idx];
if (!this._secondRangeIsAfterFirstRange(previousR, r)) {
return false;
}
}
return true;
}
static _stringMax(a, b) {
return a >= b ? a : b;
}
static _stringCompare(a, b) {
return a === b ? 0 : a > b ? 1 : -1;
}
static _subtractRange(r, partitionKeyRange) {
const left = this._stringMax(partitionKeyRange[PARITIONKEYRANGE.MaxExclusive], r.min);
const leftInclusive = this._stringCompare(left, r.min) === 0 ? r.isMinInclusive : false;
return new import_QueryRange.QueryRange(left, r.max, leftInclusive, r.isMaxInclusive);
}
/**
* Given the sorted ranges and a collection, invokes the callback on the list of overlapping partition key ranges
* @param callback - Function execute on the overlapping partition key ranges result,
* takes two parameters error, partition key ranges
* @hidden
*/
async getOverlappingRanges(collectionLink, sortedRanges, diagnosticNode) {
if (!SmartRoutingMapProvider._isSortedAndNonOverlapping(sortedRanges)) {
throw new Error("the list of ranges is not a non-overlapping sorted ranges");
}
let partitionKeyRanges = [];
if (sortedRanges.length === 0) {
return partitionKeyRanges;
}
const collectionRoutingMap = await this.partitionKeyRangeCache.onCollectionRoutingMap(
collectionLink,
diagnosticNode
);
let index = 0;
let currentProvidedRange = sortedRanges[index];
for (; ; ) {
if (currentProvidedRange.isEmpty()) {
if (++index >= sortedRanges.length) {
return partitionKeyRanges;
}
currentProvidedRange = sortedRanges[index];
continue;
}
let queryRange;
if (partitionKeyRanges.length > 0) {
queryRange = SmartRoutingMapProvider._subtractRange(
currentProvidedRange,
partitionKeyRanges[partitionKeyRanges.length - 1]
);
} else {
queryRange = currentProvidedRange;
}
const overlappingRanges = collectionRoutingMap.getOverlappingRanges(queryRange);
if (overlappingRanges.length <= 0) {
throw new Error(`error: returned overlapping ranges for queryRange ${queryRange} is empty`);
}
partitionKeyRanges = partitionKeyRanges.concat(overlappingRanges);
const lastKnownTargetRange = import_QueryRange.QueryRange.parsePartitionKeyRange(
partitionKeyRanges[partitionKeyRanges.length - 1]
);
if (!lastKnownTargetRange) {
throw new Error("expected lastKnowTargetRange to be truthy");
}
if (SmartRoutingMapProvider._stringCompare(currentProvidedRange.max, lastKnownTargetRange.max) > 0) {
throw new Error(`error: returned overlapping ranges ${overlappingRanges} does not contain the requested range ${queryRange}`);
}
if (++index >= sortedRanges.length) {
return partitionKeyRanges;
}
currentProvidedRange = sortedRanges[index];
while (SmartRoutingMapProvider._stringCompare(
currentProvidedRange.max,
lastKnownTargetRange.max
) <= 0) {
if (++index >= sortedRanges.length) {
return partitionKeyRanges;
}
currentProvidedRange = sortedRanges[index];
}
}
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
PARITIONKEYRANGE,
SmartRoutingMapProvider
});