Reactivity stops after a while


#1

For prototyping reasons, I want to implement a kind of “newsticker” on the homepage of my app. The homepage shall always show the 3 latest news.

To fake this, I’ve implemented a Meteor.method that fills a ticker collection in cyclic interval, i.e. it inserts a fake ticker message to the news collection every 5-10 seconds. This works, and I can see the collection inserts on my console log and in the collection itself.

I then created a publication like this:

Meteor.publish('latestNews', function() {
  var cursor = news.find({ 
    $query: {},
    $orderby: {
      updatedAt: -1
    }
   }, {
    limit: 3
  });
  return cursor;
});

In the client template, I’ve subscribed to this like this:

Template.home.onCreated(function() {
  var instance = this;
  instance.autorun(function() {
    var subscription = instance.subscribe('latestNews');
    if (subscription.ready()) {

    }
  });
});

and in a helper I call a find on the news collection to actually retrieve the documents.

   latestNews: function() {
    var latestNews = news.find({}, {
      sort: {
        updatedAt: -1
      },
      limit: 3
    });
    return latestNews;
  }

According to this screencast, the publication should be reactive because cursors are automatically observed.

In principle, this works, my ticker updates and shows the 3 most recent entries for a while. But suddenly, it stops and isn’t updated anymore. The same happens if a hot code reload takes place. As soon as I restart the server, the ticker is working again, until it stops again after a while.

So I am wondering what is causing the reactivity to stop after a while? Did I miss something?


#2

Is this the complete code? Is there actually anything within

if (subscription.ready()) {

}

Otherwise, could you try without the autorun:

Template.home.onCreated(function() {
  this.subscribe('latestNews');
});

because it would actually not be needed since the subscription itself does not depend on any other reactive source.


#3

Yes, I put the empty subscription.ready() there, because I read it is a reactive source.


#4

So when the subscription become ready() it rerun whole autorun, resubscribing and waiting for another ready() which than trigger autorun re-run so it re-subscribe and wait for ready() which…

like that ? :smiley:


#5

Well, it was just a desperate try to make it work :smile:

I’m actually not sure how to set things up if you’re only interested in getting the latest 3 items of a collection (just like a log tail). Yes, I assumed it would work even without the auto-run (since the find() cursor in the helper is already reactive), but it didn’t work. So I experimented a bit…


#6

btw what is that $orderby and $query in publication?
selector is first argument in Meteor
and limit and sort also have it’s own place in Meteor
just consult documentation

both news.find should be exactly the same on server and client side for your usecase
and the client side was the right one :smiley:

good luck


#7

If I use the client side query on the server, the ticker does not work at all. Maybe in this case the limit is applied before the sorting, so it always returns the same elements? Only if I use the query syntax above (which I got from the MongoDB documentation), it worked. But on client side, this enhanced syntax is not supported, so I took the standard Meteor syntax instead. Which should not make a difference, since the server already filters the result set, so the client “just” has to make sure it is also sorted correctly.

I now tried to remove the autorun. It worked, but also only for some minutes. After that time, the reactivity stopped again, and I have no clue why. Maybe it is because I do the inserts wrong on the server side? I’m using Meteor.timeout() to run a cyclic job and insert new fake elements. But I’m not sure if there’s a better way to do this.

EDIT: Tried the client side syntax again on the server side. With the same result as before: The subscription runs correctly until the “limit” is reached. From then on, no new documents will be pushed to the client. Obviously, the “limit” takes precendence over the sorting - and thus always returns the same 3 elements.


#8

wrong assumption, well I dont have time to test it now :smiley:


#9

Here’s StackOverflow discussion on how to retrieve the N latest documents:

Some of the solutions there seem to be wrong to me (since they limit first, and then sort the result), but they’re all not just using the normal “sort” option.

The “chained” syntax does not seem to work with Meteor:

  var cursor = news.find().sort({
    updatedAt: -1
  }).limit(limit);

so I used the $query, $orderby syntax. This at least worked with Meteor’s find(). And it looked better IMHO, since it would not process the whole collection (like the chained versions imply).


#10

and is the updatedAt really in database in correct format so it can sort based on it ?

and also there could be issue with your templates somewhere…
hard to comment without these info.

still I never had problem with sorting and using same form on server and client 99%.


#11

Oops, this might be the problem, I’ll try out.


#12

Ok, I think you got it right. The problem was the “updatedAt”. It was not present on all items. I’m so dumb. :-/ Thanks for your help!

BTW: Now also the client-side query works on the server side… :slight_smile:


#13

It was always working there :smiley: