use ES6 Map if we can (#602)

This commit is contained in:
Jordi Bunster 2021-04-27 08:14:21 -07:00 committed by GitHub
parent 127784abdd
commit 5cf16d01b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 106 additions and 478 deletions

View File

@ -5,7 +5,6 @@ src/Api/Apis.ts
src/AuthType.ts src/AuthType.ts
src/Bindings/BindingHandlersRegisterer.ts src/Bindings/BindingHandlersRegisterer.ts
src/Bindings/ReactBindingHandler.ts src/Bindings/ReactBindingHandler.ts
src/Common/ArrayHashMap.ts
src/Common/Constants.ts src/Common/Constants.ts
src/Common/CosmosClient.test.ts src/Common/CosmosClient.test.ts
src/Common/CosmosClient.ts src/Common/CosmosClient.ts
@ -13,15 +12,12 @@ src/Common/DataAccessUtilityBase.test.ts
src/Common/DataAccessUtilityBase.ts src/Common/DataAccessUtilityBase.ts
src/Common/EditableUtility.ts src/Common/EditableUtility.ts
src/Common/HashMap.test.ts src/Common/HashMap.test.ts
src/Common/HashMap.ts
src/Common/Logger.test.ts src/Common/Logger.test.ts
src/Common/MessageHandler.test.ts src/Common/MessageHandler.test.ts
src/Common/MessageHandler.ts src/Common/MessageHandler.ts
src/Common/MongoProxyClient.test.ts src/Common/MongoProxyClient.test.ts
src/Common/MongoUtility.ts src/Common/MongoUtility.ts
src/Common/NotificationsClientBase.ts src/Common/NotificationsClientBase.ts
src/Common/ObjectCache.test.ts
src/Common/ObjectCache.ts
src/Common/QueriesClient.ts src/Common/QueriesClient.ts
src/Common/Splitter.ts src/Common/Splitter.ts
src/Config.ts src/Config.ts

View File

@ -1,49 +1,9 @@
import { HashMap } from "./HashMap";
/** /**
* Hash map of arrays which allows to: * Hash map of arrays which allows to:
* - push an item by key: add to array and create array if needed * - push an item by key: add to array and create array if needed
* - remove item by key: remove from array and delete array if needed * - remove item by key: remove from array and delete array if needed
*/ */
export class ArrayHashMap<T> extends Map<string, T[]> {
export class ArrayHashMap<T> {
private store: HashMap<T[]>;
constructor() {
this.store = new HashMap();
}
public has(key: string): boolean {
return this.store.has(key);
}
public get(key: string): T[] {
return this.store.get(key);
}
public size(): number {
return this.store.size();
}
public clear(): void {
this.store.clear();
}
public keys(): string[] {
return this.store.keys();
}
public delete(key: string): boolean {
return this.store.delete(key);
}
public forEach(key: string, iteratorFct: (value: T) => void) {
const values = this.store.get(key);
if (values) {
values.forEach((value) => iteratorFct(value));
}
}
/** /**
* Insert item into array. * Insert item into array.
* If no array, create one. * If no array, create one.
@ -52,16 +12,8 @@ export class ArrayHashMap<T> {
* @param item * @param item
*/ */
public push(key: string, item: T): void { public push(key: string, item: T): void {
let itemsArray: T[] = this.store.get(key); const array = this.get(key);
if (!itemsArray) { array ? array.includes(item) || array.push(item) : this.set(key, [item]);
itemsArray = [item];
this.store.set(key, itemsArray);
return;
}
if (itemsArray.indexOf(item) === -1) {
itemsArray.push(item);
}
} }
/** /**
@ -70,18 +22,11 @@ export class ArrayHashMap<T> {
* @param key * @param key
* @param itemToRemove * @param itemToRemove
*/ */
public remove(key: string, itemToRemove: T) { public remove(key: string, itemToRemove: T): void {
if (!this.store.has(key)) { const array = this.get(key);
return; if (array) {
} const remaining = array.filter((item) => item !== itemToRemove);
remaining.length ? this.set(key, remaining) : this.delete(key);
const itemsArray = this.store.get(key);
const index = itemsArray.indexOf(itemToRemove);
if (index >= 0) {
itemsArray.splice(index, 1);
if (itemsArray.length === 0) {
this.store.delete(key);
}
} }
} }
} }

View File

@ -1,70 +0,0 @@
import { HashMap } from "./HashMap";
describe("HashMap", () => {
it("should test if key/val exists", () => {
const map = new HashMap<number>();
map.set("a", 123);
expect(map.has("a")).toBe(true);
expect(map.has("b")).toBe(false);
});
it("should get object back", () => {
const map = new HashMap<string>();
map.set("a", "123");
map.set("a", "456");
expect(map.get("a")).toBe("456");
expect(map.get("a")).not.toBe("123");
});
it("should return the right size", () => {
const map = new HashMap<string>();
map.set("a", "123");
map.set("b", "456");
expect(map.size()).toBe(2);
});
it("should be iterable", () => {
const map = new HashMap<number>();
map.set("a", 1);
map.set("b", 10);
map.set("c", 100);
map.set("d", 1000);
let i = 0;
map.forEach((key: string, value: number) => {
i += value;
});
expect(i).toBe(1111);
});
it("should be deleted", () => {
const map = new HashMap<number>();
map.set("a", 1);
map.set("b", 10);
expect(map.delete("a")).toBe(true);
expect(map.delete("c")).toBe(false);
expect(map.has("a")).toBe(false);
expect(map.has("b")).toBe(true);
});
it("should clear", () => {
const map = new HashMap<number>();
map.set("a", 1);
map.clear();
expect(map.size()).toBe(0);
expect(map.has("a")).toBe(false);
});
it("should return all keys", () => {
const map = new HashMap<number>();
map.set("a", 1);
map.set("b", 1);
expect(map.keys()).toEqual(["a", "b"]);
map.clear();
expect(map.keys().length).toBe(0);
});
});

View File

@ -1,45 +0,0 @@
/**
* Simple hashmap implementation that doesn't rely on ES6 Map nor polyfills
*/
export class HashMap<T> {
constructor(private container: { [key: string]: T } = {}) {}
public has(key: string): boolean {
return this.container.hasOwnProperty(key);
}
public set(key: string, value: T): void {
this.container[key] = value;
}
public get(key: string): T {
return this.container[key];
}
public size(): number {
return Object.keys(this.container).length;
}
public delete(key: string): boolean {
if (this.has(key)) {
delete this.container[key];
return true;
}
return false;
}
public clear(): void {
this.container = {};
}
public keys(): string[] {
return Object.keys(this.container);
}
public forEach(iteratorFct: (key: string, value: T) => void) {
for (const k in this.container) {
iteratorFct(k, this.container[k]);
}
}
}

View File

@ -7,7 +7,7 @@ describe("Object cache", () => {
cache.set("b", 2); cache.set("b", 2);
cache.set("c", 3); cache.set("c", 3);
cache.set("d", 4); cache.set("d", 4);
expect(cache.size()).toBe(2); expect(cache.size).toBe(2);
}); });
it("should remove first added element to keep size at limit", () => { it("should remove first added element to keep size at limit", () => {

View File

@ -1,56 +1,27 @@
import { HashMap } from "./HashMap"; export class ObjectCache<T> extends Map<string, T> {
constructor(private limit: number) {
export class ObjectCache<T> extends HashMap<T> {
private keyQueue: string[]; // Last touched key FIFO to purge cache if too big.
private maxNbElements: number;
public constructor(maxNbElements: number) {
super(); super();
this.keyQueue = [];
this.maxNbElements = maxNbElements;
this.clear();
} }
public clear(): void { public get(key: string): T | undefined {
super.clear(); return this.touch(key);
this.keyQueue = [];
} }
public get(key: string): T { public set(key: string, value: T): this {
this.markKeyAsTouched(key); if (this.size === this.limit) {
return super.get(key); this.delete(this.keys().next().value);
} }
public set(key: string, value: T): void { return this.touch(key, value), this;
}
private touch(key: string, value = super.get(key)) {
// Map keeps (re) insertion order according to ES6 spec
if (value) {
this.delete(key);
super.set(key, value); super.set(key, value);
this.markKeyAsTouched(key);
if (super.size() > this.maxNbElements && key !== this.keyQueue[0]) {
this.reduceCacheSize();
}
} }
/** return value;
* Invalidate elements to keep the total number below the limit
*/
private reduceCacheSize(): void {
// remove a key
const oldKey = this.keyQueue.shift();
if (oldKey) {
super.delete(oldKey);
}
}
/**
* Bubble up this key as new.
* @param key
*/
private markKeyAsTouched(key: string) {
const n = this.keyQueue.indexOf(key);
if (n > -1) {
this.keyQueue.splice(n, 1);
}
this.keyQueue.push(key);
} }
} }

View File

@ -199,9 +199,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -378,9 +376,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -494,21 +490,9 @@ exports[`SettingsComponent renders 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {
@ -731,9 +715,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -910,9 +892,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -1026,21 +1006,9 @@ exports[`SettingsComponent renders 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {
@ -1276,9 +1244,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -1455,9 +1421,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -1571,21 +1535,9 @@ exports[`SettingsComponent renders 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {
@ -1808,9 +1760,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -1987,9 +1937,7 @@ exports[`SettingsComponent renders 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -2103,21 +2051,9 @@ exports[`SettingsComponent renders 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {

View File

@ -11,7 +11,6 @@ import * as ko from "knockout";
import Q from "q"; import Q from "q";
import _ from "underscore"; import _ from "underscore";
import * as Constants from "../../../Common/Constants"; import * as Constants from "../../../Common/Constants";
import { HashMap } from "../../../Common/HashMap";
import { NeighborType } from "../../../Contracts/ViewModels"; import { NeighborType } from "../../../Contracts/ViewModels";
import { logConsoleError } from "../../../Utils/NotificationConsoleUtils"; import { logConsoleError } from "../../../Utils/NotificationConsoleUtils";
import { GraphConfig } from "../../Tabs/GraphTab"; import { GraphConfig } from "../../Tabs/GraphTab";
@ -195,8 +194,8 @@ export class D3ForceGraph implements GraphRenderer {
* Count edges and store in a hashmap: vertex id <--> number of links * Count edges and store in a hashmap: vertex id <--> number of links
* @param linkSelection * @param linkSelection
*/ */
public static countEdges(links: D3Link[]): HashMap<number> { public static countEdges(links: D3Link[]): Map<string, number> {
const countMap = new HashMap<number>(); const countMap = new Map<string, number>();
links.forEach((l: D3Link) => { links.forEach((l: D3Link) => {
let val = countMap.get(l.inV) || 0; let val = countMap.get(l.inV) || 0;
val += 1; val += 1;
@ -407,7 +406,7 @@ export class D3ForceGraph implements GraphRenderer {
const rootId = graph.findRootNodeId(); const rootId = graph.findRootNodeId();
// Remember nodes current position // Remember nodes current position
const posMap = new HashMap<Point2D>(); const posMap = new Map<string, Point2D>();
this.simulation.nodes().forEach((d: D3Node) => { this.simulation.nodes().forEach((d: D3Node) => {
if (d.x == undefined || d.y == undefined) { if (d.x == undefined || d.y == undefined) {
return; return;
@ -501,8 +500,8 @@ export class D3ForceGraph implements GraphRenderer {
if (!nodes || nodes.length === 0) { if (!nodes || nodes.length === 0) {
return; return;
} }
const nodeFinalPositionMap = new HashMap<Point2D>();
const nodeFinalPositionMap = new Map<string, Point2D>();
const viewCenter = this.viewCenter; const viewCenter = this.viewCenter;
const nonFixedNodes = _.filter(nodes, (node: D3Node) => { const nonFixedNodes = _.filter(nodes, (node: D3Node) => {
return !node._isFixedPosition && node.x === viewCenter.x && node.y === viewCenter.y; return !node._isFixedPosition && node.x === viewCenter.x && node.y === viewCenter.y;
@ -559,7 +558,7 @@ export class D3ForceGraph implements GraphRenderer {
newNodes.selectAll(".loadmore").attr("visibility", "hidden").transition().delay(600).attr("visibility", "visible"); newNodes.selectAll(".loadmore").attr("visibility", "hidden").transition().delay(600).attr("visibility", "visible");
} }
private restartSimulation(graph: GraphData<D3Node, D3Link>, posMap: HashMap<Point2D>) { private restartSimulation(graph: GraphData<D3Node, D3Link>, posMap: Map<string, Point2D>) {
if (!graph) { if (!graph) {
return; return;
} }

View File

@ -1,5 +1,5 @@
import { ObjectCache } from "../../../Common/ObjectCache"; import { ObjectCache } from "../../../Common/ObjectCache";
import { GremlinVertex, GraphData } from "./GraphData"; import { GraphData, GremlinVertex } from "./GraphData";
/** /**
* Remember vertex edge information * Remember vertex edge information
@ -10,9 +10,8 @@ export class EdgeInfoCache extends ObjectCache<GremlinVertex> {
* @param vertex * @param vertex
*/ */
public addVertex(vertex: GremlinVertex): void { public addVertex(vertex: GremlinVertex): void {
let v: GremlinVertex; let v = super.get(vertex.id);
if (super.has(vertex.id)) { if (super.has(vertex.id) && v) {
v = super.get(vertex.id);
GraphData.addEdgeInfoToVertex(v, vertex); GraphData.addEdgeInfoToVertex(v, vertex);
v._outEdgeIds = vertex._outEdgeIds; v._outEdgeIds = vertex._outEdgeIds;
v._inEdgeIds = vertex._inEdgeIds; v._inEdgeIds = vertex._inEdgeIds;
@ -29,8 +28,8 @@ export class EdgeInfoCache extends ObjectCache<GremlinVertex> {
* @param id * @param id
*/ */
public mergeEdgeInfo(target: GremlinVertex): void { public mergeEdgeInfo(target: GremlinVertex): void {
if (super.has(target.id)) {
const cachedVertex = super.get(target.id); const cachedVertex = super.get(target.id);
if (super.has(target.id) && cachedVertex) {
GraphData.addEdgeInfoToVertex(target, cachedVertex); GraphData.addEdgeInfoToVertex(target, cachedVertex);
target._outEdgeIds = cachedVertex._outEdgeIds; target._outEdgeIds = cachedVertex._outEdgeIds;
target._inEdgeIds = cachedVertex._inEdgeIds; target._inEdgeIds = cachedVertex._inEdgeIds;

View File

@ -1,7 +1,7 @@
import * as sinon from "sinon"; import * as sinon from "sinon";
import { GremlinClient, GremlinClientParameters } from "./GremlinClient";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import * as Logger from "../../../Common/Logger"; import * as Logger from "../../../Common/Logger";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import { GremlinClient, GremlinClientParameters } from "./GremlinClient";
describe("Gremlin Client", () => { describe("Gremlin Client", () => {
const emptyParams: GremlinClientParameters = { const emptyParams: GremlinClientParameters = {
@ -70,7 +70,7 @@ describe("Gremlin Client", () => {
gremlinClient.execute("fake query"); gremlinClient.execute("fake query");
gremlinClient.execute("fake query"); gremlinClient.execute("fake query");
gremlinClient.execute("fake query"); gremlinClient.execute("fake query");
expect(gremlinClient.pendingResults.size()).toBe(3); expect(gremlinClient.pendingResults.size).toBe(3);
}); });
it("should clean up pending request ids after success", async () => { it("should clean up pending request ids after success", async () => {
@ -89,7 +89,7 @@ describe("Gremlin Client", () => {
return requestId; return requestId;
}); });
await gremlinClient.execute("fake query"); await gremlinClient.execute("fake query");
expect(gremlinClient.pendingResults.size()).toBe(0); expect(gremlinClient.pendingResults.size).toBe(0);
}); });
it("should log and display error out on unknown requestId", () => { it("should log and display error out on unknown requestId", () => {
@ -247,7 +247,7 @@ describe("Gremlin Client", () => {
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => requestId); sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => requestId);
gremlinClient.execute("fake query").finally(() => { gremlinClient.execute("fake query").finally(() => {
try { try {
expect(gremlinClient.pendingResults.size()).toBe(0); expect(gremlinClient.pendingResults.size).toBe(0);
done(); done();
} catch (e) { } catch (e) {
done(e); done(e);

View File

@ -4,7 +4,6 @@
import * as Q from "q"; import * as Q from "q";
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils"; import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils";
import { HashMap } from "../../../Common/HashMap";
import { logConsoleInfo } from "../../../Utils/NotificationConsoleUtils"; import { logConsoleInfo } from "../../../Utils/NotificationConsoleUtils";
import { GremlinSimpleClient, Result } from "./GremlinSimpleClient"; import { GremlinSimpleClient, Result } from "./GremlinSimpleClient";
@ -30,7 +29,7 @@ interface PendingResultData {
export class GremlinClient { export class GremlinClient {
public client: GremlinSimpleClient; public client: GremlinSimpleClient;
public pendingResults: HashMap<PendingResultData>; // public for testing purposes public pendingResults: Map<string, PendingResultData>; // public for testing purposes
private maxResultSize: number; private maxResultSize: number;
private static readonly PENDING_REQUEST_TIMEOUT_MS = 6 /* minutes */ * 60 /* seconds */ * 1000 /* ms */; private static readonly PENDING_REQUEST_TIMEOUT_MS = 6 /* minutes */ * 60 /* seconds */ * 1000 /* ms */;
private static readonly TIMEOUT_ERROR_MSG = `Pending request timed out (${GremlinClient.PENDING_REQUEST_TIMEOUT_MS} ms)`; private static readonly TIMEOUT_ERROR_MSG = `Pending request timed out (${GremlinClient.PENDING_REQUEST_TIMEOUT_MS} ms)`;
@ -38,7 +37,7 @@ export class GremlinClient {
public initialize(params: GremlinClientParameters) { public initialize(params: GremlinClientParameters) {
this.destroy(); this.destroy();
this.pendingResults = new HashMap(); this.pendingResults = new Map();
this.maxResultSize = params.maxResultSize; this.maxResultSize = params.maxResultSize;
this.client = new GremlinSimpleClient({ this.client = new GremlinSimpleClient({
@ -68,9 +67,9 @@ export class GremlinClient {
// Fail all pending requests if no request id (fatal) // Fail all pending requests if no request id (fatal)
if (!requestId) { if (!requestId) {
this.pendingResults.keys().forEach((reqId: string) => { for (const reqId of this.pendingResults.keys()) {
this.abortPendingRequest(reqId, errorMessage, null); this.abortPendingRequest(reqId, errorMessage, null);
}); }
} }
} else { } else {
this.abortPendingRequest(requestId, errorMessage, result.requestCharge); this.abortPendingRequest(requestId, errorMessage, result.requestCharge);

View File

@ -2,7 +2,6 @@ import * as ko from "knockout";
import * as _ from "underscore"; import * as _ from "underscore";
import * as Constants from "../../Common/Constants"; import * as Constants from "../../Common/Constants";
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import { HashMap } from "../../Common/HashMap";
import { configContext, Platform } from "../../ConfigContext"; import { configContext, Platform } from "../../ConfigContext";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
@ -51,7 +50,7 @@ export default class CassandraAddCollectionPane extends ContextualPaneBase {
public ruToolTipText: ko.Computed<string>; public ruToolTipText: ko.Computed<string>;
public canConfigureThroughput: ko.PureComputed<boolean>; public canConfigureThroughput: ko.PureComputed<boolean>;
private keyspaceOffers: HashMap<DataModels.Offer>; private keyspaceOffers: Map<string, DataModels.Offer>;
constructor(options: ViewModels.PaneOptions) { constructor(options: ViewModels.PaneOptions) {
super(options); super(options);
@ -60,7 +59,7 @@ export default class CassandraAddCollectionPane extends ContextualPaneBase {
this.keyspaceCreateNew = ko.observable<boolean>(true); this.keyspaceCreateNew = ko.observable<boolean>(true);
this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText()); this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText());
this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled()); this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled());
this.keyspaceOffers = new HashMap<DataModels.Offer>(); this.keyspaceOffers = new Map();
this.keyspaceIds = ko.observableArray<string>(); this.keyspaceIds = ko.observableArray<string>();
this.keyspaceHasSharedOffer = ko.observable<boolean>(false); this.keyspaceHasSharedOffer = ko.observable<boolean>(false);
this.keyspaceThroughput = ko.observable<number>(); this.keyspaceThroughput = ko.observable<number>();

View File

@ -175,9 +175,7 @@ exports[`Settings Pane should render Default properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -354,9 +352,7 @@ exports[`Settings Pane should render Default properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -470,21 +466,9 @@ exports[`Settings Pane should render Default properly 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {
@ -830,9 +814,7 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -1009,9 +991,7 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -1125,21 +1105,9 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {

View File

@ -178,9 +178,7 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -357,9 +355,7 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -473,21 +469,9 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {
@ -709,9 +693,7 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -888,9 +870,7 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -1004,21 +984,9 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {

View File

@ -175,9 +175,7 @@ exports[`Upload Items Pane should render Default properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -354,9 +352,7 @@ exports[`Upload Items Pane should render Default properly 1`] = `
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -470,21 +466,9 @@ exports[`Upload Items Pane should render Default properly 1`] = `
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {

View File

@ -176,9 +176,7 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -355,9 +353,7 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
"keyspaceHasSharedOffer": [Function], "keyspaceHasSharedOffer": [Function],
"keyspaceId": [Function], "keyspaceId": [Function],
"keyspaceIds": [Function], "keyspaceIds": [Function],
"keyspaceOffers": HashMap { "keyspaceOffers": Map {},
"container": Object {},
},
"keyspaceThroughput": [Function], "keyspaceThroughput": [Function],
"maxThroughputRU": [Function], "maxThroughputRU": [Function],
"minThroughputRU": [Function], "minThroughputRU": [Function],
@ -475,21 +471,9 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
"resourceTree": ResourceTreeAdapter { "resourceTree": ResourceTreeAdapter {
"container": [Circular], "container": [Circular],
"copyNotebook": [Function], "copyNotebook": [Function],
"databaseCollectionIdMap": ArrayHashMap { "databaseCollectionIdMap": Map {},
"store": HashMap { "koSubsCollectionIdMap": Map {},
"container": Object {}, "koSubsDatabaseIdMap": Map {},
},
},
"koSubsCollectionIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"koSubsDatabaseIdMap": ArrayHashMap {
"store": HashMap {
"container": Object {},
},
},
"parameters": [Function], "parameters": [Function],
}, },
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken { "resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {

View File

@ -1,6 +1,5 @@
import * as ko from "knockout"; import * as ko from "knockout";
import * as Constants from "../../Common/Constants"; import * as Constants from "../../Common/Constants";
import { HashMap } from "../../Common/HashMap";
import { configContext, Platform } from "../../ConfigContext"; import { configContext, Platform } from "../../ConfigContext";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
@ -17,11 +16,11 @@ export default class MongoShellTab extends TabsBase {
public url: ko.Computed<string>; public url: ko.Computed<string>;
private _container: Explorer; private _container: Explorer;
private _runtimeEndpoint: string; private _runtimeEndpoint: string;
private _logTraces: HashMap<number>; private _logTraces: Map<string, number>;
constructor(options: ViewModels.TabOptions) { constructor(options: ViewModels.TabOptions) {
super(options); super(options);
this._logTraces = new HashMap<number>(); this._logTraces = new Map();
this._container = options.collection.container; this._container = options.collection.container;
this.url = ko.computed<string>(() => { this.url = ko.computed<string>(() => {
const account = userContext.databaseAccount; const account = userContext.databaseAccount;

View File

@ -5,7 +5,6 @@ import * as Constants from "../../Common/Constants";
import { queryDocuments } from "../../Common/dataAccess/queryDocuments"; import { queryDocuments } from "../../Common/dataAccess/queryDocuments";
import { queryDocumentsPage } from "../../Common/dataAccess/queryDocumentsPage"; import { queryDocumentsPage } from "../../Common/dataAccess/queryDocumentsPage";
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import { HashMap } from "../../Common/HashMap";
import * as HeadersUtility from "../../Common/HeadersUtility"; import * as HeadersUtility from "../../Common/HeadersUtility";
import { MinimalQueryIterator } from "../../Common/IteratorUtilities"; import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
@ -47,7 +46,7 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
public splitter: Splitter; public splitter: Splitter;
public isPreferredApiMongoDB: boolean; public isPreferredApiMongoDB: boolean;
public queryMetrics: ko.Observable<HashMap<DataModels.QueryMetrics>>; public queryMetrics: ko.Observable<Map<string, DataModels.QueryMetrics>>;
public aggregatedQueryMetrics: ko.Observable<DataModels.QueryMetrics>; public aggregatedQueryMetrics: ko.Observable<DataModels.QueryMetrics>;
public activityId: ko.Observable<string>; public activityId: ko.Observable<string>;
public roundTrips: ko.Observable<number>; public roundTrips: ko.Observable<number>;
@ -91,10 +90,8 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
this.isPreferredApiMongoDB = false; this.isPreferredApiMongoDB = false;
this.aggregatedQueryMetrics = ko.observable<DataModels.QueryMetrics>(); this.aggregatedQueryMetrics = ko.observable<DataModels.QueryMetrics>();
this._resetAggregateQueryMetrics(); this._resetAggregateQueryMetrics();
this.queryMetrics = ko.observable<HashMap<DataModels.QueryMetrics>>(new HashMap<DataModels.QueryMetrics>()); this.queryMetrics = ko.observable<Map<string, DataModels.QueryMetrics>>(new Map());
this.queryMetrics.subscribe((metrics: HashMap<DataModels.QueryMetrics>) => this.queryMetrics.subscribe((metrics) => this.aggregatedQueryMetrics(this._aggregateQueryMetrics(metrics)));
this.aggregatedQueryMetrics(this._aggregateQueryMetrics(metrics))
);
this.isQueryMetricsEnabled = ko.computed<boolean>(() => { this.isQueryMetricsEnabled = ko.computed<boolean>(() => {
return userContext.apiType === "SQL" || false; return userContext.apiType === "SQL" || false;
}); });
@ -364,13 +361,13 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
this.queryMetrics.valueHasMutated(); this.queryMetrics.valueHasMutated();
} }
private _aggregateQueryMetrics(metricsMap: HashMap<DataModels.QueryMetrics>): DataModels.QueryMetrics { private _aggregateQueryMetrics(metricsMap: Map<string, DataModels.QueryMetrics>): DataModels.QueryMetrics {
if (!metricsMap) { if (!metricsMap) {
return null; return null;
} }
const aggregatedMetrics: DataModels.QueryMetrics = this.aggregatedQueryMetrics(); const aggregatedMetrics: DataModels.QueryMetrics = this.aggregatedQueryMetrics();
metricsMap.forEach((partitionKeyRangeId: string, queryMetrics: DataModels.QueryMetrics) => { metricsMap.forEach((queryMetrics) => {
if (queryMetrics) { if (queryMetrics) {
aggregatedMetrics.documentLoadTime = aggregatedMetrics.documentLoadTime =
queryMetrics.documentLoadTime && queryMetrics.documentLoadTime &&
@ -510,7 +507,7 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
return null; return null;
} }
const queryMetrics: HashMap<DataModels.QueryMetrics> = this.queryMetrics(); const queryMetrics = this.queryMetrics();
let csvData: string = ""; let csvData: string = "";
const columnHeaders: string = const columnHeaders: string =
[ [
@ -528,7 +525,7 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
"Document write time (ms)", "Document write time (ms)",
].join(",") + "\n"; ].join(",") + "\n";
csvData = csvData + columnHeaders; csvData = csvData + columnHeaders;
queryMetrics.forEach((partitionKeyRangeId: string, queryMetric: DataModels.QueryMetrics) => { queryMetrics.forEach((queryMetric, partitionKeyRangeId) => {
const partitionKeyRangeData: string = const partitionKeyRangeData: string =
[ [
partitionKeyRangeId, partitionKeyRangeId,

View File

@ -930,7 +930,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
} }
private cleanupDatabasesKoSubs(): void { private cleanupDatabasesKoSubs(): void {
this.koSubsDatabaseIdMap.keys().forEach((databaseId: string) => { for (const databaseId of this.koSubsDatabaseIdMap.keys()) {
this.koSubsDatabaseIdMap.get(databaseId).forEach((sub: ko.Subscription) => sub.dispose()); this.koSubsDatabaseIdMap.get(databaseId).forEach((sub: ko.Subscription) => sub.dispose());
this.koSubsDatabaseIdMap.delete(databaseId); this.koSubsDatabaseIdMap.delete(databaseId);
@ -939,7 +939,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
.get(databaseId) .get(databaseId)
.forEach((collectionId: string) => this.cleanupKoSubsForCollection(databaseId, collectionId)); .forEach((collectionId: string) => this.cleanupKoSubsForCollection(databaseId, collectionId));
} }
}); }
} }
private cleanupCollectionsKoSubs(databaseId: string, existingCollectionIds: string[]): void { private cleanupCollectionsKoSubs(databaseId: string, existingCollectionIds: string[]): void {

View File

@ -14,7 +14,6 @@
"./src/Common/DeleteFeedback.ts", "./src/Common/DeleteFeedback.ts",
"./src/Common/DocumentUtility.ts", "./src/Common/DocumentUtility.ts",
"./src/Common/EnvironmentUtility.ts", "./src/Common/EnvironmentUtility.ts",
"./src/Common/HashMap.ts",
"./src/Common/HeadersUtility.test.ts", "./src/Common/HeadersUtility.test.ts",
"./src/Common/HeadersUtility.ts", "./src/Common/HeadersUtility.ts",
"./src/Common/Logger.ts", "./src/Common/Logger.ts",