Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Tools
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Monthly Archives: May 2009

Pivotal Labs

Railsconf: HTTP's Best-Kept Secret: Caching – Ryan Tomayko (Heroku)

Pivotal Labs
Thursday, May 7, 2009

HTTP’s Best-Kept Secret: Caching Ryan Tomayko (Heroku)

About Ryan

  • http://tomayko.com
  • Sinatra maintainer.
  • Rack core team.
  • Creator and maintainer of Rack::Cache.

Http Caching?

  • NOT Rails Caching
  • HTTP caching headers in requests: Cache-control: If-Modified-Since: If-None-Match:
  • and responses: Cache-control: Last-Modified: ETag: Vary:
  • This stuff is defined in RFC2616, we won’t be going into this that deeply.

Types of Cache

Client cache

  • Built into browsers and other types of client.
  • 1:1 relationship between cache and client. The cache only serves one client (private cache).
  • How much bandwidth does each cache save: can’t beat it.

Shared Proxy Cache

  • Setup for an organization
  • 1:many relationship between cache and clients. Serves more than one client (shared cache).
  • Is closer to the client than the server, therefore saves a lot of bandwidth.

Gateway Cache

  • a.k.a. Reverse Proxy Cache
  • Situated inside of the origin site
  • 1:everyone relationship between cache and clients.
  • Reduces bandwidth the least.

Why cache?

  • The answer to this has changed over time.
  • In Nov 1990 there was 1 guy on the web – Tim Berners-Lee.
  • In Feb 1996 the web population was 20M. State of the art connectivity was a 28.8kbps modem. At that speed, loading the current http://yahoo.com (~350k) would take 2:48s. Bandwidth was the largest issue. RFC1945 HTTP 1.0 included the Expires: and Last-Modified: headers.
  • In March 1999 RFC2616 HTTP 1.1 was released. Addressed 1996 caching problems.
  • Today: we cache so we can scale. Keep your back-ends free from as much work as possible. Push as much work up the stack as possible.

HTTP 1.1 defines 2 caching models

Expiration

  • Back-end sets Cache-Control: public, max-age: 60
  • Gets cached in gateway cache an browser cache.
  • Public says it is good for many clients.
  • Cached for 60s.

Rails example

def show
  expires_in 60.seconds, :public -> true
  # stuff
  render ...
end

Sinatra example

headers['Cache-Control'] = 'public, max-age=60'

Validation (Conditional GET)

  • Back-end adds ETag or Last-modified, e.g. ETag: abcdef012345
  • Last-modified is redundant, basically there for HTTP 1.0 clients.
  • On 2nd request, gateway cache realizes it has this page in cache, then sends a GET /foo, Host: foo.com, If-None-Match: abcdef012345 to the back-end.
  • If back-end returns a 304 Not Modified, gateway cache returns cached version.

Rails example:

def show
  @foo = Foo.find(params[:id])
  fresh_when :etag => @foo,
  :last_modfied => @foo.updated_at.utc

Alternative idiom:

def show
  @foo = Foo.find(params[:id])
  modified = @foo.updated_at.utc
  if stale?(:etac => @foo, :last_modifed => modified)
    respond_to ...

Sinatra example:

get '/foo' do
  @foo = Foo.find(paramsp:id])
  etag @foo.etag
  erb :foo
end

Combine Expiration & Validation

  • Back-end sets Cache-control: public, max=age=60 and ETag: abcdef012345
  • In < 60 seconds, cache-control takes precedence
  • After 60 seconds, it queries back-end using ETag
  • Back end can then send back a 304 not modified with a new Cache-control: public, max-age: 60

Misc

  • Never Generate the Same Response Twice

Recommend using Rack:cache

gem install rack-cache

config.middlware.use Rack::Cache,
  :verbose          => true,
  :metatstore       => "fie:/var./cahe/rack/meta",
  :entitystore      => "file var/cache/rack/body",
  :allow_reload     => false,
  :allow_revalidate => false

The client controls what happens at the cache as well as the server using Cache-control. Refresh send Cache-control: no-cache. No-cache means gateway cache MUST revalidate ETag before sending response. This is bad and people can pound your back-end. :allow_reload => false disables this.

  • High-Performance Caches: Squid, Varnish (Heroku uses this)
  • Interesting discussion about ESI at the end.
  • Rails by default uses id of model, classname and last_updated to create an MD5 hash for etag.
  • Need to start with a seed that covers your release version, otherwise etag will not change. Rails now has a mechanism to handle this.
  • 2.3 branch has a new “touch” mechanism too.
  • Browser behavior differs and varies quite significantly when using SSL.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

RailsConf: Art of the Ruby Proxy for Scale, Performance, and Monitoring – Ilya Grigorik (AideRSS Inc.)

Pivotal Labs
Thursday, May 7, 2009

Slides are online already

Random nuggets from the talk:

The overhead of most requests is calls out of a framework to a DB, FS etc, but because it is called from the framework, that is what gets the blame. This sustains the myth that “<insert your framework of choice> doesn’t scale”. Solution: put a proxy in front of the server and duplicate the server behind it.

Types of proxy:

  • Transparent
  • Intercepting
  • Caching
  • …

Transparent Cut-Through Proxy = 90% use case

  • Transparent Proxy – user cannot detect he is behind a proxy
  • Cut-Through – forwards on the fly (not store and forward)

The Problem

Flaws of Staging environments:

  • Any change in profile of queries invalidates your testing
  • Cost

The Solution

  • What if you could take your production traffic and fork it to two environments

EventMachine

  • EventMachine inplements a design pattern knows as the reactor pattern
  • Will connect to any file descriptor (e.g. a socket)
  • Written in C++ for high performance and concurrency without threads
  • EM does have a native thread pool used for EM.defer
  • http://bit.ly/aiderss-eventmachine excellent PDF to document EM

EM-Proxy

  • http://github.com/igrigorik/em-proxy
  • A simple DSL for writing proxy servers.
  • The return from on_data and on_response blocks is just passed on/back.
  • If you return nil from a block, no data gets forwarded.
  • 5% performance hit for large messages
  • 20% perforamnce hit if messages are very small, mitigate by putting behind HA proxy and add another server.
  • No way to send to only 1 back-end server yet (can’t implement a load-balancing proxy).

Misc name-dropping

  • httpperf is really good for replaying traffic against a site
  • igrigorik/autoperf – replay nginx logs against your site
  • Recommended we look at MySQL proxy – awesome dashboard.
  • Nginx does really good things with compression (gzip, ETAGS etc).
  • Mailtrap is a fake SMTP server gem for testing sending email from your Rails app.
  • Defensio is a smap filter for blogs. API you can send comments to and it will tell you if it is spam or not. Returns a ‘spam index’.
  • Beanstalk is an in-memory distributed message queue. Despite frequent requests, they have not implemented persistence, which is what motivated Ilya to work around them with this proxy server.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Erector 0.6.3 – Now Ready to Conquer The World

Alex Chaffee
Wednesday, May 6, 2009

[Updated: added instructions "If you are using a widget in rails, you now need to inherit from RailsWidget"]

Erector has been around for almost 2 years now, but we’ve always been a little reluctant to market it heavily. One reason has been that the API was a little inelegant. Another is that Rails integration wasn’t as seamless as we’d like.

With today’s release of version 0.6.3, we have hopefully fixed both of those problems. With the new RailsWidget we’ve got a clean separation between core Erector functionality and the magic we need to make it work with Rails. We’ve renamed “render” to “content” so we don’t conflict with the standard Rails render method. And we’ve changed the API for smoother lifecycle management — the constructor is about initializing the widget, and the refurbished “widget” method is about setting it up to emit its HTML.

The bad news is that you’ll have to change your existing code. The good news is there’s an update guide, which you’ll find below the fold in this blog post.

Please visit our Google Group to register comments or complaints, our project web site for full documentation and FAQs, and feel free to clone or fork our GitHub repo.

(Why 0.6.3 and not 0.6.0? Because we had to work through some glitches in the new deploy process with GitHub and Jeweler and whatnot. We’re only human…)

Erector 0.6.0 Announcement

This release is the first major API change to Erector. It will definitely break
existing code. Sorry about that, but we promise it’ll be cleaner afterwards.

Quick Update Guide

  • Rename ‘def render’ to ‘def content’ in all your widgets

  • If you are using a widget in rails, you now need to inherit from
    RailsWidget to get helper goodness

  • Change MyWidget.new(helpers, assigns, output) to just
    MyWidget.new(assigns)

  • To render a widget from inside another widget, use

    widget MyWidget, :foo=>2
    

    or

    widget MyWidget.new(:foo => 2)
    
  • If you want your variables to have attr_readers, use ‘needs’

  • If you want your widgets to be more self-documenting, use ‘needs’

Major API changes

  • “new” and “to_s” have been changed to clarify the lifecycle of a widget,
    so “new” accepts permanent state (”assigns” variables) and “to_s” accepts
    temporary, rendering state (output stream, helpers, and prettyprinting).
    This lets you do things like make collections of widgets in once place in
    your code and render them in another place.

  • Renamed “render” to “content”, which removes confusion/ambiguity with
    Rails’ “render” method and concept, and also allows “render :partial” to
    be made to work (though we’re not sure if that totally works yet).

  • To render a widget from outside code, the pattern is:

    w = DateWidget.new(:when => Time.now, :title => "Nap Time")
    puts w.to_s(:helpers => some_rails_view)
    
  • To render a widget from inside another widget:

    def content
      # first way... pass class and assigns
      widget DateWidget, :when => Time.now, :title => "Nap Time"
      # second way... pass instance
      widget DateWidget.new(:when => Time.now, :title => "Nap Time")
    end
    

    Using “widget” will improve performance over calling “raw foo.to_s” or
    whatever since it reuses the same output stream.

  • To declare variables — and raise an exception when one is not provided:

    class JohnLennon < Erector::Widget
      needs :love
    end
    
  • Formerly, every ‘assigns’ variable had an attr_reader defined for it. Now,
    only variables declared with ‘needs’ get attr_readers.

Other changes:

  • Removed Widget#to_s caching, which fixed indentation issues.

  • BUGFIX: Indentation level is now correctly propagated to nested widgets.

  • Erector’s Rails support strategy has changed. The released version of
    Erector only supports the latest stable Rails version (currently 2.3.2).
    If you need support for earlier versions of Rails, there are separate Git
    branches for each one, but we will not be in the habit of keeping these up
    to date with the latest features and patches. If someone wants to do a
    merge to a prior Rails branch, Brian will be happy to help :-)

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Railsconf: Giving Rails the Big F – Surviving Facebook Integration Unscarred, Greg Borenstein

Pivotal Labs
Wednesday, May 6, 2009

The Facebook API Menagerie

Facebook API has many different parts:

Canvas Apps

FB requests from your site, they inline the resonse in the middle of the page.

  • Not available: JavaScript.
  • Available: FBJS – a sandboxed limited JS API, FBML – a templating language, the FB session.

iFrame Apps

Your response is put in an IFRAME on the page.

  • Available: FB session.
  • Not available: FBJS, FBML.

Connect App

Host your app on your own domain.
Connect back into FB to e.g. user their authentication & friends model.

  • Available: Connect Session
  • Not available: FB Session

Pages/Profiles

  • No JS

Think of FB as a browser

FB API LOLZ

  • REST API – api/facebook.com/restserver.php – awesome URL.
  • Facebook does not do GETs, they always POST to your site.
  • Connect inside an iFrame, Connect requires the XHTML doctype to work, but iFrames are not supported in XHTML.

SRSLY

Running your App in development

  1. Create an app
  2. Setup DynDNS.com, point it at your IP address http://mysubdomain.dyndns.com
  3. open ports on your local network
  4. Add /etc/host entry: 0.0.0.0 facebook.dontexist.com

Abstract the API

  • Use Facebooker.
  • apps.facebook.com/facebooker_tutorial
  • Access everything through the session
    if session[:facebook_session]
    @friends = session[:facebook_session].user.friends.collect do |f|
    User.find_by_fb_user_id f.uid
    end

Project your code

e.g. use rack-facebook so everything is not a POST

Others

  • Frakie: Facebooker for Sinatra
  • rack-facebook: tranlates FB POST to correct action

How can I make things better?

  • Need a test harness for session[:facebook_session]. There is something in facebooker that needs extraction.
  • Greg is starting Faceboot API Continouus Integration Suite of Tests – github.com/atduskgreg/FACIST – some JS hooks to green/red light that your tags are actually showing up in the page.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Railsconf: Rails Metal, Rack and Sinatra – Adam Wiggings (Heroku)

Pivotal Labs
Wednesday, May 6, 2009

Rails Metal

  • Rails Metal is a gateway to the exciting and possibly dangerous world of Rack.
  • Replace selected URLs for a speed boost.
  • Bypasses the Rails router. You have to do your own routing.
  • All Metal endpoints are tried before Rails routing.

Lets say in an alternate universe you are running EBay on Rails.
Your most active page is bots hitting your API to get auction status: GET /auctions/1234567.xml

Replace app/controllers/autctions_controller.rb

With app/metal/auctions_api.rb

class AuctionsApi
  def self.call(Env)
    url_pattern = %r{/auctions/(d+).xml}
    if m = env['PATH_INFO'].match(url_pattern)
      Auctions.find(m[1])
      # This is a Rack return value:
      [ 200, { "Content-Type" => 'text/xml" }, auction.to_xml ]
    end
  end
end

Sinatra

Sinatra is an extremely minimalist web framework. It works in the Rack framework. This is an entire Sinatra application:

require 'rubygems'
require 'sinatra'

get '/hello' do
  "Hello, whirled"
end

Run it:

$ ruby hello.rb
# Starts up server on port 4567
$ curl http://localhost:4567/hello
Hello, whirled

Here is the alternate universe auction example with Sinatra:

class AuctionsApi < Sinatra::Application
  get '/autions/:id.xml'
    Auction.find params[:id].to_xml
  end
end
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Wednesday 5/6 Standup

Pivotal Labs
Wednesday, May 6, 2009

Help

  • Can’t remove git tag on remote: Anyone know how to ensure that a git tag is removed on the remote repository? We’ve tried to remove the tag locally, then push to remote. The tag is removed for a while, but at some point in the future it magically comes back.

Interesting

  • Soap4r (courtesy of Adam Milligan):
    If you’re using soap4r in a Rails app, you know that it generates a module based on a WSDL that you feed it, so you can make SOAP calls by calling Ruby methods. Simple and nice, right? Right. Be careful where you require the generated files though. If Rails loads them too soon they won’t have the necessary information from the WSDL, and your SOAP calls will fail in subtle and frustrating ways.

    If you require the generated files in the class that uses them, your SOAP calls will work in development mode but fail in any environment with class caching turned on (it may work if you have eager class loading disabled, but why take the chance?). If you require the generated files in an initializer, your SOAP calls will fail in every environment. We made this work by including the generated files at the very end of the environment file. An after_initialize block may work as well.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Davis W. Frank

Follow-ups from my RailsConf talk

Davis W. Frank
Wednesday, May 6, 2009

First, thanks to everyone who came – especially those who laughed at all the right spots. If I didn’t get to your question, I’m here through Thursday afternoon.

There were a couple of questions during the talk and lots after the talk about how to deal with remote pairs. Since it’s RailsConf and most folks are on MacOS, ScreenSharing.app came up.

Chad Woolley, King Remote Pivot, wrote up a great detailed discussion of his setup back in December. It should have answers to your tool & equipment questions.

The key element is the Full Screen mode in ScreenSharing.app. In Full Screen mode the remote Mac just becomes a terminal on the host machine – which means keystrokes like CMD-TAB, CMD-Space and a few others go over the wire instead of to your local box.

But Apple killed this feature as of 10.5.5 – but you can get it back! Follow the instructions at this post at MacWorld – use the second, more complex method – to hack on your ScreenSharing.app bundle to restore the awesomeness.

Once you’ve got the new app, replace the current ScreenSharing.app so you are always awesome:

sudo mv /System/Library/CoreServices/Screen Sharing.app/ /System/Library/CoreServices/Lame Screen Sharing.app/

sudo cp Awesome Screen Sharing.app/ /System/Library/CoreServices/Screen Sharing.app/

Then, run these two commands from Terminal:

defaults write com.apple.ScreenSharing ShowBonjourBrowser_Debug 1

'NSToolbar Configuration ControlToolbar' -dict-add 'TB Item Identifiers'  '(Scale,Control,Share,Curtain,Capture,FullScreen,GetClipboard,SendClipboard,Quality)'

We keep a copy of this app around which we renamed to AwesomeScreenSharing.app, so we don’t lose the feature on subsequent Software Updates.

One last thing: Quicksilver doesn’t index into the /System directory by default, but you can change that as well:

  • Go to QuickSilver preferences
  • Go to Catalog (top right)
  • Go to Custom (bottom left)
  • Hit the plus (system bar) to add a new location
  • Pick File & Folder scanner
  • Navigate to /System/Library/CoreServices

Now you can launch ScreenSharing via QS. Enjoy!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Railsconf: Cucumber – Aslak Hellesoy

Pivotal Labs
Wednesday, May 6, 2009

Most of this talk was a basic Cucumber primer. However these things were new to me:

Multi-line arguments

You can use this in a spec; it adds a block argument with the string in it:

"""
  multi-line
  string
"""

Tables

This Genearates a block argument as an array of hashes. ActiveRecord.create can take this as an argument.

Given the following proposals
  |email                    | title   |
  |aslak.hellesoy@gmail.com | Cucumber|
  |bryan@brynary.com        | Webrat  |

Abstract Scenarios

Scenario Outline: Email accepted prposals
  Given the following proposals
    |email                    | title   |
    |aslak.hellesoy@gmail.com | Cucumber|
    |bryan@brynary.com        | Webrat  |
  And the <proposal> proposal is approved
  When I send proposal emails
  Then <email> should <what>

  Examples:
    | proposal | email                    | what          |
    | Cucumber | aslak.hellesoy@gmail.com | get email     |
    | Cucumber | bryan@brynary.com        | not get email |
    | Webrat   | bryan@brynary.com        | get email     |

Before/After/World

Before do
end

After do |scenario|
end

World do
end

World(MyModule)

Background

Feature: Notification emails
  Background:

Tagged Features

Feature: Take over the world
  I want it all

  @spanish @french @english
  Scenario: Take over Europe

Then run:

cucumber -t french doit.feature

# or negative

cucumber -t ~french doit.feature
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Railsconf: Smacking Git Around – Advanced Git Tricks Scott Chacon (GitHub)

Pivotal Labs
Tuesday, May 5, 2009

Presentation

Cheat Sheet

Range selection:

  • Full SHA1
  • Partial SHA1 – at least 4 characters and unique
  • Branch, remote or tag name
  • Caret parent: master^^ (2nd parent of master)
  • Tilde spec: master~2 (2nd parent of master)
  • Combination: master~2^2
  • Blob spec: default:path/to/file
  • Relative spec: master@{yesterday} (relative to your machine)
  • master@{5} the 5th last value of master (locally)
  • [old]..[new] everything reacable from new but not from old
  • jes/master..master
  • jes/master..c36ae

Log usage:

  • git log origin/master.. or origin/master..HEAD only the commits that are going to go upstream
  • git log ..origin/master or HEAD..origin/master everything that origin/master has that you do not
  • git log master –not origin/master
  • git log master –not origin/master
  • git log –graph gives an ascii graph of listory

Diff:

  • git diff HEAD…topic go backto a common ancestor before diffing – gives better results`
  • git commit –ammend modify the last commit

Rebasing:

  • Replay the changes in my branch on top of another branch.
  • rebase –onto use for transplating a topic branch.
  • To transplant some of a topic branch, create a new branch to refer to the part you don’t want then do a rebase –onto.
  • git rebase -i <ref> interactvely pick/redorder/squash by editing a list/script.
  • DO NOT rebase using any commits you have already pushed upstream.

Filter Rebranch:

  • git filter-branch –tree-filter ‘rm -f filename’ HEAD Remove all instances of a file from every commit.

Subtree merging:

  • Alternative to submodules. Looks way complex. Tim Dysinger wrote rake tasks go do this. Google it.

Patch Staging

  • git add -p patch staging – interactively stage only some hunks of a file.

Debugging

  • Annotation: git blame
  • git blame -C <file> even if your like was moved from another file, produce a blame report for it.
  • git bisect

    git bisect start
    git bisect bad (Assumes HEAD)
    git bisect good 3acb4

    takes range you just specified, picks the middle commit nad checks it out, you call it good or bad, wash rince repeat.

    git bisect reset # when you are done.

Customization

  • git config –global help.autocorrect 1 – Stop git com complaining.
  • git config –global color.ui auto
  • Configure external merge tool.
  • .gitattributes for this class of files that match this pattern, treat them differently: e.g. diff binary files echo ‘*.png diff=exif’ >> .gitattributes and add a gitconfig line describing the exif diff strategy.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Railsconf: Building a Mini-Google in Ruby – Ilya Grigorik

Pivotal Labs
Tuesday, May 5, 2009

Ilya’s slides are already on the web.

A few random notes:

  • In 1994-1995 term frequency was state of the art in search engine relevancy.
  • State of the art today = TF-IDF = Term Frequency – Inverse Document Frequency
  • http://rubyforge.org/projects/gratr/ graph theory gem – gets slow after 1000 nodes but can manage about a million.
  • Working with math in Ruby is not the best idea. Use GSL with one of the ruby binding gems.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (783)
  • rails (117)
  • testing (90)
  • ruby (86)
  • ruby on rails (71)
  • jobs (62)
  • javascript (59)
  • techtalk (44)
  • ironblogger (42)
  • rspec (39)
  • bloggerdome (34)
  • productivity (34)
  • activerecord (30)
  • rubymine (30)
  • git (29)
  • gogaruco (29)
  • nyc (27)
  • design (24)
  • mobile (23)
  • pivotal tracker (22)
  • process (21)
  • cucumber (21)
  • jasmine (19)
  • ios (18)
  • tracker ecosystem (17)
  • webos (17)
  • objective-c (17)
  • fun (16)
  • android (16)
  • palm (16)
  • ci (16)
  • "soft" ware (16)
  • bdd (15)
  • tdd (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • css (14)
  • gem (13)
  • mouse-free development (12)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • api (12)
  • keyboard (11)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
Subscribe to Community Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Tools
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >