Thin is fast, I don’t think I need to prove that again. But what I’d like to showcase now is Thin extensibility. Most of it is due to Thin being based on Rack. It’s also why lots of framework are supporting Thin already.
Can Thin replace all images with LOLCAT pics on my site when it’s my birthday of a leap year, plz, plz, plz? Cause it should!
Yeah, you’re not the first one to ask.
config.ru file
require 'open-uri' require 'hpricot' class LolCater def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) if iz_ma_burdae? && leap_year? doc = Hpricot(body) doc.search('img').set('src', lolcat_pic_url) body = doc.to_html end [status, headers, body] end private def iz_ma_burdae? Date.today.month == 11 && Date.today.day == 7 end def leap_year? Date.today.leap? end def lolcat_pic_url doc = Hpricot(open('http://icanhascheezburger.com/?random#top')) pic = (doc/'div.snap_preview img').first.attributes['src'] end end use LolCater run Rack::Adapter::Rails.new(:root => '/path/to/my/app')That’s called a Rack middleware. It must have a
call
method and receive a Rack app as the first argument ofnew
. You then tell Thin to use this middleware when running your Rails application. Save the file asconfig.ru
. .ru is for Rackup config file.You can now launch your application with the
thin
script:thin start --rackup config.ruWai-wai-wait that means I can built my own framework in like 30 LOC and use all of Thin goodness?
Right! You can start a cluster of your lolcat image replacer app like you would for a Rails app, but specify the
--rackup
option, which tell Thin to load your application from this file instead to go with the default Rails adapter.thin start --rackup config.ru --servers 3In fact, here’s a lil’ framework I built in 35 LOC:
# Start w/ thin start -r invisible.rb require 'tenjin' module ::Invisible class Adapter def initialize @template = Tenjin::Engine.new(:postfix=>'.rbhtml', :layout=>'../layout.rbhtml', :path=>'home') @file = Rack::File.new('public') end def call(env) path = env['PATH_INFO'] if path.include?('.') @file.call(env) else _, controller, action = env['PATH_INFO'].split('/') Invisible.const_get("#{(controller || 'home').capitalize}Controller").new(@template, env).call(action || 'index') end end end class Controller def initialize(template, env) @template, @status, @env, @headers = template, 200, env, {'Content-Type' => 'text/html'} end def call(action) send(action) render(action) unless @body [@status, @headers.merge('Content-Length'=>@body.size.to_s), [@body]] end protected def render(action=nil) @body = @template.render(action.to_sym, instance_variables.inject({}) {|h,v| h[v[1..-1]] = instance_variable_get(v); h}) end end end require 'app/controllers' run Invisible::Adapter.newFull code on my github repo: http://github.com/macournoyer/invisible/.
And you know I can’t help myself but benchmark it:
merb-core: 1865.19 req/sec
invisible: 2428.17 req/sec(Disclamer: it’s just for fun, don’t use that framework ever or I will come in your house when you sleep and steel all your left foot socks).
Democratizing deployment
I don’t know if you get what this means? It means, deploying a Rails or Merb, Ramaze, etc, app is just a matter of writing a simple Rack config file and playing w/ the –rackup option. It’s all the same script and tools now!
For example, there’s a Ramaze Rack config file in example/ramaze.ru, so to deploy your Ramaze application you would.
thin start --servers 3 --rackup ramaze.ruOr create a config file and install it as a runlevel script:
thin config --rackup ramaze.ru -C myapp.yml edit myapp.yml sudo thin install # Installs the runlevel script mv myapp.yml /etc/thin/myapp.ymlOr if you prefer to monitor your clusters with God, check out the sample God config file that is a drop-in replacement for Thin’s runlevel script.
Happy hacking & deploying!
You have a bug in LolCater#is_ma_burdae?
def iz_ma_burdae?
Date.today == Date.new(1981, 11, 7)
end
That would only return true on the day you were born (in 1981!), which will never happen again.
yay, thanks for catching this, now I can hope my birthday to come again next year!
Pingback: links for 2008-02-11 « Bloggitation
Pingback: Head On » Blog Archive » links for 2008-02-11
Pingback: Starting to Get Thin, v0.6.3
I’m a bit late to comment on this post, but here I am anyways.
When I started developing Halcyon with Rack, I didn’t really comprehend the implications of serving Halcyon; I thought I’d have to write the server, et al. But with Rack and now Thin supporting Rackup config files, I have decided to remove all of the “server” code from Halcyon and just depend primarily on Thin (though with the rackup runner the deployer can use whichever inferior server the deployer chooses to run with).
This makes my framework a great deal simpler, thankfully. Now I can focus on more important issues rather than serving and performance (well, on the performance of serving Halcyon apps, anyways; performance is always a concern).
hey matt,
That’s very cool. Rack is changing a lot of stuff in the web ruby world these days and it’s all for the best. We can now all focus on what makes our app special.
well done, guy
so you’re saying that being thin is an advantage on being a better gymnast? I’m a gymnast and im not thin but im not fat and i do fairly well for a starter. im doing a report on why gymnasts like me go anorexic and this popped up. it could be helpful to my paper for school.thanks much.
Pingback: decodeURI » Creating a Rack Middleware for Minifying Your Javascript files
Pingback: Creating a Rack Middleware for Minifying Your Javascript files « decodeURI
I’m not sure exactly why but this site is loading extremely slow for me. Is anyone else having this issue or is it a problem on my end? I’ll check back later
on and see if the problem still exists.