SRC10 – De-normalising rails applications

Presented by: Daniel Lucraft & Matt Wynne

De-normalisation is just one of many strategies to cope with the scaling requirements of an application. It is the process of devising a method to group relevant data together in an optimal way for the system to return what is required quickly.

During the talk Daniel and Matt explained how Songkick has devised a series of classes to implement a de-normalisation strategy using a key value store in a document based database (MongoDB).

They use the Model View Presenter (MVP Presenter first) design pattern to serve up content for the views on the website. Presenters are first class domain objects tailored for displaying a single page or module of information. So when looking at information on the site you are actually seeing content returned from a document store through the Presenter.

This however presents it’s own bunch of problems. The first and probably most obvious is consistency. Unlike caching, content is not expired and then re-generated on demand, content will be regenerated as and when it is created or updated.

Presenter, Soli and Silovator

A presenter is basically a model which has methods to get only the data required for the view element and store these in the specific document. A typical presenter looks like this:

class EventListingPresenter

  def initialize(event)
    @event = event
  end

  def title;            @event.artists.map(&:name).to_sentance;   end
  def image_count;      @event.images.count;                      end
  def attendance_count; @event.attending_users.count;             end

  #silo creates document on save using silo methods

  silo_method :title
  silo_method :image_count
  silo_method :attendance_count

ends

The silo_method works in a similar way to memoization. Data will attempt to return from the document store and failover to using the actual database through ActiveRecord.

Cache control

Cache expiration is controlled through asynchronous observers called Silovators. These silovators listen for events like create, update and delete on objects and run processes to generate the presenter data for any given presenter. For example:

class EventListingSilovator < AsyncObserver

  listen :create, Attendance do
    Silo.generate(presenter_for(attendance.event))
  end

  listen :update, Venue do
    venue.events.each do |event|
      Silo.generate(presenter_for(event.venue))
    end
  end
end

The silovator processes could be running on any number of machines, which creates another problem with possible race conditions. This is solved using http://github.com/songkick/mega_mutex which will ensure when a job is picked up, no other client will run that job at the same time. Megamutex uses memcache-client so your environment must be setup to use it.

Songkick have multiple background tasks which consume events and perform actions, these include ImageResizer, EmailNotifier and Silovater which all take advantage of mega_mutex to guarantee consistency.

Resources

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • StumbleUpon
  • Twitter

About Danny

Primarily a Ruby On Rails developer, but I can do other cool stuff too.
This entry was posted in Conferences, Development, Ruby / Rails, SRC10. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>