Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FilePathCache throws exceptions almost every release #191

Open
rodmcnew opened this issue Jun 2, 2016 · 13 comments
Open

FilePathCache throws exceptions almost every release #191

rodmcnew opened this issue Jun 2, 2016 · 13 comments

Comments

@rodmcnew
Copy link

rodmcnew commented Jun 2, 2016

Almost every time we release we get errors from the following line for random css and js files.
https://github.com/RWOverdijk/AssetManager/blob/master/src/AssetManager/Cache/FilePathCache.php#L94

I believe this happens because more than one person is asking for the same file at the same time. Perhaps two php threads are trying to write the same file at the same time.

I had to change it to this in our local version to prevent errors in our logs every release:

        if (@file_put_contents($tmpFilePath, $value, LOCK_EX) === false) {
            //THIS IS THE MODIFICATION THAT PREVENTS ERRORS DURING RELEASES
            return;
//            throw new RuntimeException('Unable to write file ' . $this->cachedFile());
        }
@RWOverdijk
Copy link
Owner

@rodmcnew You're right when guessing it's because you're trying to access the same file. This was done to make sure you don't accidentally corrupt a file. This should not happen a lot, unless you deploy to high-traffic active nodes. Perhaps then they want to write to files you just locked for your release.

@rodmcnew
Copy link
Author

rodmcnew commented Jun 3, 2016

Our release process doesn't do anything strange like locking files. I believe the only effect our releases have is that they delete the asset manager file cache. We get errors in our logs from this during at least 50% of releases. Its hard to image that anything else is the issue other than 2 threads writing the same file at the same time.

One solution could be to change this

$tmpFilePath = $cacheDir . '/AssetManagerFilePathCache_' . $fileName;

To something like:

$tmpFilePath = $cacheDir . '/AssetManagerFilePathCache_' . rand(0, 1000000000) . '_' . $fileName;

I'm going to try this on our local copy for a while and see if it makes the errors go away.

@RWOverdijk
Copy link
Owner

That's what I said, if you clear the cache on an active node (meaning, with traffic), and don't have 1 process warming it up somewhere offline, you might get errors. I still think that's appropriate behavior.

This is just a guess obviously, I don't know how / where you guys do releases.

@rodmcnew
Copy link
Author

rodmcnew commented Jun 6, 2016

In my opinion, there is no point in having a cache if it has to be pre-warmed offline. That sounds more like a build process than a cache.

I would guess that at least 80% developers are not going to have a complex release process that does offline cache pre-warming, especially in the PHP world.

@RWOverdijk
Copy link
Owner

@rodmcnew I doubt it, too. But if you're going to resolve assets using php on high traffic sites, you really should. If two or more people try to access the exact same resource at the exact same time, and it's not there yet, it's going to break stuff. I'd suggest to either host assets statically, or implement a warm-up strategy.

The caching makes sense. The only alternative I see, is listening for exceptions and retrying the result (maybe redirect to self) when you catch one, to keep retrying until it works. This is icky though. Another solution (if you don't want to go static) is to use varnish. Varnish is amazing at this, but renders the caching mechanism useless (as it gives you a whole new level of control).

@rodmcnew
Copy link
Author

Thanks. I believe adding randomness to the $tmpFilePath as in the above comment will fix the issue in a simple manner. I did this 10 days ago and haven't seen any exceptions since. If I don't get any exceptions in a month and I still remember, I will PR it.

@RWOverdijk
Copy link
Owner

@rodmcnew If this solves it for you, I see no problem in merging that. It won't hurt others. :)

@wshafer
Copy link
Contributor

wshafer commented Aug 6, 2016

@rodmcnew Funny to see this error. I put that lock in to fix your release problems. Glad you found another fix to fix the new issue.

@rodmcnew
Copy link
Author

rodmcnew commented Aug 8, 2016

@wshafer I have found that adding randomness to $tmpFilePath as I suggested has not eliminated this issue. We now get errors from "!is_writable($cacheDir)" during releases. I'm not sure what causes it though. Our release process looks like the following. PHP is stopped while files are being moved around. This happens to at least one file in about 20% of our releases.

service php5-fpm stop
mv /www/app/current /www/app/current.bak
mv /www/app/deploying-temp /www/app/current
service php5-fpm start

Example message from the "!is_writable($cacheDir)" line:

Unable to write file /www/app/current/config/autoload/../../public/modules/checkout/directive/preview-totals/preview-totals.html

@wshafer
Copy link
Contributor

wshafer commented Jul 26, 2017

One thing I've always disliked is throwing exception on cache misses. Would anyone object to caches failing silently? Or perhaps only failing if a debug flag is set?

My issue here is that there is absolutely nothing wrong with the asset itself. I feel like we should show the user the valid asset unless told otherwise.

incidentally, when I first put the PR in to do this that's what I was doing. And as you'd expect we didn't see the error @rodmcnew is seeing now.

Thoughts?

@RWOverdijk @rodmcnew @Ocramius

@RWOverdijk
Copy link
Owner

@wshafer I think the idea behind it is that you get to decide what happens yourself. If you don't want to throw exceptions, you catch them and ignore them. Others might want to catch them and do something else. Throwing them provides the most flexibility.

@wshafer
Copy link
Contributor

wshafer commented Jul 28, 2017

I get that except you can't catch these. You'd have to extend the Service Manager yourself and override the set cache and put your version in place of the main service.

I guess you could replace the eror handler to catch it but you don't have the assets in the exception to pass it through.

To keep the mind set and so errors don't have to go unnoticed, what if we made the exceptions a config option on the cache? Maybe a flag on the caches like 'ignoreErrors' like Monolog?

@RWOverdijk
Copy link
Owner

RWOverdijk commented Jul 31, 2017

Update on record (based on our gitter conversation) we'll be skipping this for now.

@wshafer

PS. No fix for the cache issue we talked about earlier. No way to distinguish a cache exception from an asset exception. Gonna drop it for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants