Wednesday, January 15, 2014

Sinatra Caches Templates

Yesterday, I learned the hard way that Sinatra caches templates when running under a non-development environment by default.

How I Found Out

My company site (Leavins-Software.com) was having serious issues where changes in layouts were not reflected in web browsers. I originally thought that this was a bug in how I set the Last-Modified HTTP header. Then I looked closely at Firefox's web console (specifically, the 'Network' tab). Last-Modified was being set properly!

I started making template changes in production to see what the real cause was. Please don't try this at home. I only did it because I'm a cheapskate working on a low-traffic site.

The test page seemed to update with every other change (which is odd behavior). Last-Modified was being updated properly, but the page wasn't changing. And then I got lucky: I was served an old version of the site with a properly-set Last-Modified date! Then a question hit me: "does Sinatra cache templates?"

Yes, Sinatra caches templates. Just not under the default development environment.

How Sinatra Caches Templates

Sinatra uses Tilt to render templates. While digging around Sinatra's source code, I discovered that Sinatra also uses Tilt's built-in caching for rendered templates. Tilt uses a Ruby Hash object for caching, meaning that Tilt's cache is per-instance.

This is different from how Rails does this. I'm not a Rails expert (I should probably change this if I want to continue working with Ruby), but I know that it uses a variety of different caching methods including page caching, and, to quote Caching with Rails, "Page caches are always stored on disk."

Each Sinatra app instance has its own cache, and I managed to hit the instance with a previously cached version of the template.

There is a Sinatra app setting named 'reload_templates' that controls caching behavior. The default setting is "true" for development and "false" for everywhere else. This is why Sinatra doesn't cache templates by default for the development environment.

Fixing Related Issues

The easiest way to resolve a template update issue is to just restart the Ruby app server. Really!

No comments:

Post a Comment