Best practice for putting code to subscribe to pubs

I only have very few pub/sub left but two of them are currently in the FlowRouter.subscriptions function.

As that function gets executed a lot of times, I feel it’s not the right place. IMO, a (general - meaning its needed all the time) sub to a pub should only be executed once during startup.

What is the best practice for such a general sub to a pub? Where did you put it in your project and when is it executed during startup (should be as early as possible IMO as one of them for example is checking if the backend system is up & running or currently down for maintenance or other reasons).

Thanks in advance,

Andreas

I’m using react, for this kind of subscriptions, I put it in a component which won’t change (rerender). For example

<App>
// other components here

<ComponentDoesSubscriptions />
</App>
``

I might use a method for stuff like this where ur just checking on or pulling data arbitrarily like that. U can use a subscription I guess but a method might serve ur use case better.

He said “I only have very few pub/sub left” so I guess he used methods already.

Two pub/subs to be precise, yes.

In those two cases I need the reactivity. As I’ve written above, one is for the Status collection which I use at the backend to force a logout to all users when I need to take the Backend server down or make a specific feature “temporarily unavailable” due to some severe errors in it. A method unfortunately won’t help.

I need to figure out which part of my code base is only called during startup.

The problem with this .subscription function is that the first line:

const userId = Meteor.userId();

is reactive. Unfortunately this part is called when the user is inactive too long and the network connection is closed. Which then leads to the:

Error: You can't use reactive data sources like Session inside the .subscriptions method!

error and makes the whole app unresponsive.

You don’t need a (new) publication nor a method for this. You can logout all users by deleting all login tokens from the server. Since the meteor user account is already reactive, they will be automatically logged out once you removed the login tokens

Can’t you use the browser lifecycle to handle this automatically? The browser knows if the user is active, passive, or using another app, etc.

This is what I do to kick out all users when the Backend server has to go down:

// set empty array in order to log out all userId sessions
        Meteor.users.update(
            { _id: userId },
            { $set: { 'services.resume.loginTokens': [], 'status.online': false } },
        );

I assume this is what you meant.

It doesn’t address the other use cases of the Status collection though

Sorry RJ, I don’t know anything about this but it sounds intriguing. Could you point me to some more information or elaborate a bit more on it?

What I have done in the meantime is call

AccountsTemplates.logout();

immediately. It used to be

FlowRouter.go('/logout');

which didn’t work.

No, that was not. What you are doing is something like this:

Update status in server → status updated in client forcing a client logout → delete specific client login tokens in server

Why not just delete ALL the login tokens in server which will logout all clients? Same result without the need of the status publication

This was the one that I missed. In our app, we have a single hash value in a settings collection which is updated whenever a setting or a feature toggle has been updated. When an update happens, the single hash value is updated which is published to all clients. Then an update to that single hash value triggers a method call to fetch either the settings or the feature toggles.

Similar to @minhna above, we have a component dedicated for this at the very root of our App structure. The only re-rendering that will happen to that component is if a new hash is published from the server.

1 Like

I’m surprised that this hasn’t been suggested yet:

// client/main.js
Meteor.startup(() => Meteor.subscribe('system-status'));

That seems to be the most direct answer to the question, but maybe this practice is frowned upon these days. If that’s true, can anyone explain why?

I think yours is great suggession.

How do you organize your code? How can you extract the value from the subscription to be used on your components? How do you manage changes on those values?

For us, using React, it will most likely be inside a component.

In my case the changes to those two subscriptions are caught in an .observe, like this:

Identities.find().observe({
    changed(newDoc, oldDoc) {

Identities collection holds information on different DNA tests under one users account and is available in a drop-down in the navbar. That and other information is retrieved with a findOne.

All this is on Blaze, I can’t comment on React or Vue or any other.

Thanks for that suggestion. In my specific use case the backend is on another server and at that moment the remote connection might not be done yet (though both are in the same virtual private network in the cloud).

I will give it a try.