既存のsinatraをPadrino::Cacheする(2011年11月現在)

どうも気持ち悪いのでメモ。
sinatrarails相当に高機能化する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

ここは不要になりました。