mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-06-12 23:47:29 +01:00
add copy of cosmos node.js SDK as local dependency
This commit is contained in:
committed by
Chris Anderson
parent
ff1e733679
commit
ca396cdfbe
+4
@@ -0,0 +1,4 @@
|
||||
import { InMemoryCollectionRoutingMap } from "./inMemoryCollectionRoutingMap";
|
||||
/** @hidden */
|
||||
export declare function createCompleteRoutingMap(partitionKeyRangeInfoTuppleList: any[]): InMemoryCollectionRoutingMap;
|
||||
//# sourceMappingURL=CollectionRoutingMapFactory.d.ts.map
|
||||
+1
@@ -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
|
||||
+1
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"]}
|
||||
+17
@@ -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
|
||||
+1
@@ -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
|
||||
+1
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"]}
|
||||
+24
@@ -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"]}
|
||||
+23
@@ -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
Reference in New Issue
Block a user