angelnikolov / ts-cacheable

Observable/Promise Cache Decorator
https://npmjs.com/package/ts-cacheable
ISC License
340 stars 42 forks source link

how to bust a cache? #4

Closed moshejs closed 5 years ago

moshejs commented 6 years ago

Great module! I'm confused how to bust the cache based on an action or another API call (such as "add item, remove item, etc.)

a sample would help.

Thanks

angelnikolov commented 6 years ago

You can achieve it by decorating the cache busting method with the CacheBuster decorator, like;

const cacheBuster$ = new Subject<void>();
export class Service {
  @Cacheable({
    cacheBusterObserver: cacheBuster$
  })
  getData() {
    ///needs to return an Observable
  }
  @CacheBuster({
    cacheBusterNotifier: cacheBuster$
  })
  saveData() {
    ///needs to return an Observable
  }
}

Going to close this issue, once I updated the readme. Thanks!!

angelnikolov commented 5 years ago

Readme file was updated. Timely :)

angelnikolov commented 5 years ago

@syedabdrehman I don't understand the issue. Is there a question?

theCreativeGuy commented 5 years ago

I'm refering the above given example const cacheBuster$ = new Subject(); export class Service { @Cacheable({ cacheBusterObserver: cacheBuster$ }) getMerchants() {...}

@CacheBuster({ cacheBusterNotifier: cacheBuster$ }) addMerchants ( ) {....}

@CacheBuster({ cacheBusterNotifier: cacheBuster$ }) saveMerchants ( ) {...} }

On adding merchants and update of merchant details,the cache gets busted and time to load the data is taking some time,Any suggestions to improve the performance?

angelnikolov commented 5 years ago

Well, that's the idea of it, if you bust the cache you will now fetch from the server. I would suggest to not use a @CacheBuster, but rather provide a custom subject to the Cacheable decorator, and just next() on it when you want to remove the cache. Then you can control when the cache is removed and you won't depend on the saveMerchants request completing..

theCreativeGuy commented 5 years ago

Well, that's the idea of it, if you bust the cache you will now fetch from the server. I would suggest to not use a @cachebuster, but rather provide a custom subject to the Cacheable decorator, and just next() on it when you want to remove the cache. Then you can control when the cache is removed and you won't depend on the saveMerchants request completing..

Would you Please provide an example for merchants for the above answer ?

angelnikolov commented 5 years ago

@theCreativeGuy It'd be best if you provide an example of what you want to accomplish and most importantly - when do you want to bust the cache. What is the use case and etc..

theCreativeGuy commented 5 years ago

@theCreativeGuy It'd be best if you provide an example of what you want to accomplish and most importantly - when do you want to bust the cache. What is the use case and etc..

Let's say there are 2 merchants : A and B A -- > Fetching A details through API,data gets cached B ---> Fetching B details through API,data gets cached and when I again fetch A details,A's cache data gets removed

How can this problem be resolved so that A's details are not removed from cache ? and I would like to know on what basis data gets stored in cache?

djhouseknecht commented 4 years ago

@theCreativeGuy I know this is an old post, but the way to accomplish your desired results is to use the configuration option maxCacheCount. It will cache calls based on what parameters are passed in. For your case, you would use it like this:

@Injectable({providedIn: 'root'})
export class MerchantService {

 constructor (private http: HttpClient) { }

  @Cacheable({
    maxCacheCount: 2 // or however many you want
  })
  getMerchantById(merchantId: string): Observable<any> {
    return this.http.get(`${YOUR_MERCHANT_ENDPOINT}/${merchantId}`);
  }
}

maxCacheCount will cache all requests based on their parameters.

NemeanLionBot commented 4 years ago

Hi, I am very new to coding and trying to get my cache to refresh and return the last submitted data. I started by trying the cacheBuster method but it did not work for me. Do you have a working example of how to provide a custom subject to the Cacheable decorator, and just next() on it when you want to remove the cache?

djhouseknecht commented 4 years ago

@NemeanLionBot, I made a stackblitz example where you can see the cache buster in action. Feel free to play around with with some of the other cool options ngx-cacheable has to offer.

For quick reference, here is the code in app.service.ts:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable, Subject } from "rxjs";
import { tap } from "rxjs/operators";
import { Cacheable } from "ngx-cacheable";

/* cache buster Subject */
const cacheBuster$ = new Subject();

@Injectable({ providedIn: "root" })
export class AppService {

  constructor(private http: HttpClient) {
    cacheBuster$.subscribe(() => {
      console.log('app.service cacheBuster$ just emitted');
    });
  }

  @Cacheable({
    maxCacheCount: 2,
    cacheBusterObserver: cacheBuster$.asObservable() 
  })
  loadGithubUser(username: string): Observable<any> {
    /* this will only get called if we don't have a value in the cache */
    return this.http
      .get<any>(`https://api.github.com/users/${username}`)
      .pipe(
        tap(user => {
          console.log("app.service loaded a user from github's api", user);
        })
      );
  }

  bustCache() {
    cacheBuster$.next();
  }
}
NemeanLionBot commented 4 years ago

Thanks djhouseknecht . I'll have a play with this. I'll update if I make it work on my project.