Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | 8x 8x 8x 8x 8x 8x 8x | import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { CacheLayer } from './ngx-events-layer.layer';
import { CacheLayerInterface, CacheServiceConfigInterface, CacheLayerItem } from './ngx-events-layer.interfaces';
import { Service } from '../../container/index';
import { Container } from '../..';
const INTERNAL_PROCEDURE_CACHE_NAME = 'cache_layers';
const FRIENDLY_ERROR_MESSAGES = {
TRY_TO_UNSUBSCRIBE: 'Someone try to unsubscribe from collection directly... agghhh.. read docs! Blame: ',
LOCAL_STORAGE_DISABLED: 'LocalStorage is disabled switching to regular in-memory storage.Please relate issue if you think it is enabled and there is a problem with the library itself.'
};
@Service()
export class CacheService {
public _cachedLayers: BehaviorSubject<CacheLayer<CacheLayerItem<any>>[]> = new BehaviorSubject([]);
public map: Map<any, any> = new Map();
config: any = {};
public static createCacheInstance<T>(cacheLayer): CacheLayer<CacheLayerItem<T>> {
return new CacheLayer<CacheLayerItem<T>>(cacheLayer);
}
public static isLocalStorageUsable(): boolean {
const error = [];
try {
localStorage.setItem('test-key', JSON.stringify({ key: 'test-object' }));
localStorage.removeItem('test-key');
} catch (e) {
error.push(e);
console.log(FRIENDLY_ERROR_MESSAGES.LOCAL_STORAGE_DISABLED);
}
return error.length ? false : true;
}
public getLayer<T>(name: string): CacheLayer<CacheLayerItem<T>> {
const exists = this.map.has(name);
if (!exists) {
return this.createLayer<T>({ name: name });
}
return this.map.get(name);
}
public createLayer<T>(layer: CacheLayerInterface): CacheLayer<CacheLayerItem<T>> {
const exists = this.map.has(layer.name);
if (exists) {
return this.map.get(layer.name);
}
layer.items = layer.items || [];
layer.config = layer.config || this.config;
const cacheLayer = CacheService.createCacheInstance<T>(layer);
if (layer.config.localStorage && CacheService.isLocalStorageUsable()) {
localStorage.setItem(INTERNAL_PROCEDURE_CACHE_NAME, JSON.stringify([...CacheService.getLayersFromLS().filter(l => l !== cacheLayer.name), cacheLayer.name]));
localStorage.setItem(cacheLayer.name, JSON.stringify(layer));
}
this.map.set(cacheLayer.name, cacheLayer);
this._cachedLayers.next([...this._cachedLayers.getValue(), cacheLayer]);
this.LayerHook<T>(cacheLayer);
return cacheLayer;
}
private LayerHook<T>(layerInstance: CacheLayer<CacheLayerItem<T>>): void {
this.protectLayerFromInvaders<T>(layerInstance);
if (layerInstance.config.cacheFlushInterval || this.config.cacheFlushInterval) {
this.OnExpire(layerInstance);
}
}
private protectLayerFromInvaders<T>(cacheLayer: CacheLayer<CacheLayerItem<T>>): void {
cacheLayer.items.constructor.prototype.unsubsribeFromLayer = cacheLayer.items.constructor.prototype.unsubscribe;
cacheLayer.items.constructor.prototype.unsubscribe = () => {
console.error(FRIENDLY_ERROR_MESSAGES.TRY_TO_UNSUBSCRIBE + cacheLayer.name);
};
}
private OnExpire<T>(layerInstance: CacheLayer<CacheLayerItem<T>>): void {
Observable
.create(observer => observer.next())
.timeoutWith(layerInstance.config.cacheFlushInterval || this.config.cacheFlushInterval, Observable.of(1))
.skip(1)
.subscribe(observer => this.removeLayer(layerInstance));
}
public removeLayer<T>(layerInstance: CacheLayer<CacheLayerItem<T>>): void {
this.map.delete(layerInstance.name);
if (this.config.localStorage) {
localStorage.removeItem(layerInstance.name);
localStorage.setItem(INTERNAL_PROCEDURE_CACHE_NAME, JSON.stringify(CacheService.getLayersFromLS().filter(layer => layer !== layerInstance.name)));
}
this._cachedLayers.next([...this._cachedLayers.getValue().filter(layer => layer.name !== layerInstance.name)]);
}
public transferItems(name: string, newCacheLayers: CacheLayerInterface[]): CacheLayer<CacheLayerItem<any>>[] {
const oldLayer = this.getLayer(name);
const newLayers = [];
newCacheLayers.forEach(layerName => {
const newLayer = this.createLayer(layerName);
oldLayer.items.getValue().forEach(item => newLayer.putItem(item));
newLayers.push(newLayer);
});
return newLayers;
}
public static getLayersFromLS(): Array<string> {
return JSON.parse(localStorage.getItem(INTERNAL_PROCEDURE_CACHE_NAME));
}
public flushCache(force?: boolean): Observable<boolean> {
let oldLayersNames: string[];
return this._cachedLayers.take(1)
.map(layers => {
oldLayersNames = layers.map(l => l.name);
layers.forEach(layer => this.removeLayer(layer));
if (force) {
localStorage.removeItem(INTERNAL_PROCEDURE_CACHE_NAME);
} else {
oldLayersNames.forEach((l) => this.createLayer({ name: l }));
}
return true;
});
}
} |