Skip to content

Commit

Permalink
Fix to object (#240)
Browse files Browse the repository at this point in the history
* fix-cache-ttl
  • Loading branch information
maxi7587 authored and pablorsk committed Oct 9, 2019
1 parent d33303f commit af98946
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 16 deletions.
13 changes: 13 additions & 0 deletions src/document-collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@ export class RelatedDocumentCollection<R extends Resource = Resource> extends Do
});
}

public setCacheLastUpdate(value = Date.now()) {
this.cache_last_update = value;
}

public setCacheLastUpdateAndPropagate(value = Date.now()) {
this.setCacheLastUpdate(value);
this.data.forEach(resource => {
if (resource instanceof Resource) {
resource.setCacheLastUpdate(value);
}
});
}

public toObject(params?: IParamsCollection): IDataCollection {
if (!this.builded) {
return { data: this.data };
Expand Down
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-jsonapi",
"version": "2.1.9",
"version": "2.1.10",
"description": "JSON API library for Angular",
"module": "ngx-jsonapi/@ngx-jsonapi/ngx-jsonapi.es5.js",
"es2015": "ngx-jsonapi/@ngx-jsonapi/ngx-jsonapi.js",
Expand Down
4 changes: 4 additions & 0 deletions src/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,4 +341,8 @@ export class Resource implements ICacheable {
}
}
}

public setCacheLastUpdate(value = Date.now()) {
this.cache_last_update = value;
}
}
97 changes: 84 additions & 13 deletions src/service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ describe('service.all()', () => {
await booksService.clearCacheMemory();
test_response_subject.complete();
test_response_subject = new BehaviorSubject(new HttpResponse());

// clear cachememory on every test
let cachememory = CacheMemory.getInstance();
(cachememory as any).resources = {};
(cachememory as any).collections = {};
});

it(`without cached collection emits source ^new-server|`, async () => {
Expand Down Expand Up @@ -179,13 +184,14 @@ describe('service.all()', () => {
test_response_subject.next(new HttpResponse({ body: TestFactory.getCollectionDocumentData(Book) }));
booksService.collections_ttl = 5; // live
await booksService.all().toPromise();
CacheMemory.getInstance().deprecateCollections(''); // kill only memory cache
let cachememory = CacheMemory.getInstance(); // kill only memory cache
(cachememory as any).resources = {}; // kill memory cache
(cachememory as any).collections = {}; // kill memory cache

let http_request_spy = spyOn(HttpClient.prototype, 'request').and.callThrough();
let expected = [
// expected emits
// source_resource: 'server' because we dont touch child elements
{ builded: true, loaded: false, source: 'new', source_resource: 'server' },
{ builded: false, loaded: false, source: 'new', source_resource: undefined },
{ builded: true, loaded: true, source: 'store', source_resource: 'store' }
];

Expand All @@ -199,7 +205,44 @@ describe('service.all()', () => {
}
}),
map(emit => {
return { builded: emit.builded, loaded: emit.loaded, source: emit.source, source_resource: emit.data[0].source };
if (emit.data.length > 0) {
return { builded: emit.builded, loaded: emit.loaded, source: emit.source, source_resource: emit.data[0].source };
} else {
return { builded: emit.builded, loaded: emit.loaded, source: emit.source, source_resource: undefined };
}
}),
toArray()
)
.toPromise();
expect(emits).toMatchObject(expected);
expect(http_request_spy).toHaveBeenCalledTimes(0);
});

it(`with cached on store (live) collection wihtout includes emits source ^new-store|`, async () => {
// caching collection
test_response_subject.next(new HttpResponse({ body: TestFactory.getCollectionDocumentData(Book) }));
booksService.collections_ttl = 5; // live
await booksService.all({ include: ['author'] }).toPromise();
let cachememory = CacheMemory.getInstance(); // kill only memory cache
(cachememory as any).resources = {}; // kill memory cache
(cachememory as any).collections = {}; // kill memory cache

let http_request_spy = spyOn(HttpClient.prototype, 'request').and.callThrough();
let expected = [
// expected emits
{ builded: false, loaded: false, source: 'new', source_resource: undefined },
{ builded: true, loaded: true, source: 'store', source_resource: 'store' }
];

let emits = await booksService
.all()
.pipe(
map(emit => {
if (emit.data.length > 0) {
return { builded: emit.builded, loaded: emit.loaded, source: emit.source, source_resource: emit.data[0].source };
} else {
return { builded: emit.builded, loaded: emit.loaded, source: emit.source, source_resource: undefined };
}
}),
toArray()
)
Expand All @@ -213,13 +256,39 @@ describe('service.all()', () => {
test_response_subject.next(new HttpResponse({ body: TestFactory.getCollectionDocumentData(Book) }));
booksService.collections_ttl = 0; // dead
await booksService.all().toPromise();
booksService.clearCacheMemory(); // kill only memory cache
CacheMemory.getInstance().deprecateCollections('');

let http_request_spy = spyOn(HttpClient.prototype, 'request').and.callThrough();
let expected = [
// expected emits
{ builded: true, loaded: false, source: 'new' }, // @TODO: builded should be false
{ builded: true, loaded: true, source: 'server' }
];

let emits = await booksService
.all()
.pipe(
map(emit => {
return { builded: emit.builded, loaded: emit.loaded, source: emit.source };
}),
toArray()
)
.toPromise();
expect(emits).toMatchObject(expected);
expect(http_request_spy).toHaveBeenCalledTimes(1);
});

it(`with cached on store (dead, no collection_ttl defined) collection emits source ^new-store-server|`, async () => {
// caching collection
test_response_subject.next(new HttpResponse({ body: TestFactory.getCollectionDocumentData(Book) }));
delete booksService.collections_ttl; // dead
await booksService.all().toPromise();
CacheMemory.getInstance().deprecateCollections('');

let http_request_spy = spyOn(HttpClient.prototype, 'request').and.callThrough();
let expected = [
// expected emits
{ builded: true, loaded: false, source: 'new' }, // @TODO: builded should be false
// { builded: true, loaded: false, source: 'store' }, // @todo
{ builded: true, loaded: true, source: 'server' }
];

Expand Down Expand Up @@ -320,6 +389,7 @@ describe('service.all() and next service.get()', () => {
});

it(`with cached collection on memory and next request get() without include`, async () => {
Author.test_ttl = 100000;
let http_request_spy = spyOn(HttpClient.prototype, 'request').and.callThrough();
let all_authors_body = TestFactory.getCollectionDocumentData(Author, 1, ['books']);
test_response_subject.next(new HttpResponse({ body: all_authors_body }));
Expand All @@ -346,8 +416,7 @@ describe('service.all() and next service.get()', () => {
)
.toPromise();

// @TODO: fix this error!!!
// expect(author_emits).toMatchObject(expected); // ERROR!!! [{ loaded: false, source: 'memory' }, { loaded: false, source: 'store' }]
expect(author_emits).toMatchObject(expected);
// expect(received_author.relationships.books.data[0].attributes).toBeFalsy(); // ERROR!!!
expect(http_request_spy).toHaveBeenCalledTimes(1); // on all() request
});
Expand Down Expand Up @@ -385,7 +454,7 @@ describe('service.all() and next service.get()', () => {
.toPromise();

// @TODO: fix this error!!!
// expect(author_emits).toMatchObject(expected); // ERROR!!! [{ loaded: false, source: 'new' }, { loaded: false, source: 'store' }]
expect(author_emits).toMatchObject(expected);
// expect(received_author.relationships.books.data[0].attributes).toBeFalsy(); // ERROR!!!
expect(http_request_spy).toHaveBeenCalledTimes(1); // on all() request
});
Expand All @@ -395,6 +464,7 @@ describe('service.get()', () => {
let core: Core;
let booksService: BooksService;
let authorsService: AuthorsService;
let photosService: PhotosService;
beforeEach(async () => {
core = new Core(
new JsonapiConfig(),
Expand All @@ -406,6 +476,8 @@ describe('service.get()', () => {
await booksService.clearCacheMemory();
authorsService = new AuthorsService();
authorsService.register();
photosService = new PhotosService();
photosService.register();
await authorsService.clearCacheMemory();
test_response_subject.complete();
test_response_subject = new BehaviorSubject(new HttpResponse());
Expand Down Expand Up @@ -589,17 +661,16 @@ describe('service.get()', () => {
{ loaded: true, source: 'server' }
];
let emits = await booksService
.get('1', { ttl: 1000 })
.get('1')
.pipe(
map(emit => {
return { loaded: emit.loaded, source: emit.source };
}),
toArray()
)
.toPromise();
// @TODO: fix library
// expect(emits).toMatchObject(expected); // ERROR!!! [{ loaded: true, source: 'memory' }, { loaded: true, source: 'server' }]
// expect(http_request_spy).toHaveBeenCalledTimes(1); // ERROR: receiving 0...
expect(emits).toMatchObject(expected);
expect(http_request_spy).toHaveBeenCalledTimes(1);
});

it(`with cached on store (live) resource emits source ^new-store|`, async () => {
Expand Down
20 changes: 19 additions & 1 deletion src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ export class Service<R extends Resource = Resource> {

return;
}

throw new Error('Resource is dead!');
}

// if you change this logic, maybe you need to change getAllFromServer()
Expand Down Expand Up @@ -193,7 +195,14 @@ export class Service<R extends Resource = Resource> {
return <R>resource;
}

/**
* deprecated since 2.2
*/
public async clearCacheMemory(): Promise<boolean> {
return this.clearCache();
}

public async clearCache(): Promise<boolean> {
let path = new PathBuilder();
path.applyParams(this);

Expand Down Expand Up @@ -240,6 +249,10 @@ export class Service<R extends Resource = Resource> {
public all(params: IParamsCollection = {}): Observable<DocumentCollection<R>> {
let builded_params: IBuildedParamsCollection = { ...Base.ParamsCollection, ...params };

if (!builded_params.ttl && builded_params.ttl !== 0) {
builded_params.ttl = this.collections_ttl;
}

let path = new PathCollectionBuilder();
path.applyParams(this, builded_params);

Expand All @@ -260,7 +273,9 @@ export class Service<R extends Resource = Resource> {
this.getAllFromLocal(builded_params, path, temporary_collection)
.then(() => {
subject.next(temporary_collection);
setTimeout(() => subject.complete(), 0);
setTimeout(() => {
subject.complete();
}, 0);
})
.catch(() => {
temporary_collection.setLoaded(false);
Expand Down Expand Up @@ -305,6 +320,8 @@ export class Service<R extends Resource = Resource> {

return;
}

throw new Error('Collection is dead!');
}

// if you change this logic, maybe you need to change getGetFromServer()
Expand All @@ -329,6 +346,7 @@ export class Service<R extends Resource = Resource> {
}
temporary_collection.fill(<IDataCollection>success);
temporary_collection.cache_last_update = Date.now();
temporary_collection.setCacheLastUpdateAndPropagate();
temporary_collection.setSourceAndPropagate('server');
temporary_collection.setLoadedAndPropagate(true);

Expand Down
1 change: 0 additions & 1 deletion src/services/json-ripper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ describe('JsonRipper for collections', () => {
author1.relationships.books.data[1].id = '2';
let book1 = author1.relationships.books.data[0];
book1.addRelationship(author1, 'author');
console.log(author1.relationships.books.data[1]);

/* Is private now
it('A collection is converted to objects for a DataProvider', () => {
Expand Down
9 changes: 9 additions & 0 deletions src/tests/factories/authors.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ export class Author extends Resource {
};
public type = 'authors';
public ttl = 0;
public static test_ttl;

public constructor() {
super();

if (Author.test_ttl || Author.test_ttl === 0) {
this.ttl = Author.test_ttl;
}
}
}

export class AuthorsService extends Service<Author> {
Expand Down
9 changes: 9 additions & 0 deletions src/tests/factories/books.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ export class Book extends Resource {
};
public type = 'books';
public ttl = 0;
public static test_ttl;

public constructor() {
super();

if (Book.test_ttl || Book.test_ttl === 0) {
this.ttl = Book.test_ttl;
}
}
}

export class BooksService extends Service<Book> {
Expand Down
12 changes: 12 additions & 0 deletions src/tests/factories/photos.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ export class Photo extends Resource {
created_at: new Date(),
updated_at: new Date()
};

public type = 'photos';
public ttl = 0;
public static test_ttl;

public constructor() {
super();

if (Photo.test_ttl || Photo.test_ttl === 0) {
this.ttl = Photo.test_ttl;
}
}
}

export class PhotosService extends Service<Photo> {
Expand Down

0 comments on commit af98946

Please sign in to comment.