blog.eliotsykes.com

Icon

Why Rails asset caching is broken in your app and how you can fix it

Rails Asset Fingerprint Plugin

Ruby on Rails’ helper methods (image_tag etc.) that generate URLs to assets (assets are static resources like stylesheet, image, and javascript files) use the broken caching strategy of timestamped query strings, which fails to provide desirable caching behaviour. The new Asset Fingerprint plugin fixes this problem by making it easy to use a file name fingerprint solution (recommended by Google) to improve the cacheability of your app.

Why using the query string is a bad idea

From Google’s advice on leveraging proxy caching:

Most proxies, most notably Squid up through version 3.0, do not cache resources with a “?” in their URL even if a Cache-control: public header is present in the response. To enable proxy caching for these resources, remove query strings from references to static resources, and instead encode the parameters into the file names themselves.

Google uses the term “fingerprinting” to describe putting parameters in a file name to identify a unique version of that file.

Why using file timestamps is a bad idea

File timestamps are not recommended as resource fingerprints as these are often inconsistent between deployments when a file has not changed. This means your app may not take full advantage of asset caching. Reasons for timestamp inconsistency include:

  • multiple app servers checking out files from code repo at different times
  • git does not preserve file timestamps (it really doesn’t)
  • subversion not configured to preserve file timestamps
  • generated asset files (e.g. compressed css/js bundles)

A hash function checksum (e.g. MD5 checksum) of an asset file’s contents can be used to give a more reliable file fingerprint.

What the Asset Fingerprint plugin does out-of-the-box

Easiest to illustrate what the plugin does by example: say there’s an image in your app located at public/images/logo.png, the Asset Fingerprint plugin will modify Rails’ helper methods to generate asset file paths like ‘/images/logo-fp-1749689fc4ba35c5bb1a4d1a8ef903e3.png’.

The ‘-fp-’ part of the path is a fixed string used to help identify fingerprinted paths and the ’1749689fc4ba35c5bb1a4d1a8ef903e3′ part is the fingerprint of the logo.png file, which is the MD5 checksum of the logo.png file. The fingerprints are calculated once and cached for performance (like Rails does already with the file timestamps).

By default, the plugin will create symlinks on-the-fly to ensure the fingerprinted asset paths are valid and serve the expected resource. You can configure this behaviour to have symlinks generated by a rake task instead (normally run during deployment) or you can use server rewrite rules if you prefer – the plugin’s README explains this and provides examples.

What else the Asset Fingerprint plugin can do

You can configure the plugin in a single line to use timestamps as fingerprints if you prefer, or you could write a SHA-2 FingerPrinter if you have a problem with MD5.

If you have an urge to put the fingerprint in the query string (as Rails does by default) that is a single line of configuration.

Who uses the plugin?

At time of writing Asset Fingerprint is used in production for MissedConnections.com.

How to get the plugin?

You can find source and in-depth details of the Asset Fingerprint plugin, including installation and customization instructions on Github.

TLTR summary Rails’ timestamped query string asset caching is broken. Install the Asset Fingerprint plugin in your app to fix it and improve the cacheability of your app.

Photo source

Spring Custom Scopes: Site Scope HOWTO

Ok, so I’ve finally got round to putting some sample code together on Site Scope with Spring Custom Scopes. I’ve been wanting to do this for some time… Sample code on Github

What does Site Scope do?

Say you are running a multi-tenant web app. E.g. you have one video rental webapp that runs 3 different web sites: netflix.com, blockbuster.com, and betamaxrules.com.  For each site you sometimes want to use different beans in your spring application context.

Say for Netflix you want the page titles to be formatted with a “- Netflix” suffix, and for Blockbuster you want the page titles to be formatted with a “Blockbuster presents: ” prefix.

To solve this you can create a TitleFormatter class, and create two subclasses of it, NetflixTitleFormatter and BlockbusterTitleFormatter (I’d normally make a more flexible TitleFormatter with prefix and suffix attributes rather than subclassing, but subclassing simplifies the example).

Your app determines the current site by the domain name (or some other request/session attribute if you prefer) and our Site Scope uses the correct TitleFormatter bean for the site.

Site Scope prevents site.isXxx() code smells in your views. If you have a lot of tenants, you can end up with views looking like this:

if (site.isNetflix())
  pageTitle + " - Netflix"
else if (site.isBlockbuster())
  "Blockbuster presents: " + pageTitle
else if (site.isBetamaxRules())
  pageTitle
else if (site.isVhsOldSchoolRentals())
 "VHS Old School Rentals have static titles"

With SiteScope this could be replaced with:

  titleFormatter.format(pageTitle)

For the sample code source/HOWTO see spring-site-scope on github.

Are you going to use Site Scope? What are you going to use it for? Please share in the comments.

What tech is Chatroulette running on?

Chatroulette circa 1910

Chatroulette circa 1910

The programmer in me has been wondering what technology Chatroulette is running on and this is what I’ve found out – those who know better please forgive mistakes and correct me in the comments:

  • Connections between users are P2P (i.e. my computer connects directly to yours)
  • These P2P connections are established using Adobe’s free experimental Stratus service
  • Using P2P connections massively reduces the bandwidth costs to Chatroulette as the majority of the traffic is between the chatter’s computers
  • The application is written in Flex/Flash (I’m not sure of the distinction)

The Adobe forum has this post about recent performance problems with their hosted Stratus service, it hints that they may be hosting Chatroulette.

Chatroulette clones

Update 20th April 2010 Well this post has been getting swamped with comments listing more clones than I ever expected so I’ve turned commenting off, the list below is not comprehensive but well, all you need to know is that there is a lot of Chatroulette-like sites out there.

Partly as a result of the Chatroulette Missed Connections site, and partly because it is fascinating to see an Internet phenomenon like Chatroulette unfold, I’m taking an interest in all things related to it.  I love how Andrey, the man responsible for Chatroulette, has created this just by doing something he loves.

So a couple weeks ago I saw ads on freelancer sites looking for developers to clone Chatroulette.  Looks like these ads found some willing developers as these clones are starting to crop up every day.

Here’s the Chatroulette clone list so far, in no particular order:

If you hear of more let me know and I’ll add them to the list. Remember though, if you’re thinking of visiting one of these sites, Chatroulette will always be the original success story for this type of web site, and if you think cloning it is a good idea, may I politely suggest that building an idea that is original and needed might be more rewarding – copy Andrey’s passion, not his idea.

New Rails Page Cache plugin: for holeless/seamless page caching

For Missed Connections the sitemap and home page are cached on the filesystem and only refreshed periodically, after an event is fired in the app to say that missed connection ads have been created or deleted.

To make users lives a little easier, I never wanted them to make the request that generated one of these cached pages.  This isn’t quite how Rails page caching works out of the box.  Instead I wanted the page cache to be primed during deployment and periodically updated by a rake-task-calling cron job.

In Rails, out of the box, if a cached page is expired, it is deleted from the filesystem and is only generated when a new request comes in for that page.  This means the first person (could be more than one person if you get concurrent requests) to request the expired page will have to wait for it to be generated.

Instead, to save users’ time, I wanted the cache to be “holeless” (inspired by the Pivotal Labs post Rails, Slashdotted: no problem). To do this there is a cron job that generates new cached pages, and then replaces the old cached pages with these new cached pages.

In other words, the expired cached pages are only deleted after a refreshed version of the same page is available on the filesystem.

The first version of the plugin and README details are available at Github: Page Cache Rails Plugin

Turn off Google Buzz HOWTO

Turn off Google Buzz

Disabling Google Buzz is easy:

  1. Log in to Google Mail
  2. Scroll to the bottom of the page
  3. Click the “turn off buzz” link as highlighted in the picture above, its nested between the “turn on chat” and “older version” links

Bonus! 10 geek points if you can tell from the screen grab above which Google Mail theme I’m using.

Using Prototype to load Facebook API on demand (or any other script)

I was trying to figure out how to get PrototypeJS to load the Facebook JavaScript API on demand.

For Missed Connections I’m writing a modal box that can optionally display a Facebook connect button, but I didn’t want to load the Facebook API unless the Fb connect button is shown.

In the end I wrote FacebookApiLoader to do this, you can find the source and details here:

http://stackoverflow.com/questions/2117691/using-prototype-to-load-a-javascript-file-from-another-domain/2123219

Many thanks to Thomas’s answer which pointed me in the right direction.

Freecycle alternatives for UK

Early last Summer I used SnaffleUp to freecycle some dvd cases and jiffy bags, but then I couldn’t remember its name when I wanted to get rid of an old artificial Xmas tree last month.

Next I tried Gumtree’s London free section but that didn’t work out so well (I’m guessing its normally better), so in the end the tree went to the Salvation Army.

Anyway, I guess in December I had a problem with my brain and couldn’t figure out the simple task of searching through my old e-mails to remind me of SnaffleUp’s name. So what I’m doing here as a memory aid and to help others is listing the alternatives to Freecycle for the UK that I’ve found, comment below if you’ve found any others or have some feedback on the services:

Tried (rating)

  • SnaffleUp (5 out of 5)
  • Gumtree (3 out of 5)
  • Freecycle Yahoo Groups (2 out of 5 – low rating because if memory serves you’re forced to join a mailing list through Yahoo Groups – I’ve found a dedicated web site like SnaffleUp is easier for freecycling)

Not tried

  • Freegle – set up by massive breakaway group of UK Freecycle users who weren’t impressed with how Freecyle was being run. Nice looking web site but still uses Yahoo Groups and mailing lists by the looks of things.
  • Recycle

Sprixi – New way to find free images for your blog

sprixi

Here’s an alternative and easier way to Flickr Advanced Search for finding free images for your blog:

http://www.sprixi.com/

Thanks to The Next Web for the article that made me aware of Sprixi

Alcohol Free Christmas Pudding Recipes

christmas-pudding-alcohol-free

Its a few days before Christmas and I feel like making an alcohol free Christmas pudding, here are links to 3 recipes, none of which I’ve tried:

Hopefully collecting these recipes in one place will help someone else out.  If you find any other recipes add a comment and I’ll add the links above.

I’m planning on using the first recipe as the quantities seem to be small enough for making a single good-sized pudding – the second and third recipes are for making a few puddings.

Who’s Blog?



Hello, I’m Eliot Sykes and this is my blog. Thank you for visiting. I'm the Founder of MissedConnections.com


Read about my current projects, contact me or find me on github