既存のsinatraをPadrino::Cacheする(2011年11月現在)
どうも気持ち悪いのでメモ。
sinatraをrails相当に高機能化するpadrinoというものがあります。運用実績とか考えるとおんなじ機能だといまはまだrailsで行くべきと思いました。サンプルソース見る限りrinariがある分railsかなと。ただしsinatraなのでrailsに比べてルーティングが高速(らしい)。sinatra+padrinoはそのうちrailsをリプレースするのかもなーとすら思います。すごく良いものだと思いました。
インストール
gem install padrino #あるいはGemfileで
利用する
各機能を独立して使う事もできるというので既存のsinatraに使ってみたら少し、はまった。
読み込んだ時にデフォルトでファイルキャシュをルート/tmp/#{app_name}/cacheにつくろうとするっぽいがapp_nameなんてsetされてないのでとりあえずset :app_nameしないとだめだった。
あとエンコーディングでコケるのでひとつmonkeyする
loggerとしてmodule Kernelにloggerで作ったPadrino::loggerを使うようになっているのだけれども、少なくとも自分の環境ではKernelにぶら下げられてるはずのogger==Padrino::loggerがruby組み込みのloggerに切り替わってしまってうごかなくてイラっとしたりする。loggerを再定義して切り抜けた。
このあたりソースを読むはめにならないようになるといいですね。読んでも小さいのでまぁしんどくは無いですが読む分時間はやっぱりかかる。
動く最小コードはこんな感じでした
require 'sinatra/base' require 'padrino-core/application/routing' require 'padrino-cache' module Padrino module Cache module Store class File def get(key) init if ::File.exist?(path_for_key(key)) puts key contents = ::File.read(path_for_key(key)).force_encoding('ASCII-8BIT') #<= ココ expires_in, body = contents.split("\n", 2) expires_in = expires_in.to_i if expires_in == -1 or Time.new.to_i < expires_in Marshal.load(body) if body else delete(key) nil end else nil end end end end end end class MyApp < Sinatra::Application set :app_name, "musicdb_dev" end class MyApp < Sinatra::Application register Padrino::Routing register Padrino::Cache #loggerがPadrino::loggerじゃなくなる。挙動は追いかけきれていない。 def logger Padrino::logger end enable :caching get "/cachetest",:cache => true do expires_in 60 "cached?" end end
幸せになれるかどうか
データソースアクセスがない単純なerbページでキャッシュ生成のために初回は倍時間がかかる。
時間感覚はキャッシュなしで毎回100msのページが初回200msでキャッシュ配信は10msというイメージ。
まぁメモリ運用のVarnishが落ちてmonitで帰ってきた、という時にunicornが爆発しないという意味では安全弁的幸福なのか。cache_keyをいじってquerystringも含めたキャッシュは可能なので初回生成を許容できならかなりGood。2倍なら余裕で許容できるよなー、と。webserverでダイレクトに配信するのはキャッシュの中身がMarshal.dumpしてるだけなので無理なのかも。
Nginxでキャッシュ効かせておけばVarnish落ちてもNginxのキャッシュが働くなぁとかもおもう。キャッシュだけのためにPadrino入れるのはあまりクールではないなぁと。やるならはじめからPadrinoでという状況がやはり望ましいですね。
追記 11/23
app_nameをsetしないとダメな部分については本家がmergeしてくれたようです。
class MyApp < Sinatra::Application set :app_name, "musicdb_dev" end
ここは不要になりました。