So I deploy an existing app using Passenger for the first time and hit this:
The only Google results had to do with components and how they could result in the sweeper's after filter getting called twice which would results in a nil controller variable the second time thru. But I wasn't using components.
Finally after adding a bit of logging to show me FULL stack traces each time cache_sweeper was called I found something interesting: application.rb was being loaded twice.
I use Exception Logger in this app so I have this small bit of code in my production environment:
That set's up authentication on the LoggedException controller so not just anyone can access it in production. The problem is line #2. We're requiring application.rb since we don't have it yet this early in the stack. But then Passenger is coming along a little later and requiring it again inside preload_application.
Thankfully Passenger is using require_dependency (which checks to see if the same dependency has already been loaded via require_dependency)... so if we used require_dependency also then we'd avoid this. A diff:
Problem solved. I'll be submitting a patch on github for this as well.
But is it really Passenger's fault?
Someone tried to make the argument that this has nothing to do with Passenger. I could argue it's not my require call that breaks anything but rather Passenger's later require_dependency call - but I won't do that.
My point of view is this: It worked before for years and when I moved to Passenger it broke. From where I'm standing it doesn't really matter who is to blame. Only that the app worked in a "traditional" Rails deployment (Mongrel) and did not work with Passenger.
Regardless of who's code is at fault I think this is the type of issue Passenger has to take some of the heat for. If someone comes out with a new car with the gas and brake pedals reversed I think one could make a strong argument that the car manufacturer shares some of the blame (if not most) for wrecks resulting from people hitting the wrong pedal. It's not a perfect analogy, but we don't live in a perfect world. :-)
This post is mostly intended to help others deal with similar problems they might have moving to Passenger - not just to cast stones at Passenger.
I disagree with you when it comes to placing the blame on passenger.
You were doing something that's not standard in a Rails app: requiring application.rb. It was your call, you had your reasons to do it, and you were dealing with the impact... until you changed environments. So it's your responsibility to make sure your hack still works in the new environment.
We've had similar problems, and, just like you, our mistake was to use a plain require instead of require_dependency. It's our fault, not rails or passenger.
Posted by: Sebastian Delmont | December 03, 2008 at 10:45 AM
I'm not really saying it's 100% Passenger's fault or even that we *should* blame Passenger.
I'm just saying by virtue of making a formerly working app fail Passenger IS going to take some of the blame, whether deserved or not. These kind of things need to be better documented somewhere. It was a pain in the ass to track this issue down.
It doesn't help that the plugin's own docs recommend the approach. I've forked and updated the repository and sent pull requests to everyone though.
Posted by: Josh Goebel | December 03, 2008 at 10:48 AM
Ok, ok, I get your point... you don't need to say it three times.
And yes, you're right at saying that "passenger will be blamed" so they might want to do something about it.
Posted by: Sebastian Delmont | December 03, 2008 at 11:25 AM
Ha, it didn't add my comments and then all at once it added all of them. How weird.
Posted by: Josh Goebel | December 03, 2008 at 11:33 AM
See that's where you're wrong. Passenger provides a new and efficient way of using rails. You're under no requirement to use passenger, you can keep using Mongrel clusters forever if it suits you.
Your car analogy is not a good one. Because having the pedal on the right side could be compared to a configuration, the default is for Australia to have the accelerator on the right and break on the left, with the clutch even further to the left if you're in manual. This may be different in other countries but that can hardly be blamed on the manufacturer. Just as you drive on the right side of the road in the US and we drive on the left, it's not wrong, it's just the way you're used to.
A better way of looking at it might be switching from a manual to an automatic (or vice versa). When you hop in that Automatic for the first time you try and press down on the clutch, which isn't there. Likewise if you switch from a automatic to a manual you're likely to crunch the gears a couple of times when you forget to use the clutch.
If you'd developed that application using passenger in the first place then you would have realised during the development process that that doesn't work properly. It's not wrong it's just different. Compromises have had to be made to get the result of an application that can't have the mongrel instances die and not come back.
You're in an automatic now, and some of the things you liked about manuals (stick shifts?) just aren't there anymore. Passenger is opinionated, just like Rails.
Posted by: Luke Chadwick | December 14, 2008 at 08:11 PM