From e7ab40c8e261fba5a347fe751d09df080f8fc36a Mon Sep 17 00:00:00 2001 From: Johan Gyllenspetz Date: Tue, 29 Dec 2015 10:52:30 -0800 Subject: [PATCH] Prepare for cache eveiction of nodes --- src/graph/GraphService.ts | 22 +++++++++++++--------- src/graph/MyGraph.ts | 29 +++++++++++++++++++++++++++++ src/graph/Node.ts | 4 ++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/graph/GraphService.ts b/src/graph/GraphService.ts index 4dd93ec9..63c2d005 100644 --- a/src/graph/GraphService.ts +++ b/src/graph/GraphService.ts @@ -25,37 +25,39 @@ export class GraphService { this.prisitine = true; this.tilesService = new TilesService(clientId); + // operation pattern updating the graph this.graph = this.updates .scan( (myGraph: MyGraph, operation: IGraphOperation): MyGraph => { - return operation(myGraph); + let newMyGraph: MyGraph = operation(myGraph); + newMyGraph.evictNodeCache(); + return newMyGraph; }, new MyGraph()) .shareReplay(1); + // stream of cached nodes, uses distinct to not cache a node more than once this.cachedNode = this.cache.distinct((node: Node): string => { - return node.key; + return node.key + node.lastCacheEvict; }).flatMap((node: Node): rx.Observable => { return node.cacheAssets(); }); + + // make tilesservice aware of that a new node is beeing cached this.cachedNode.subscribe(this.tilesService.cacheNode); + // save the cached node to the graph, cache its edges this.cachedNode.map((node: Node) => { return (myGraph: MyGraph): MyGraph => { - myGraph.computeEdges(node); - node.cached = true; + myGraph.cacheNode(node); return myGraph; }; }).subscribe(this.updates); + // feedback from tiles service adding fresh tiles to the graph this.tilesService.tiles.map((data: IAPINavIm): IGraphOperation => { return (myGraph: MyGraph): MyGraph => { - if (data === undefined) { - return myGraph; - } - myGraph.addNodesFromAPI(data); - return myGraph; }; }).subscribe(this.updates); @@ -79,6 +81,7 @@ export class GraphService { return myGraph.getNode(key); }); + // hack to start of the whole graph fetching process, a better trigger is needed if (this.prisitine) { this.tilesService.cacheIm.onNext(key); this.prisitine = false; @@ -92,6 +95,7 @@ export class GraphService { rx.Observable.throw(new Error("node is not yet cached")); } + // go find the next node return this.graph.map((myGraph: MyGraph): string => { let nextNode: Node = myGraph.nextNode(node, dir); if (nextNode == null) { diff --git a/src/graph/MyGraph.ts b/src/graph/MyGraph.ts index 79f8e5f5..23f6e026 100644 --- a/src/graph/MyGraph.ts +++ b/src/graph/MyGraph.ts @@ -21,6 +21,8 @@ export class MyGraph { private graph: any; private spatial: any; + private cachedNodes: {[key: string]: boolean}; + private boxWidth: number = 0.001; private defaultAlt: number = 2; @@ -32,12 +34,17 @@ export class MyGraph { this.sequenceHash = {}; this.spatial = rbush(20000, [".lon", ".lat", ".lon", ".lat"]); this.graph = new graphlib.Graph({multigraph: true}); + this.cachedNodes = {}; this.edgeCalculator = new EdgeCalculator(); this.spatialLib = new Spatial(); this.geoCoords = new GeoCoords(); } public addNodesFromAPI(data: IAPINavIm): void { + if (data === undefined) { + return; + } + let nodes: Node[]; let sequences: Sequence[]; let sequenceHash: {[key: string]: Sequence} = {}; @@ -105,6 +112,28 @@ export class MyGraph { }); } + public cacheNode(node: Node): void { + this.computeEdges(node); + node.cached = true; + node.lastUsed = new Date().getTime(); + this.cachedNodes[node.key] = true; + } + + public evictNodeCache(): void { + if (Object.keys(this.cachedNodes).length < 30) { + // no cleaning of cache + return; + } + // evice nodes from cache here + return; + } + + public unCacheNode(node: Node): void { + delete this.cachedNodes[node.key]; + node.lastCacheEvict = new Date().getTime(); + console.log("uncache"); + } + public computeEdges(node: Node): boolean { if (!node.worthy) { return false; diff --git a/src/graph/Node.ts b/src/graph/Node.ts index 022d9e51..6095106d 100644 --- a/src/graph/Node.ts +++ b/src/graph/Node.ts @@ -16,6 +16,8 @@ export class Node { public apiNavImIm: IAPINavImIm; public translation: number[]; public cached: boolean; + public lastCacheEvict: number; + public lastUsed: number; public image: any; public mesh: any; @@ -37,6 +39,8 @@ export class Node { this.apiNavImIm = apiNavImIm; this.translation = translation; this.cached = false; + this.lastCacheEvict = 0; + this.lastUsed = new Date().getTime(); } public cacheAssets(): rx.Observable {