production環境ではexception_notificationでエラーをメールしてる人も多い思います。(AirBreakとかも)
怖話でもそうやってエラーメールが一通も来ない状態にしたいんですが、例えば下記のような”バグじゃないエラー”は皆様どうやって対応してるんでしょう?
A ActionView::MissingTemplate occurred in home#index:
Missing template home/index, application/index with {:handlers=>[:erb, :builder, :haml], :formats=>["*/*;q=0.01"], :locale=>[:ja, :ja]}. Searched
formatsに*/*;q=0.01なんて文字列を送ってくるのは単なるスパム。使ってるformatだけに限定するように何か書く?うーん・・・。
怖話.jpをHerokuからさくらVPS 512に移行することにしました。理由は下記です。
- DB容量が無料の範囲を大幅に超えている。(一応容量オーバーしていても使える)
- slug(リポジトリ)のサイズが制限(100MB)を超えた。(これはオーバーしているとpushできない)
- ファイルアップロードが必要になった。(S3を使えば対応は可能)
- 回線が遅い。(us westとかなので仕方が無い)
Amazon EC2にしなかった理由はまだ人気が無いのでお金をかけられないからです。もし売上が月数十万になったら移行します。
DB移行
HerokuのDBはPostgreSQLです。さくらVPS 512ではMySQLを使うことにしました。
現在のDB容量は37.4MB。レコード数は約2万件ぐらいです。heroku db:pullをしたら1時間たっても終わる気配がなかったので次の方法を取ることにしました。
- herokuからローカルにpg_dumpを持ってくる。
- ローカルのpostgresにpg_restore。
- ローカルのmysqlにtapsサーバーを立てる。
- ローカルのpostgresからtapsサーバーへpush。
- ローカルのmysqlからmysqldump。
- さくらVPSのmysqlにrestore。
大したデータ量じゃないのに、要はネット経由でtapsするととてつもなく時間がかかるのです。
「これ絶対もっと楽な方法あるよなあ」
などと思いながら作業しました。
怖話.jpのランキングの実装を考える。(ニコニコ動画で言えば総合ランキング)
下記の様に各怖い話のスコアを算出してそれでソートする。
スコア = PV数 + 怖いの数 * 1000 + コメント数 * 100
("怖いの数"というのはニコニコ動画で言えば"マイリスト数")
当分の間、特殊なランキングアルゴリズムは必要無いだろう。1000と100という重みは定数にして様子を見ながら変えていく。
人気サイトであれば裏で集計すべきだけどまだ貧弱サイトなので毎回サブクエリで集計してしまおう。
select * from stories order by view + (select count(*) from scares where scares.story_id = stories.id) * 1000 + (select count(*) from comments where comments.story_id = stories.id) * 100 desc, id desc;
我ながらとっても遅そうなクエリだ。
class Story < ActiveRecord::Base
scope :order_by_ranking, order("view + (select count(*) from scares where scares.story_id = stories.id) * #{Scare::RANKING_WEIGHT} + (select count(*) from comments where comments.story_id = stories.id) * #{Comment::RANKING_WEIGHT} desc, stories.id desc")
end
Story.order_by_ranking.page(params[:page]).per(50)
ActiveRecordとkaminariのお陰でスマートな見た目にできたが、気をつけて実行しなければならない重いsocpeになってしまった。