Prepare for cache eveiction of nodes

This commit is contained in:
Johan Gyllenspetz 2015-12-29 10:52:30 -08:00
parent de84d78d02
commit e7ab40c8e2
3 changed files with 46 additions and 9 deletions

View File

@ -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: 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: Node): rx.Observable<Node> => {
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<Node>(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) {

View File

@ -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;

View File

@ -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<Node> {