2

Having a piece of code that fetches some data to a cache, and keeps it in sync using a websocket connection, and provides an access interface to the data using an Observable, how can I know that there are no subscribers to said data at one point in time?

I would like to hook onto the unsubscribe() call for the observable (and check wether the subscribers count is 0), but I'm not sure how to achieve that.

The real life scenario is a graphql query (apollo-angular), and a websocket subscription to keep the data in sync. Once there is no subscribers to the data (the user navigated to another page for ex.), the websocket connection could be closed to save server resources, but the data needs to be deleted from the cache at the same time, otherwise it might go out of sync, as there are no push events received from the server anymore, in case the user navigates back again. I'm reluctant to keep data in the cache that is stale.

So... How can I hook into the event that a observable is being destroyed / all subscribers have unsubscribed to delete the data from the cache as well? The service sets up a graphql query and sets up the subscription to listen for changes, returning the Observable, but i'm not sure how can I tear the thing down, as the instance has been passed on the the user code.

I'm not looking for network-only, circumventing the cache, and similar setups of the apollo client, I'm looking for a way to actually use, but keep the data in the apollo cache clean and up to date, as the server provides a way to do that.

Ákos Vandra-Meyer
  • 1,890
  • 1
  • 23
  • 40
  • 2
    Could you use refCount and a Subject? How much control over the websocket observable do you have? – NathanH May 27 '20 at 16:35

1 Answers1

2

If you're using RxJS, you could leverage WebSocketSubject, which comes with some great options.

For example, the WebSocketSubject can be given a configuration object, where one useful option is closeObserver: NextObserver<T>, whose next method is called when the socket connection becomes closed.

The connection is automatically closed when the WebSocketSubject has no more active subscribers.


Here's the code for the above idea:

const connectionClosed = new Subjet();
const unsubscribe = new Subject();

const webSocket = new WebSocketSubject({
  url: '',
  /* ... */,
  closeObserver: connectionClosed
});

connectionClosed.subscribe(() => {
  // Teardown logic
  // e.g clear cache 
});


// Registering subscribers
webSocket.pipe(takeUntil(unsubscribe)).subscribe(...);
webSocket.pipe(takeUntil(unsubscribe)).subscribe(...);
webSocket.pipe(takeUntil(unsubscribe)).subscribe(...);

// In `ngOnDestroy`, called maybe when the user navigates to another route
unsubscribe.next();
unsubscribe.complete();
Andrei Gătej
  • 11,116
  • 1
  • 14
  • 31