読者です 読者をやめる 読者になる 読者になる

HerokuからMOGOKへ移行

MOGOK をHerokuからMOGOKへ移行しました。
MOGOKについてはこちら -> MOGOK
HerokuではDBがこのまえPostgreSQLに移行した際に1万行の制限がかかり、絶対復習ではお金を払わないといけなくなったのですけど、それが月々$8くらいかかるので…。
それを捻出できない絶対復習のようなサービスではちょっと負担が大きいかなと思い、MOGOKへ移行することに。
(MOGOKはDBが100MB制限なのでかなり使えます http://mogok.jp/service.html

作業の中ではまりそうなものだけまとめてみました。

DBの移行

まず、Herokuコマンドでメンテナンス状態にし、Heroku PGBackups | Heroku Dev Centerを使って、DBのダンプ取得。

次に、DBのダンプを自分のローカル環境にあるPostgreSQLに突っ込んで、Railsyaml_dbを入れて、DBの内容をYAML形式にダンプします。
yamldb/yaml_db · GitHub

あとはこれをMOGOK側で作成して、デプロイしておいたアプリケーションのDBに突っ込むだけです。
デプロイの方法はチュートリアルを参考に -> MOGOK Documents - Rails Application Deployment Guide

ただ、yaml_dbの rake db:load はデータサイズによってものすごく時間がかかってしまい、どうやらMOGOKのrakeタスク実行時間の制限に引っかかてしまうようなので、以下のようなスクリプトでdata.ymlを分割してしまいます。

HEADER=<<EOF
---
reminders:
  columns:
  - id
  - user_id
  - schedule_id
  - title
  - body
  - completed
  - created_at
  - updated_at
  - learned_at
  - next_learn_date
  - format
  records: 
EOF

File.open("./data.yml.reminders", "r") do |f|
  suffix = 'a'
  count = 0
  limit = 50000
  out = File.open("./data.yml.#{suffix}", "w")
  out << HEADER
  f.each_line do |line|
    if count > limit && /\A\s\s-\s-\s\d+/ =~ line
      limit += 50000
      out.close
      out = File.open("./data.yml.#{suffix.succ!}", "w")
      out << HEADER
    end
    out << line
    count+=1
  end
  out.close
end

だいぶテキトーな書き捨てスクリプトですが、勝手に書き換えて使えばいいんじゃないかと。
(上のはdata.ymlに1テーブルのデータしかない想定で書いてます)

ほいで分割したdata.yml.*は以下のタスクで読み込ませます。

namespace :db do
  desc "load dumped data"
  task :load_of => :environment do
    format_class = ENV['class'] || "YamlDb::Helper"
    helper = format_class.constantize
    SerializationHelper::Base.new(helper).load("#{Rails.root}/db/#{ENV['FILE']}", ENV['TRUNCATE'])
  end
end

yaml_dbのdb:loadだとテーブルのtruncateが入ってしまうので扱いづらいんですよね。

$ mogok rake db:load_of FILE=data.yml.a TRUNCATE=true
$ for i in b c d e f g h i j; do mogok rake db:load_of FILE=data.yml.$i; done

これでDBの移行は完了っと。

カスタムドメイン

MOGOKではまだカスタムドメインの機能はないので、手持ちのWebサーバでプロキシさせることになります。
Apacheであればたとえば以下のような感じの設定でいけたっぽいです。

<IfModule mod_proxy.c>
ProxyRequests Off 

<VirtualHost *:80>
    ServerName brushup.narihiro.info

    ProxyPass        / http://brushup.ruby.iijgio.com/
    ProxyPassReverse / http://brushup.ruby.iijgio.com/
    ProxyPassReverseCookieDomain brushup.ruby.iijgio.com brushup.narihiro.info
</VirtualHost>

Railsにプロキシしているドメイン名を伝えるために以下のようなRackのミドルウェアも書きました。

diff --git a/config/environments/production.rb b/config/environments/production.rb
index d2dd166..de7f2e1 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,3 +1,5 @@
+require 'brushup/rack_set_http_x_forwarded'
+
 Brushup::Application.configure do
   # Settings specified here will take precedence over those in config/application.rb
 
@@ -61,6 +63,8 @@ Brushup::Application.configure do
   # Send deprecation notices to registered listeners
   config.active_support.deprecation = :notify
 
+  config.middleware.insert_before ActionDispatch::ParamsParser, Brushup::RackSetHttpXForwarded
+
   # Log the query plan for queries taking more than this (works
   # with SQLite, MySQL, and PostgreSQL)
   # config.active_record.auto_explain_threshold_in_seconds = 0.5
diff --git a/lib/brushup/rack_set_http_x_forwarded.rb b/lib/brushup/rack_set_http_x_forwarded.rb
new file mode 100644
index 0000000..ca33b05
--- /dev/null
+++ b/lib/brushup/rack_set_http_x_forwarded.rb
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+require 'rack'
+require 'rack/request'
+
+module Brushup
+  # HTTP_X_FORWARDED_XX系を無理やり設定する
+  class RackSetHttpXForwarded
+    def initialize(app)
+      @app = app
+    end
+
+    def call(env)
+      env['HTTP_X_FORWARDED_HOST'] = 'brushup.narihiro.info'
+      status, headers, body = @app.call(env)
+      [status, headers, body]
+    end
+  end
+end

ほんとはプロキシ側でHTTP_X_FORWARDED_HOSTを設定してやればいいのですが、MOGOK側で上書きされてしまうようなので、これはしょうがないかなあと。

と、そんなところでsora_hにオワコンと言われた(まだ根にもってる)絶対復習はすくすくと動いておりますし、MOGOKがこの世にある限り、これからも動き続けることでしょう。
おわり。