Skip to content

Commit 06d12d5

Browse files
authored
Merge pull request #116 from kygoh/refactor-cache-blob
Consolidate blob handling functions into original functions
2 parents dcdda64 + 763b95f commit 06d12d5

File tree

2 files changed

+51
-92
lines changed

2 files changed

+51
-92
lines changed

src/cache.service.spec.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ describe('CacheService', () => {
102102
const response = await fetch(dataURL);
103103
const blob = await response.blob();
104104

105-
await service.saveBlobItem(blobKey, blob, groupKey, ttl);
105+
await service.saveItem(blobKey, blob, groupKey, ttl);
106106
done();
107107
} catch (e) {
108108
expect(e).toBeUndefined();
@@ -115,7 +115,7 @@ describe('CacheService', () => {
115115
const response = await fetch(dataURL);
116116
const blob = await response.blob();
117117

118-
let value = await service.getBlobItem(blobKey);
118+
const value = await service.getItem(blobKey);
119119
expect(value).toEqual(blob);
120120
done();
121121
} catch (e) {
@@ -173,7 +173,7 @@ describe('CacheService', () => {
173173
it('should throw error because cache blob expired (async)', done => {
174174
setTimeout(async () => {
175175
try {
176-
await service.getBlobItem(blobKey);
176+
await service.getItem(blobKey);
177177

178178
expect(false).toBeTruthy();
179179
done();
@@ -576,7 +576,7 @@ describe('Observable blob caching errors', () => {
576576
});
577577

578578
it('should return data from observable (async)', (done: any) => {
579-
service.loadFromBlobObservable(key, observableError).subscribe(
579+
service.loadFromObservable(key, observableError).subscribe(
580580
res => {
581581
expect(true).toBeFalsy();
582582
done();
@@ -602,9 +602,9 @@ describe('Observable Blob Caching', () => {
602602

603603
const delay = ms => new Promise(res => setTimeout(res, ms));
604604

605-
let mockBlob: Blob = new Blob(['Hello, world!'], {type: 'text/plain'});
605+
const mockBlob: Blob = new Blob(['Hello, world!'], {type: 'text/plain'});
606606

607-
let observable = of(mockBlob);
607+
const observable = of(mockBlob);
608608

609609
let service: CacheService;
610610

@@ -629,7 +629,7 @@ describe('Observable Blob Caching', () => {
629629
});
630630

631631
it('should return blob data from observable (async)', (done: any) => {
632-
service.loadFromBlobObservable(key, observable).subscribe(
632+
service.loadFromObservable(key, observable).subscribe(
633633
async res => {
634634
expect(res).toBeDefined();
635635
expect(observable.subscribe).toHaveBeenCalled();
@@ -645,7 +645,7 @@ describe('Observable Blob Caching', () => {
645645
});
646646

647647
it('should return cached observable blob data (async)', done => {
648-
service.loadFromBlobObservable(key, observable).subscribe(res => {
648+
service.loadFromObservable(key, observable).subscribe(res => {
649649
expect(observable.subscribe).not.toHaveBeenCalled();
650650
expect(res).toEqual(mockBlob);
651651
done();

src/cache.service.ts

+43-84
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ const isHttpResponse = (data: any): boolean => {
3737
return data && (data instanceof HttpResponse || orCondition);
3838
};
3939

40+
const isJsOrResponseType = (data: any): boolean => {
41+
const jsType =
42+
data.type === 'undefined' ||
43+
data.type === 'object' ||
44+
data.type === 'boolean' ||
45+
data.type === 'number' ||
46+
data.type === 'bigint' ||
47+
data.type === 'string' ||
48+
data.type === 'symbol' ||
49+
data.type === 'function';
50+
51+
const responseType =
52+
data.type === 'response';
53+
54+
return responseType || jsType;
55+
}
56+
4057
@Injectable()
4158
export class CacheService {
4259
private ttl: number = 60 * 60; // one hour
@@ -151,6 +168,10 @@ export class CacheService {
151168
throw new Error(MESSAGES[1]);
152169
}
153170

171+
if (Blob.name === data.constructor.name) {
172+
return this.saveBlobItem(key, data, groupKey, ttl);
173+
}
174+
154175
const expires = new Date().getTime() + ttl * 1000,
155176
type = isHttpResponse(data) ? 'response' : typeof data,
156177
value = JSON.stringify(data);
@@ -171,7 +192,7 @@ export class CacheService {
171192
* @param {number} [ttl] - TTL in seconds
172193
* @return {Promise<any>} - saved data
173194
*/
174-
async saveBlobItem(
195+
private async saveBlobItem(
175196
key: string,
176197
blob: any,
177198
groupKey: string = 'none',
@@ -306,25 +327,6 @@ export class CacheService {
306327
return CacheService.decodeRawData(data);
307328
}
308329

309-
/**
310-
* @description Get blob item from cache with expire check and correct type assign
311-
* @param {string} key - Unique key
312-
* @return {Promise<any>} - promise that resolves with blob data from cache
313-
*/
314-
async getBlobItem(key: string): Promise<Blob> {
315-
if (!this.cacheEnabled) {
316-
throw new Error(MESSAGES[1]);
317-
}
318-
319-
let data = await this.getRawItem(key);
320-
321-
if (data.expires < new Date().getTime() && (this.invalidateOffline || this.isOnline())) {
322-
throw new Error(MESSAGES[2] + key);
323-
}
324-
325-
return CacheService.decodeRawBlobData(data);
326-
}
327-
328330
async getOrSetItem<T>(
329331
key: string,
330332
factory: CacheValueFactory<T>,
@@ -348,35 +350,28 @@ export class CacheService {
348350
* @param {any} data - Data
349351
* @return {any} - decoded data
350352
*/
351-
static decodeRawData(data: StorageCacheItem): any {
353+
static async decodeRawData(data: StorageCacheItem): Promise<any> {
352354
let dataJson = JSON.parse(data.value);
353-
if (isHttpResponse(dataJson)) {
354-
let response: any = {
355-
body: dataJson._body || dataJson.body,
356-
status: dataJson.status,
357-
headers: dataJson.headers,
358-
statusText: dataJson.statusText,
359-
url: dataJson.url
360-
};
361-
362-
return new HttpResponse(response);
363-
}
364-
365-
return dataJson;
366-
}
367-
368-
/**
369-
* @description Decode raw blob data from DB
370-
* @param {any} data - Data
371-
* @return {Promise<Blob>} - promise that resolves with a Blob.
372-
*/
373-
static async decodeRawBlobData(data: StorageCacheItem): Promise<Blob> {
374-
const dataURL = JSON.parse(data.value);
355+
if (isJsOrResponseType(data)) {
356+
if (isHttpResponse(dataJson)) {
357+
let response: any = {
358+
body: dataJson._body || dataJson.body,
359+
status: dataJson.status,
360+
headers: dataJson.headers,
361+
statusText: dataJson.statusText,
362+
url: dataJson.url
363+
};
364+
365+
return new HttpResponse(response);
366+
}
375367

376-
// Technique derived from: https://stackoverflow.com/a/36183085
377-
const response = await fetch(dataURL);
368+
return dataJson;
369+
} else {
370+
// Technique derived from: https://stackoverflow.com/a/36183085
371+
const response = await fetch(dataJson);
378372

379-
return response.blob();
373+
return response.blob();
374+
}
380375
}
381376

382377
/**
@@ -470,8 +465,8 @@ export class CacheService {
470465
})
471466
.catch(e => {
472467
this.getRawItem<T>(key)
473-
.then(res => {
474-
let result = CacheService.decodeRawData(res);
468+
.then(async(res) => {
469+
let result = await CacheService.decodeRawData(res);
475470
if (metaKey) {
476471
result[metaKey] = result[metaKey] || {};
477472
result[metaKey].fromCache = true;
@@ -485,42 +480,6 @@ export class CacheService {
485480
return observableSubject.asObservable();
486481
}
487482

488-
/**
489-
* @description Load blob item from cache if it's in cache or load from origin observable
490-
* @param {string} key - Unique key
491-
* @param {any} observable - Observable with blob data
492-
* @param {string} [groupKey] - group key
493-
* @param {number} [ttl] - TTL in seconds
494-
* @return {Observable<any>} - blob data from cache or origin observable
495-
*/
496-
loadFromBlobObservable(
497-
key: string,
498-
observable: Observable<Blob>,
499-
groupKey?: string,
500-
ttl?: number
501-
): Observable<Blob> {
502-
if (!this.cacheEnabled) return observable;
503-
504-
observable = observable.pipe(share());
505-
506-
return defer(() => {
507-
return from(this.getBlobItem(key)).pipe(
508-
catchError(e => {
509-
observable.subscribe(
510-
blob => {
511-
return this.saveBlobItem(key, blob, groupKey, ttl);
512-
},
513-
error => {
514-
return throwError(error);
515-
}
516-
);
517-
518-
return observable;
519-
})
520-
);
521-
});
522-
}
523-
524483
/**
525484
* Perform complete cache clear
526485
* @return {Promise<any>}

0 commit comments

Comments
 (0)