add copy of cosmos node.js SDK as local dependency

This commit is contained in:
Theo van Kraay
2024-08-31 16:44:42 +01:00
committed by Chris Anderson
parent ff1e733679
commit ca396cdfbe
1017 changed files with 39434 additions and 19 deletions
@@ -0,0 +1,4 @@
import { InMemoryCollectionRoutingMap } from "./inMemoryCollectionRoutingMap";
/** @hidden */
export declare function createCompleteRoutingMap(partitionKeyRangeInfoTuppleList: any[]): InMemoryCollectionRoutingMap;
//# sourceMappingURL=CollectionRoutingMapFactory.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"CollectionRoutingMapFactory.d.ts","sourceRoot":"","sources":["../../../src/routing/CollectionRoutingMapFactory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAiB9E,cAAc;AACd,wBAAgB,wBAAwB,CACtC,+BAA+B,EAAE,GAAG,EAAE,GACrC,4BAA4B,CAqB9B"}
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Constants } from "../common/constants";
import { InMemoryCollectionRoutingMap } from "./inMemoryCollectionRoutingMap";
/**
* @hidden
*/
function compareRanges(a, b) {
const aVal = a[0][Constants.PartitionKeyRange.MinInclusive];
const bVal = b[0][Constants.PartitionKeyRange.MinInclusive];
if (aVal > bVal) {
return 1;
}
if (aVal < bVal) {
return -1;
}
return 0;
}
/** @hidden */
export function createCompleteRoutingMap(partitionKeyRangeInfoTuppleList) {
const rangeById = {}; // TODO: any
const rangeByInfo = {}; // TODO: any
let sortedRanges = [];
// the for loop doesn't invoke any async callback
for (const r of partitionKeyRangeInfoTuppleList) {
rangeById[r[0][Constants.PartitionKeyRange.Id]] = r;
rangeByInfo[r[1]] = r[0];
sortedRanges.push(r);
}
sortedRanges = sortedRanges.sort(compareRanges);
const partitionKeyOrderedRange = sortedRanges.map((r) => r[0]);
const orderedPartitionInfo = sortedRanges.map((r) => r[1]);
if (!isCompleteSetOfRange(partitionKeyOrderedRange)) {
return undefined;
}
return new InMemoryCollectionRoutingMap(partitionKeyOrderedRange, orderedPartitionInfo);
}
/**
* @hidden
*/
function isCompleteSetOfRange(partitionKeyOrderedRange) {
// TODO: any
let isComplete = false;
if (partitionKeyOrderedRange.length > 0) {
const firstRange = partitionKeyOrderedRange[0];
const lastRange = partitionKeyOrderedRange[partitionKeyOrderedRange.length - 1];
isComplete =
firstRange[Constants.PartitionKeyRange.MinInclusive] ===
Constants.EffectivePartitionKeyConstants.MinimumInclusiveEffectivePartitionKey;
isComplete =
isComplete &&
lastRange[Constants.PartitionKeyRange.MaxExclusive] ===
Constants.EffectivePartitionKeyConstants.MaximumExclusiveEffectivePartitionKey;
for (let i = 1; i < partitionKeyOrderedRange.length; i++) {
const previousRange = partitionKeyOrderedRange[i - 1];
const currentRange = partitionKeyOrderedRange[i];
isComplete =
isComplete &&
previousRange[Constants.PartitionKeyRange.MaxExclusive] ===
currentRange[Constants.PartitionKeyRange.MinInclusive];
if (!isComplete) {
if (previousRange[Constants.PartitionKeyRange.MaxExclusive] >
currentRange[Constants.PartitionKeyRange.MinInclusive]) {
throw Error("Ranges overlap");
}
break;
}
}
}
return isComplete;
}
//# sourceMappingURL=CollectionRoutingMapFactory.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,35 @@
import { PartitionKeyRange } from "../client/Container/PartitionKeyRange";
import { QueryRange as ResponseQueryRange } from "../request/ErrorResponse";
/** @hidden */
export declare class QueryRange {
min: string;
max: string;
isMinInclusive: boolean;
isMaxInclusive: boolean;
/**
* Represents a QueryRange.
*
* @param rangeMin - min
* @param rangeMin - max
* @param isMinInclusive - isMinInclusive
* @param isMaxInclusive - isMaxInclusive
* @hidden
*/
constructor(rangeMin: string, rangeMax: string, isMinInclusive: boolean, isMaxInclusive: boolean);
overlaps(other: QueryRange): boolean;
isFullRange(): boolean;
isEmpty(): boolean;
/**
* Parse a QueryRange from a partitionKeyRange
* @returns QueryRange
* @hidden
*/
static parsePartitionKeyRange(partitionKeyRange: PartitionKeyRange): QueryRange;
/**
* Parse a QueryRange from a dictionary
* @returns QueryRange
* @hidden
*/
static parseFromDict(queryRangeDict: ResponseQueryRange): QueryRange;
}
//# sourceMappingURL=QueryRange.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"QueryRange.d.ts","sourceRoot":"","sources":["../../../src/routing/QueryRange.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE1E,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE5E,cAAc;AACd,qBAAa,UAAU;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IAE/B;;;;;;;;OAQG;gBAED,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,OAAO,EACvB,cAAc,EAAE,OAAO;IAOlB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IAsBpC,WAAW,IAAI,OAAO;IAStB,OAAO,IAAI,OAAO;IAGzB;;;;OAIG;WACW,sBAAsB,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,UAAU;IAQtF;;;;OAIG;WACW,aAAa,CAAC,cAAc,EAAE,kBAAkB,GAAG,UAAU;CAQ5E"}
@@ -0,0 +1,63 @@
import { Constants } from "../common";
/** @hidden */
export class QueryRange {
/**
* Represents a QueryRange.
*
* @param rangeMin - min
* @param rangeMin - max
* @param isMinInclusive - isMinInclusive
* @param isMaxInclusive - isMaxInclusive
* @hidden
*/
constructor(rangeMin, rangeMax, isMinInclusive, isMaxInclusive) {
this.min = rangeMin;
this.max = rangeMax;
this.isMinInclusive = isMinInclusive;
this.isMaxInclusive = isMaxInclusive;
}
overlaps(other) {
const range1 = this; // eslint-disable-line @typescript-eslint/no-this-alias
const range2 = other;
if (range1 === undefined || range2 === undefined) {
return false;
}
if (range1.isEmpty() || range2.isEmpty()) {
return false;
}
if (range1.min <= range2.max || range2.min <= range1.max) {
if ((range1.min === range2.max && !(range1.isMinInclusive && range2.isMaxInclusive)) ||
(range2.min === range1.max && !(range2.isMinInclusive && range1.isMaxInclusive))) {
return false;
}
return true;
}
return false;
}
isFullRange() {
return (this.min === Constants.EffectivePartitionKeyConstants.MinimumInclusiveEffectivePartitionKey &&
this.max === Constants.EffectivePartitionKeyConstants.MaximumExclusiveEffectivePartitionKey &&
this.isMinInclusive === true &&
this.isMaxInclusive === false);
}
isEmpty() {
return !(this.isMinInclusive && this.isMaxInclusive) && this.min === this.max;
}
/**
* Parse a QueryRange from a partitionKeyRange
* @returns QueryRange
* @hidden
*/
static parsePartitionKeyRange(partitionKeyRange) {
return new QueryRange(partitionKeyRange[Constants.PartitionKeyRange.MinInclusive], partitionKeyRange[Constants.PartitionKeyRange.MaxExclusive], true, false);
}
/**
* Parse a QueryRange from a dictionary
* @returns QueryRange
* @hidden
*/
static parseFromDict(queryRangeDict) {
return new QueryRange(queryRangeDict.min, queryRangeDict.max, queryRangeDict.isMinInclusive, queryRangeDict.isMaxInclusive);
}
}
//# sourceMappingURL=QueryRange.js.map
@@ -0,0 +1 @@
{"version":3,"file":"QueryRange.js","sourceRoot":"","sources":["../../../src/routing/QueryRange.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,cAAc;AACd,MAAM,OAAO,UAAU;IAMrB;;;;;;;;OAQG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,cAAuB,EACvB,cAAuB;QAEvB,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC;QACpB,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC;QACpB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IACM,QAAQ,CAAC,KAAiB;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,uDAAuD;QAC5E,MAAM,MAAM,GAAG,KAAK,CAAC;QACrB,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE;YAChD,OAAO,KAAK,CAAC;SACd;QACD,IAAI,MAAM,CAAC,OAAO,EAAE,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE;YACxC,OAAO,KAAK,CAAC;SACd;QAED,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE;YACxD,IACE,CAAC,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,CAAC;gBAChF,CAAC,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,CAAC,EAChF;gBACA,OAAO,KAAK,CAAC;aACd;YACD,OAAO,IAAI,CAAC;SACb;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,WAAW;QAChB,OAAO,CACL,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,8BAA8B,CAAC,qCAAqC;YAC3F,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,8BAA8B,CAAC,qCAAqC;YAC3F,IAAI,CAAC,cAAc,KAAK,IAAI;YAC5B,IAAI,CAAC,cAAc,KAAK,KAAK,CAC9B,CAAC;IACJ,CAAC;IAEM,OAAO;QACZ,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC;IAChF,CAAC;IACD;;;;OAIG;IACI,MAAM,CAAC,sBAAsB,CAAC,iBAAoC;QACvE,OAAO,IAAI,UAAU,CACnB,iBAAiB,CAAC,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAC3D,iBAAiB,CAAC,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAC3D,IAAI,EACJ,KAAK,CACN,CAAC;IACJ,CAAC;IACD;;;;OAIG;IACI,MAAM,CAAC,aAAa,CAAC,cAAkC;QAC5D,OAAO,IAAI,UAAU,CACnB,cAAc,CAAC,GAAG,EAClB,cAAc,CAAC,GAAG,EAClB,cAAc,CAAC,cAAc,EAC7B,cAAc,CAAC,cAAc,CAC9B,CAAC;IACJ,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\nimport { PartitionKeyRange } from \"../client/Container/PartitionKeyRange\";\nimport { Constants } from \"../common\";\nimport { QueryRange as ResponseQueryRange } from \"../request/ErrorResponse\";\n\n/** @hidden */\nexport class QueryRange {\n public min: string;\n public max: string;\n public isMinInclusive: boolean;\n public isMaxInclusive: boolean;\n\n /**\n * Represents a QueryRange.\n *\n * @param rangeMin - min\n * @param rangeMin - max\n * @param isMinInclusive - isMinInclusive\n * @param isMaxInclusive - isMaxInclusive\n * @hidden\n */\n constructor(\n rangeMin: string,\n rangeMax: string,\n isMinInclusive: boolean,\n isMaxInclusive: boolean,\n ) {\n this.min = rangeMin;\n this.max = rangeMax;\n this.isMinInclusive = isMinInclusive;\n this.isMaxInclusive = isMaxInclusive;\n }\n public overlaps(other: QueryRange): boolean {\n const range1 = this; // eslint-disable-line @typescript-eslint/no-this-alias\n const range2 = other;\n if (range1 === undefined || range2 === undefined) {\n return false;\n }\n if (range1.isEmpty() || range2.isEmpty()) {\n return false;\n }\n\n if (range1.min <= range2.max || range2.min <= range1.max) {\n if (\n (range1.min === range2.max && !(range1.isMinInclusive && range2.isMaxInclusive)) ||\n (range2.min === range1.max && !(range2.isMinInclusive && range1.isMaxInclusive))\n ) {\n return false;\n }\n return true;\n }\n return false;\n }\n\n public isFullRange(): boolean {\n return (\n this.min === Constants.EffectivePartitionKeyConstants.MinimumInclusiveEffectivePartitionKey &&\n this.max === Constants.EffectivePartitionKeyConstants.MaximumExclusiveEffectivePartitionKey &&\n this.isMinInclusive === true &&\n this.isMaxInclusive === false\n );\n }\n\n public isEmpty(): boolean {\n return !(this.isMinInclusive && this.isMaxInclusive) && this.min === this.max;\n }\n /**\n * Parse a QueryRange from a partitionKeyRange\n * @returns QueryRange\n * @hidden\n */\n public static parsePartitionKeyRange(partitionKeyRange: PartitionKeyRange): QueryRange {\n return new QueryRange(\n partitionKeyRange[Constants.PartitionKeyRange.MinInclusive],\n partitionKeyRange[Constants.PartitionKeyRange.MaxExclusive],\n true,\n false,\n );\n }\n /**\n * Parse a QueryRange from a dictionary\n * @returns QueryRange\n * @hidden\n */\n public static parseFromDict(queryRangeDict: ResponseQueryRange): QueryRange {\n return new QueryRange(\n queryRangeDict.min,\n queryRangeDict.max,\n queryRangeDict.isMinInclusive,\n queryRangeDict.isMaxInclusive,\n );\n }\n}\n"]}
@@ -0,0 +1,17 @@
import { PartitionKeyRange } from "../client";
import { QueryRange } from "./QueryRange";
/** @hidden */
export declare class InMemoryCollectionRoutingMap {
private orderedPartitionKeyRanges;
private orderedRanges;
orderedPartitionInfo: unknown;
/**
* Represents a InMemoryCollectionRoutingMap Object,
* Stores partition key ranges in an efficient way with some additional information and provides
* convenience methods for working with set of ranges.
*/
constructor(orderedPartitionKeyRanges: PartitionKeyRange[], orderedPartitionInfo: unknown);
getOrderedParitionKeyRanges(): PartitionKeyRange[];
getOverlappingRanges(providedQueryRanges: QueryRange | QueryRange[]): PartitionKeyRange[];
}
//# sourceMappingURL=inMemoryCollectionRoutingMap.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"inMemoryCollectionRoutingMap.d.ts","sourceRoot":"","sources":["../../../src/routing/inMemoryCollectionRoutingMap.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,cAAc;AACd,qBAAa,4BAA4B;IACvC,OAAO,CAAC,yBAAyB,CAAsB;IACvD,OAAO,CAAC,aAAa,CAAe;IAE7B,oBAAoB,EAAE,OAAO,CAAC;IAErC;;;;OAIG;gBACS,yBAAyB,EAAE,iBAAiB,EAAE,EAAE,oBAAoB,EAAE,OAAO;IAYlF,2BAA2B,IAAI,iBAAiB,EAAE;IAIlD,oBAAoB,CAAC,mBAAmB,EAAE,UAAU,GAAG,UAAU,EAAE,GAAG,iBAAiB,EAAE;CA+EjG"}
@@ -0,0 +1,81 @@
import { Constants } from "../common";
import { QueryRange } from "./QueryRange";
/** @hidden */
export class InMemoryCollectionRoutingMap {
/**
* Represents a InMemoryCollectionRoutingMap Object,
* Stores partition key ranges in an efficient way with some additional information and provides
* convenience methods for working with set of ranges.
*/
constructor(orderedPartitionKeyRanges, orderedPartitionInfo) {
this.orderedPartitionKeyRanges = orderedPartitionKeyRanges;
this.orderedRanges = orderedPartitionKeyRanges.map((pkr) => {
return new QueryRange(pkr[Constants.PartitionKeyRange.MinInclusive], pkr[Constants.PartitionKeyRange.MaxExclusive], true, false);
});
this.orderedPartitionInfo = orderedPartitionInfo;
}
getOrderedParitionKeyRanges() {
return this.orderedPartitionKeyRanges;
}
getOverlappingRanges(providedQueryRanges) {
// TODO This code has all kinds of smells. Multiple iterations and sorts just to grab overlapping ranges
// stfaul attempted to bring it down to one for-loop and failed
const pqr = Array.isArray(providedQueryRanges)
? providedQueryRanges
: [providedQueryRanges];
const minToPartitionRange = {}; // TODO: any
// this for loop doesn't invoke any async callback
for (const queryRange of pqr) {
if (queryRange.isEmpty()) {
continue;
}
if (queryRange.isFullRange()) {
return this.orderedPartitionKeyRanges;
}
const minIndex = this.orderedRanges.findIndex((range) => {
if (queryRange.min > range.min && queryRange.min < range.max) {
return true;
}
if (queryRange.min === range.min) {
return true;
}
if (queryRange.min === range.max) {
return true;
}
});
if (minIndex < 0) {
throw new Error("error in collection routing map, queried value is less than the start range.");
}
// Start at the end and work backwards
let maxIndex;
for (let i = this.orderedRanges.length - 1; i >= 0; i--) {
const range = this.orderedRanges[i];
if (queryRange.max > range.min && queryRange.max < range.max) {
maxIndex = i;
break;
}
if (queryRange.max === range.min) {
maxIndex = i;
break;
}
if (queryRange.max === range.max) {
maxIndex = i;
break;
}
}
if (maxIndex > this.orderedRanges.length) {
throw new Error("error in collection routing map, queried value is greater than the end range.");
}
for (let j = minIndex; j < maxIndex + 1; j++) {
if (queryRange.overlaps(this.orderedRanges[j])) {
minToPartitionRange[this.orderedPartitionKeyRanges[j][Constants.PartitionKeyRange.MinInclusive]] = this.orderedPartitionKeyRanges[j];
}
}
}
const overlappingPartitionKeyRanges = Object.keys(minToPartitionRange).map((k) => minToPartitionRange[k]);
return overlappingPartitionKeyRanges.sort((a, b) => {
return a[Constants.PartitionKeyRange.MinInclusive].localeCompare(b[Constants.PartitionKeyRange.MinInclusive]);
});
}
}
//# sourceMappingURL=inMemoryCollectionRoutingMap.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
export * from "./QueryRange";
export * from "./inMemoryCollectionRoutingMap";
export * from "./partitionKeyRangeCache";
export * from "./smartRoutingMapProvider";
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/routing/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
export * from "./QueryRange";
export * from "./inMemoryCollectionRoutingMap";
export * from "./partitionKeyRangeCache";
export * from "./smartRoutingMapProvider";
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/routing/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\nexport * from \"./QueryRange\";\nexport * from \"./inMemoryCollectionRoutingMap\";\nexport * from \"./partitionKeyRangeCache\";\nexport * from \"./smartRoutingMapProvider\";\n"]}
@@ -0,0 +1,24 @@
import { PartitionKeyRange } from "../client/Container/PartitionKeyRange";
import { ClientContext } from "../ClientContext";
import { DiagnosticNodeInternal } from "../diagnostics/DiagnosticNodeInternal";
import { InMemoryCollectionRoutingMap } from "./inMemoryCollectionRoutingMap";
import { QueryRange } from "./QueryRange";
/** @hidden */
export declare class PartitionKeyRangeCache {
private clientContext;
private collectionRoutingMapByCollectionId;
constructor(clientContext: ClientContext);
/**
* Finds or Instantiates the requested Collection Routing Map
* @param collectionLink - Requested collectionLink
* @hidden
*/
onCollectionRoutingMap(collectionLink: string, diagnosticNode: DiagnosticNodeInternal, forceRefresh?: boolean): Promise<InMemoryCollectionRoutingMap>;
/**
* Given the query ranges and a collection, invokes the callback on the list of overlapping partition key ranges
* @hidden
*/
getOverlappingRanges(collectionLink: string, queryRange: QueryRange, diagnosticNode: DiagnosticNodeInternal, forceRefresh?: boolean): Promise<PartitionKeyRange[]>;
private requestCollectionRoutingMap;
}
//# sourceMappingURL=partitionKeyRangeCache.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"partitionKeyRangeCache.d.ts","sourceRoot":"","sources":["../../../src/routing/partitionKeyRangeCache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAG/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,cAAc;AACd,qBAAa,sBAAsB;IAKrB,OAAO,CAAC,aAAa;IAJjC,OAAO,CAAC,kCAAkC,CAExC;gBAEkB,aAAa,EAAE,aAAa;IAGhD;;;;OAIG;IACU,sBAAsB,CACjC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,sBAAsB,EACtC,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,4BAA4B,CAAC;IAWxC;;;OAGG;IACU,oBAAoB,CAC/B,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,sBAAsB,EACtC,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,iBAAiB,EAAE,CAAC;YAKjB,2BAA2B;CAe1C"}
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { MetadataLookUpType } from "../CosmosDiagnostics";
import { getIdFromLink } from "../common/helper";
import { withMetadataDiagnostics } from "../utils/diagnostics";
import { createCompleteRoutingMap } from "./CollectionRoutingMapFactory";
/** @hidden */
export class PartitionKeyRangeCache {
constructor(clientContext) {
this.clientContext = clientContext;
this.collectionRoutingMapByCollectionId = {};
}
/**
* Finds or Instantiates the requested Collection Routing Map
* @param collectionLink - Requested collectionLink
* @hidden
*/
async onCollectionRoutingMap(collectionLink, diagnosticNode, forceRefresh = false) {
const collectionId = getIdFromLink(collectionLink);
if (this.collectionRoutingMapByCollectionId[collectionId] === undefined || forceRefresh) {
this.collectionRoutingMapByCollectionId[collectionId] = this.requestCollectionRoutingMap(collectionLink, diagnosticNode);
}
return this.collectionRoutingMapByCollectionId[collectionId];
}
/**
* Given the query ranges and a collection, invokes the callback on the list of overlapping partition key ranges
* @hidden
*/
async getOverlappingRanges(collectionLink, queryRange, diagnosticNode, forceRefresh = false) {
const crm = await this.onCollectionRoutingMap(collectionLink, diagnosticNode, forceRefresh);
return crm.getOverlappingRanges(queryRange);
}
async requestCollectionRoutingMap(collectionLink, diagnosticNode) {
const { resources } = await withMetadataDiagnostics(async (metadataDiagnostics) => {
return this.clientContext
.queryPartitionKeyRanges(collectionLink)
.fetchAllInternal(metadataDiagnostics);
}, diagnosticNode, MetadataLookUpType.PartitionKeyRangeLookUp);
return createCompleteRoutingMap(resources.map((r) => [r, true]));
}
}
//# sourceMappingURL=partitionKeyRangeCache.js.map
@@ -0,0 +1 @@
{"version":3,"file":"partitionKeyRangeCache.js","sourceRoot":"","sources":["../../../src/routing/partitionKeyRangeCache.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAIzE,cAAc;AACd,MAAM,OAAO,sBAAsB;IAKjC,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAC9C,IAAI,CAAC,kCAAkC,GAAG,EAAE,CAAC;IAC/C,CAAC;IACD;;;;OAIG;IACI,KAAK,CAAC,sBAAsB,CACjC,cAAsB,EACtB,cAAsC,EACtC,eAAwB,KAAK;QAE7B,MAAM,YAAY,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,kCAAkC,CAAC,YAAY,CAAC,KAAK,SAAS,IAAI,YAAY,EAAE;YACvF,IAAI,CAAC,kCAAkC,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,2BAA2B,CACtF,cAAc,EACd,cAAc,CACf,CAAC;SACH;QACD,OAAO,IAAI,CAAC,kCAAkC,CAAC,YAAY,CAAC,CAAC;IAC/D,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,oBAAoB,CAC/B,cAAsB,EACtB,UAAsB,EACtB,cAAsC,EACtC,eAAwB,KAAK;QAE7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,cAAc,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;QAC5F,OAAO,GAAG,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,2BAA2B,CACvC,cAAsB,EACtB,cAAsC;QAEtC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,uBAAuB,CACjD,KAAK,EAAE,mBAA2C,EAAE,EAAE;YACpD,OAAO,IAAI,CAAC,aAAa;iBACtB,uBAAuB,CAAC,cAAc,CAAC;iBACvC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QAC3C,CAAC,EACD,cAAc,EACd,kBAAkB,CAAC,uBAAuB,CAC3C,CAAC;QACF,OAAO,wBAAwB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\nimport { MetadataLookUpType } from \"../CosmosDiagnostics\";\nimport { PartitionKeyRange } from \"../client/Container/PartitionKeyRange\";\nimport { ClientContext } from \"../ClientContext\";\nimport { getIdFromLink } from \"../common/helper\";\nimport { DiagnosticNodeInternal } from \"../diagnostics/DiagnosticNodeInternal\";\nimport { withMetadataDiagnostics } from \"../utils/diagnostics\";\nimport { createCompleteRoutingMap } from \"./CollectionRoutingMapFactory\";\nimport { InMemoryCollectionRoutingMap } from \"./inMemoryCollectionRoutingMap\";\nimport { QueryRange } from \"./QueryRange\";\n\n/** @hidden */\nexport class PartitionKeyRangeCache {\n private collectionRoutingMapByCollectionId: {\n [key: string]: Promise<InMemoryCollectionRoutingMap>;\n };\n\n constructor(private clientContext: ClientContext) {\n this.collectionRoutingMapByCollectionId = {};\n }\n /**\n * Finds or Instantiates the requested Collection Routing Map\n * @param collectionLink - Requested collectionLink\n * @hidden\n */\n public async onCollectionRoutingMap(\n collectionLink: string,\n diagnosticNode: DiagnosticNodeInternal,\n forceRefresh: boolean = false,\n ): Promise<InMemoryCollectionRoutingMap> {\n const collectionId = getIdFromLink(collectionLink);\n if (this.collectionRoutingMapByCollectionId[collectionId] === undefined || forceRefresh) {\n this.collectionRoutingMapByCollectionId[collectionId] = this.requestCollectionRoutingMap(\n collectionLink,\n diagnosticNode,\n );\n }\n return this.collectionRoutingMapByCollectionId[collectionId];\n }\n\n /**\n * Given the query ranges and a collection, invokes the callback on the list of overlapping partition key ranges\n * @hidden\n */\n public async getOverlappingRanges(\n collectionLink: string,\n queryRange: QueryRange,\n diagnosticNode: DiagnosticNodeInternal,\n forceRefresh: boolean = false,\n ): Promise<PartitionKeyRange[]> {\n const crm = await this.onCollectionRoutingMap(collectionLink, diagnosticNode, forceRefresh);\n return crm.getOverlappingRanges(queryRange);\n }\n\n private async requestCollectionRoutingMap(\n collectionLink: string,\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<InMemoryCollectionRoutingMap> {\n const { resources } = await withMetadataDiagnostics(\n async (metadataDiagnostics: DiagnosticNodeInternal) => {\n return this.clientContext\n .queryPartitionKeyRanges(collectionLink)\n .fetchAllInternal(metadataDiagnostics);\n },\n diagnosticNode,\n MetadataLookUpType.PartitionKeyRangeLookUp,\n );\n return createCompleteRoutingMap(resources.map((r) => [r, true]));\n }\n}\n"]}
@@ -0,0 +1,23 @@
import { ClientContext } from "../ClientContext";
import { DiagnosticNodeInternal } from "../diagnostics/DiagnosticNodeInternal";
import { QueryRange } from "./QueryRange";
/** @hidden */
export declare const PARITIONKEYRANGE: import("../common/constants").PartitionKeyRangePropertiesNames;
/** @hidden */
export declare class SmartRoutingMapProvider {
private partitionKeyRangeCache;
constructor(clientContext: ClientContext);
private static _secondRangeIsAfterFirstRange;
private static _isSortedAndNonOverlapping;
private static _stringMax;
private static _stringCompare;
private static _subtractRange;
/**
* 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
*/
getOverlappingRanges(collectionLink: string, sortedRanges: QueryRange[], diagnosticNode: DiagnosticNodeInternal): Promise<any[]>;
}
//# sourceMappingURL=smartRoutingMapProvider.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"smartRoutingMapProvider.d.ts","sourceRoot":"","sources":["../../../src/routing/smartRoutingMapProvider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,cAAc;AACd,eAAO,MAAM,gBAAgB,gEAA8B,CAAC;AAE5D,cAAc;AACd,qBAAa,uBAAuB;IAClC,OAAO,CAAC,sBAAsB,CAAyB;gBAE3C,aAAa,EAAE,aAAa;IAGxC,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAsB5C,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAWzC,OAAO,CAAC,MAAM,CAAC,UAAU;IAIzB,OAAO,CAAC,MAAM,CAAC,cAAc;IAI7B,OAAO,CAAC,MAAM,CAAC,cAAc;IAM7B;;;;;OAKG;IACU,oBAAoB,CAC/B,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,UAAU,EAAE,EAC1B,cAAc,EAAE,sBAAsB,GACrC,OAAO,CAAC,GAAG,EAAE,CAAC;CAiFlB"}
@@ -0,0 +1,116 @@
import { Constants } from "../common/constants";
import { PartitionKeyRangeCache } from "./partitionKeyRangeCache";
import { QueryRange } from "./QueryRange";
/** @hidden */
export const PARITIONKEYRANGE = Constants.PartitionKeyRange;
/** @hidden */
export class SmartRoutingMapProvider {
constructor(clientContext) {
this.partitionKeyRangeCache = new 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) {
// r.min < #previous_r.max
return false;
}
else {
if (range1.max === range2.min && range1.isMaxInclusive && range2.isMinInclusive) {
// the inclusive ending endpoint of previous_r is the same as the inclusive beginning endpoint of r
// they share a point
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 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) {
// validate if the list is non- overlapping and sorted TODO: any PartitionKeyRanges
if (!SmartRoutingMapProvider._isSortedAndNonOverlapping(sortedRanges)) {
throw new Error("the list of ranges is not a non-overlapping sorted ranges");
}
let partitionKeyRanges = []; // TODO: any ParitionKeyRanges
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()) {
// skip and go to the next item
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 = QueryRange.parsePartitionKeyRange(partitionKeyRanges[partitionKeyRanges.length - 1]);
if (!lastKnownTargetRange) {
throw new Error("expected lastKnowTargetRange to be truthy");
}
// the overlapping ranges must contain the requested range
if (SmartRoutingMapProvider._stringCompare(currentProvidedRange.max, lastKnownTargetRange.max) >
0) {
throw new Error(`error: returned overlapping ranges ${overlappingRanges} \
does not contain the requested range ${queryRange}`);
}
// the current range is contained in partitionKeyRanges just move forward
if (++index >= sortedRanges.length) {
return partitionKeyRanges;
}
currentProvidedRange = sortedRanges[index];
while (SmartRoutingMapProvider._stringCompare(currentProvidedRange.max, lastKnownTargetRange.max) <= 0) {
// the current range is covered too.just move forward
if (++index >= sortedRanges.length) {
return partitionKeyRanges;
}
currentProvidedRange = sortedRanges[index];
}
}
}
}
//# sourceMappingURL=smartRoutingMapProvider.js.map
File diff suppressed because one or more lines are too long