What's going on with pub/sub and withTracker?


#1

I must be nuts, because withTracker/createContainer regarding pub/sub? Here’s what I mean. In non-React pub/sub, if you subscribe to a publication that takes an argument, the client should only get what’s provided in the publication. At least, that’s how this doc sounds:
https://guide.meteor.com/data-loading.html#fetching “If you’re publishing a subset of your data, it might be tempting to simply query for all data available in a collection (i.e. Lists.find()) in order to get that subset on the client…”

It makes it sound like doing specific queries on the client is only problematic for certain reasons, as described there.

However, in withTracker, If i do an unqualified findOne(), I get a result that’s not in the publication set, because the pub subset is limited to the current user, and my findOne() returns an item for a different user:

Meteor.publish('userFeedbacks', function userFeedbacks() {
  console.log("server userFeedbacks publish")
  if (!this.userId) {
    return this.ready();
  }

  return Feedbacks.find({
    userId: this.userId
  }, {});
});

and on the client, this returns a data row for a different user (which seems wrong!).

export default FeedbackScreen = withTracker(( props ) => {
  const subHandle = Meteor.subscribe('userFeedbacks');
  const loading = !subHandle.ready();
  let dataRow;
  if ( !loading ) {
    dataRow = Feedbacks.findOne( {thingId: props.thingId} );
  }
  return {
    loading,
    dataRow: dataRow,
  };

So, why isn’t my subscription limiting the FindOne to a subset that is only for the current user?

Thanks!


#2

Client side minimongo is a cache of all records that have been sent to the client from any publication or auto publish. This means if you have any other documents from the Feedbacks collection, and you don’t filter by userId in your query, then you will possibly receive other results.


#3

Thanks for the quick reply. So if I have a publication called ‘thingFeedbacks’ that publishes all feedbacks for a given thingId, and it runs somewhere else in the app, then my subscription to ‘userFeedbacks’ will return feedbacks that were sent to the minimongo client cache by those other pub/subs elsewhere in the app?


#4

It’s not that the subscription will return it but client side queries will because it’s been added to the client side cache by another publication.


#5

There’s a good section on the subscription lifecycle in the Meteor Guide:

Also this on stopping subscriptions:


#6

That seems quite unexpected and misleading as to what the expected vs actual query results will return, that this query’s results can be so wrong due to behaviors elsewhere in the app. It also means having to pass the user id all the time to get the user-specific results.

No wonder I wasn’t getting why it was happening. Thanks for clarifying! That seems a really suspect and prone-to-errors behavior. I would’ve thought different-named publications would keep their content separate from each other.


#7

Yeah, I can see how this could be a bit confusing. It’s just helpful to think of client side collections as a data cache that will return any document that are present in the cache that match your query.

Your expectations can be achieved though a package though. https://atmospherejs.com/percolate/find-from-publication


#8

Thanks for pointing me to that!