App constantly refreshing after an update

But surely, this is a pretty new issue. As of 1.3, or around there - right?

Yup. Pretty it’s sure 1.3 and on, but you can check the thread if anyone
has had the issue with 1.2

We do not see it, is there any kind of reproduction? Any idea of maybe which packages might influence this?

After much frustration, I might have found a solution. In Kadira I saw that “meteor_autoupdate_clientVersions” was call the most frequent. Autoupdate is responsible for: “When it sees that a new version is available, it uses the reload package (if included in the app) to gracefully save the app’s state and reload it in place.”

When I disabled the Hot Code Push (HCP) on the client side Meteor._reload.onMigrate(function() {return [false];}); by overwriting the reload function, the problem seems to be solved.

Not really sure what triggers the HCP on our production server. But it seems to be a client issue. Can’t spot any errors w.r.t. console / http/s / ssl etc…

Initially the reload.js was spotted in the Network tab of the console:

2 Likes

So assuming this fixes things. Does this mean the app will only update each
time the client comes to the site a new or refreshes themselves?

Yes. But for a production app I don’t think that is a problem

Great find! Works great for me, :smiley: thanks a lot!

So the question here is, what changes in 1.3 that caused this to be an issue?

I seem to be able to get around the refresh by adding a random query string value (which defeats cache). So far, I have done it only manually assuming but will likely roll out this change to prod. For me, so far it’s only happening on the sign-in page so I should be able to change the links to sign-in to something like sign-in?rn=

Any updates on this? This is very easily reproducible on my production server. I am happy to sit with anyone from the Meteor team to walk them through the issue, on VC or in-person (I am in the Bay area).

It’s making the app unusable for repeat visitors.

1 Like

Unfortunately - this didn’t work for me. I think disabling caching in Nginx is working but I can’t full test it until the previous 30d cache expires

I can confirm that

if ($uri != '/') {
    expires 30d;
}

caused infinite refreshes for some users of my app recently.

As posted above. This is helpful:


I seemed to have missed it when it was first posted.

I am facing the endless reload problem too but it is a fresh deployment, not an update. First I had the problem when adding the nginx proxy on my development machine, and fixed it by removing the caching block. Now I am using the exact same nginx config/version and it keeps reloading.

It seems to not be triggered by the caching as even with chrome’s console open with ‘Disable cache’ on it keeps refreshing (while it used to stop it on the development machine)

I do not know where to turn now as I don’t see any error anywhere… I thought that maybe it could be a websocket problem or something but the only thing that changes between development and production is that the application is bundled.

Do you have ssl setup? Force ssl package can cause issues like this.

Also the app cache package can cause this issue.

Try running it without nginx and see if you have the issue.

I’m on Meteor 1.3.5.1 and for a long time I’ve ran my production deployment with just MUP without issues. I had a requirement to add SSL to my site so over the weekend I added nginx and SSL (never had Force SSL installed). The app almost immediately starting reloading constantly. I read the issue was solved by removing caching from the config file.

if ($uri != '/') {
  expires 30d;
}

That worked. But I noticed while debugging another issue, at least one of my tracker methods that uses Meteor.userId() and a few Session variables is constantly triggering when I don’t think it should (I never noticed this before). Is there a way to find out, when one has a few Session variables inside a Tracker method, what exactly is triggering it to run?

I have not setup SSL yet.

There is no meteor package named app cache or something similar on my application.

I’ve tried running the application directly by exposing its port and the result is the same.

@aadams I had removed that part already on a previous installation, never had those lines on this install.

Actually, I feel a bit dumb… We just found out that meteor-cluster’s balancer url was hardcoded instead of using the environment URL… I don’t understand why this package would want to keep refreshing like that though, but setting the correct URL fixed the problem for us.

I experienced this issue with my new nginx config.
This thread already mentions that caching is the problem, but here’s a bit deeper explanation of this problem:

The HTML generated by Meteor contains a bit of configuration like:

__meteor_runtime_config__ = JSON.parse(decodeURIComponent("%7B%22meteorRelease%22%3A%22METEOR%401.4.2.3%22%2C%22meteorEnv%22%3A%7B%22NODE_ENV%22%3A%22development%22%2C%22TEST_METADATA%22%3A%22%7B%7D%22%7D%2C%22PUBLIC_SETTINGS%22%3A%7B%7D%2C%22ROOT_URL%22%3A%22https%3A%2F%2Fdev.barco.com%22%2C%22ROOT_URL_PATH_PREFIX%22%3A%22%22%2C%22appId%22%3A%221unoj8hnpdlfkilwye6%22%2C%22accountsConfigCalled%22%3Atrue%2C%22autoupdateVersion%22%3A%221f075a5d589e6b6752ec729586668b1fd79c0e4c%22%2C%22autoupdateVersionRefreshable%22%3A%22d4603c0cf7592ed19eabd2b57718ab72ab3a81cf%22%2C%22autoupdateVersionCordova%22%3A%22none%22%7D"));

Parsed this contains the current version of the client-bundle version (autoUpdateVersion).
The autoupdate package has a subscription to a publication that publishes new version hashes. If the hash it receives doesn’t match with the one in autoUpdateVersion, the autoupdate package asks the reload package to reload the page.

If the html has cache-headers, it will be loaded again from disk, so with the old configuration data (and therefore version info) and it will instantly reload.

Therefore removing cache-headers from your nginx like:

if ($uri != '/') {
    expires 30d;
}

Helps, but it throws the baby out with the bathwater.
@abernix Couldn’t Meteor set the ETag on this html to the autoupdate version?

2 Likes

An ETag could be added, yes, and I’d be willing to review a PR for it, but there’s a caveat.

While the ETag on the HTML “boilerplate” (as it’s referred to) could potentially avoid you having to make an exception like you’ve done, it’s not fair to say that it “throws the baby out with the bathwater” because ultimately the resources that Nginx would cache based on the ETag header still need to be verified on every request with the Meteor app (via a If-Modified-Since header on a GET request) to make sure they haven’t changed (for example, if you’ve updated your app). Meteor would still have to generate the boilerplate to determine if the content was different and respond with a 304 Not Modified response code if it was the same.

Granted, you could force it to only revalidate every so often, you are not really going to see a cache benefit from this process as Meteor is very, very quick at serving the boilerplate, with upwards of 1200 requests per second served in less than 100ms (these numbers are based on testing 5000 requests at a concurrency of 15). Additionally, considering the fact that Meteor supports features such as dynamicHead, those variables would have to be considered as well as it would affect the ETag value.

Ultimately, I think using an ETag on the boilerplate might break more than it would solve.

Yes, you’d still get a request on the server, but it would prevent Meteor having to send the boilerplate to the client.
Furthermore, you could let nginx cache the boilerplate, at least with proxy_cache_revalidate on, which would still have a lot more throughput. But I didn’t know the performance metrix you mentioned, so maybe the gains are not as big as I intuitively thought.