駒形電産

弊社(FJORD, LLC)がEngine Yardとパートナーシップ(的なもの)を結んで怖話Engine Yard Cloud(以後EYC)に移行しました。

(飽くまで”的なもの”で、ちゃんとしたパートナーシップはこういうの

トライアルで検討する

トライアルで試した件については以前こちらに書きました。

Engine Yard Cloudを試す - komagata

本契約前に

貧乏会社なので複数台サーバーなんていくら掛かるのか怖い。料金シュミレーターで予め見積もっときました。

さくらVPSから移行したのは複数台構成のためなので、ちょっと奮発してappサーバー2台+dbサーバー1台の構成にしてみました。高けー!

デプロイ

手順はトライアルの時と同じです。ただ、本契約の場合は東京リージョンが選べます。

アクセスしてみる

appサーバー2台あるけど、どのIPにアクセスしたらいいの?と思いましたが、Application Masterの方のSSHのリンクをクリックする時に出るURLにIPがハイフン区切りで出てるのでそこにアクセスします。(この場合は54.249.225.67)

dbの方もそれで直接dbのインスタンスにsshできます。ユーザー名はdeployでした。

アプリをEYCに合わせる

EYCに載せるに当ってアプリを修正しないといけない点が2点ありました。

rubyを1.9.3系にする

EYCはまだruby2.0.0に対応してないので1.9.3系に変更しました。あんまり変わらないだろうと思ってましたが、encodingのmagic commentが無くていくつかエラーが。泣く泣く追加しました。

ユーザーのアップロード画像をS3に移行

これはEYCだからではなく、appサーバーが複数台になるのでユーザーがアップする画像をローカルに保存してたら迷子になります。幸いpaperclipの画像保存先をS3にするのは簡単で1日あれば対応できました。

データベースの移行

$ ssh bodom "mysqldump -udeployer -pXXXXXXX kowabana_production" | ssh db.kowabana.jp "mysql -uroot kowabana" 

これはコマンド1行でOK。sshで入れるとこういうところが楽ですね。EYCのdb名はアプリ名と同じになるようです。mysqldumpは全テーブルロックするのでデータ量の大きなサイトではこういう雑な移行はオススメできません・・・。

railsアプリのdatabase.ymlの接続先は変えなきゃいけないんじゃないの?と思いましたが、EYCのdeployのレシピで良い感じにdatabase.ymlを生成してくれるそうです。便利。

サポートチャット

トライアルの時もお世話になったサポートチャットですが、グローバルの方は平日の8AM PST - 6PM PST(日本では1時から13時)がサポート時間です。

これは豆ですが、Engine Yardの日本法人のトップページのチャットから発信すれば日本人が日本時間で対応してくれます。

感想

まだ移行したばっかりなのでどうなるかわかりませんが、移行作業自体は思ったより早く簡単にできたなと思います。最近セキュリティ周りがキナ臭いのでその辺は安心感がありますね。(最近別の仕事でウィルスに感染したPHPのサイトの調査をやったばかりです。)

オープンネットワークラボにGithubのPJらが来た時のイベントで「初期のGithubはEngine Yardにサーバーを借りていた」という話を聞いてその後の懇親会でいきなり不躾にも「弊社にもサーバー貸してください!」と@yandoさんに無茶振りしたことから始まった話でしたが色々お手数をお掛けしつつ移行できてよかったです。ありがとうございます。

snes9x for Macの今最新は1.53らしい。

Snes9X.COM: Downloads

ここでROMを検索すると沢山出てきますが、違法ダウンロードはいけません。

ダウンロード - ROM - スーパーファミコン (SNES) - SEARCH

怖話でjsで文字幅を知る必要があったところ、こちらで神コード発見しました。

東アジアの文字幅 (East Asian Width) の判定 - 中途

コメント欄でお伺いを立ててますが、昔の記事なのでご覧になってないかも。余りにも神だったのでnpmのパッケージにしました。

東アジアの文字幅って何?とかは長くなるので下記参照。

東アジアの文字幅 - Wikipedia

類似のに比べてコードがコンパクト、そしてcharCodeAtではデフォルト対応してないサロゲートペアに対応しているのが素敵です。勝手にnpmにすんな!と言われたら直ぐ消します。すみません。

komagata/eastasianwidth · GitHub

結局、consoleとは違って等幅フォントにしても全角は半角の2倍の幅というわけじゃないのでWebでの用途(怖話)には使えませんでしたが・・・。

Install

$ npm install eastasianwidth

Usage

var eastasianwidth = require('eastasianwidth');
console.log(eastasianwidth.eastAsianWidth('₩')) // 'F'
console.log(eastasianwidth.eastAsianWidth('。')) // 'H'
console.log(eastasianwidth.eastAsianWidth('뀀')) // 'W'
console.log(eastasianwidth.eastAsianWidth('a')) // 'Na'
console.log(eastasianwidth.eastAsianWidth('①')) // 'A'
console.log(eastasianwidth.eastAsianWidth('ف')) // 'N'

その昔あったMojavi Japan(mojavi.net)というサイトがDreamhostから発掘されたので移行しようと思ったんですが、XOOPSが古過ぎて動かん・・・。

移行先は素敵なさくらVPSにDebian Wheezyを入れてるのでPHPが5.4.4と眩いばかりのバージョンで動きやしない。その点WordPressはかなり古いバージョンだったのに上書きするだけでバージョンアップが走った。すげえ。

どなたか移行方法ご存知の方がいらっしゃったら教えていただけると嬉しいです・・・。わからなかった場合はAmazon Glacier行きの予定です。

福岡で行われたPHPMatsuri2012に行って来ました。

PHPConference2012も行ってるし、訓練されたPHPerと言えそうです。

夜の闇PHPMatsuriのアン・リーダブルコード選手権にレガシーブラックが出てました。

レガシー戦隊。

「レガシーブラック、一体何者なんだ・・・。」

「全力でたけしの真似をして望んだがMr. レガシーになれなかった。プロジェクトの仲間である@hrysd, @kjirou, @kaz_29に申し訳が無い。気力も尽き、体力の限界っ!(via 千代の富士)」とはレガシーブラックの弁。

久しぶりに飛行機乗って旅行熱が高まりました。なにわともあれ、お話させて頂いた皆様、運営者の方々、お疲れ様です。ありがとうございました。

関連:レガシーPHP改善日記シリーズ

唯一ぬにの盾

今は亡きWiseknot社の同僚であった「三度の飯より四度の飯、Javascriptはもっと好きです。」でお馴染みの@kjirouが一ヶ月来てくれる事になった。

また、アリウープ様にお願いしていた件もCakePHP2実践入門の著者の一人でもある@kaz_29さんが参戦してくださることになった。

「もうついたのか!」「はやい!」「きた!盾きた!」「これで勝つる!」と大歓迎状態だった。哀れにも@komagataは盾の役目を果たせず死んでいた近くで素早くフラッシュ(略

軽く発生ポイント

俺「あのポイント関連の処理ってどこでやってるの?」

@kjirou「あー、あれは共通化されてないからどっちかは処理されてないんだけど、片方は"軽く発生ポイント"でやっ(略」

俺「軽く?・・・何?」

@kjirou「だからカルクハッセイポイントクラスで」

俺「あー、Calculation?ちょwwwww CalcHasseiPointかよwwww。英語日本語英語のクラス名をさも一般名詞みたいに日常会話に混ぜないでよwwww」

@kjirou「いやそんなんこのコードの中じゃ普通でしょ、それより酷いのがこっちの処(略」

Testing Testing Testing!

大量メール配信の部分もヤバイということで@kaz_29さんがSimpleTest(CakePHP1.3なのでPHPUnitじゃないところがまたダルいが)でテストを書き始めてくださった。

@kjirouも複雑怪奇な仕様と実装をGithub Wikiにまとめながらどんどんコードを書いてる。

@hrysdは先日仕込んだMailLoggerから容赦なくNotice, Warnningが飛んでくるのでそれを潰すのを担当。

盛り上がって来やがった。

強引なEnd To Endテスト

app/tests/helper.php:

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';

class CakePHPSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase
{
    protected function assertNoError()
    {
        $html = $this->getHtmlSource();
        $patterns = array(
            '/<b>Fatal Error<\/b> \(256\)/',
            '/<b>Warning<\/b> \(512\)/',
            '/<b>Notice<\/b> \(1024\)/'
        );

        $result = 0;
        foreach ($patterns as $pattern) {
            $result += preg_match($pattern, $html);
        }

        $this->assertEquals($result, 0);
    }
}

「とにかく普通に画面にエラーが出てる」

という問題を直すためにCakePHP1.3が出力するエラーを確かめるための強引なAssertionを作成。

app/tests/integrations/RegularOrdersTest.php:

<?php
require_once 'helper.php';

class RegularOrdersTest extends CakePHPSeleniumTestCase
{
    protected function setUp()
    {
        $this->setBrowser('*firefox');
        $this->setBrowserUrl('http://xxxxxxxxxx/');
    }


    public function testIndexTitle()
    {
        $this->open('/regular_orders');
        $this->assertTitle('管理画面');
        $this->assertNoError();
    }
}

こんな感じで使う。

PHPUnitのソース追ってましたが、開発がかなり活発。APIとマイナーバージョンがどんどん変わってく。そんなに頑張るとハゲるぞセバスチャン。

まだJenkinsに怒られるけど来週には環境が整うはず。強引にCIに乗せようと思えば乗るもんだなあという感じ。

PHPMatsuri

PHPMatsuri2012行きます。基本、Hackathonだそうなのでレガシーに役立つ何かが作れればなーと思います。

関連:レガシーPHP改善日記シリーズ

あるべき初期データの姿が不明。今動いてるDBが全て。という場合にmigrationをはじめるのが難しい。また、複合主キーを使ってる場合はそもそもmigration出来ない。なので無理矢理afterでdumpファイルを読み込んで対応。

<?php
class xxxxxxxxxxxxxxxxx extends CakeMigration
{
    public $description = '';

    public $migration = array(
        'up'   => array(),
        'down' => array(),
    );

    public function before($direction)
    {
        return true;
    }

    public function after($direction)
    {
        if ($direction == 'up') {
            $config = $this->db->config;
            `mysql -u{$config['login']} -p{$config['password']} {$config['database']} < db/20121010154033_create_initialize.sql`;
        }
   
        return true;
    }
}

レガシーコード改善ガイドが届いたので読みました。とても勇気づけられたし、レガシー改善のコーディングテクニックがいろいろと参考になりました。

個人的にはコーディング以外の開発環境やツール、スクリプト言語ならではな部分も知りたかったのでレガシーコード改善ガイド風に思いついたのを書いていこうと思います。

このPHPのコードを追える気がしません

まずは深呼吸して、コードベースをeval, create_function, extractでgrepしましょう。意外と少ないでしょう?だったら大丈夫。findとgrepとviがあればいつかは何とかなります。

バージョン管理されてません

テスト環境みたいなのがあるはず(もしくは本番環境)なのでFTPとかSCPでそれを全部もってきてgithubに突っ込む。今後、開発はそこにコミットして、アップするときもそこからアップしてねと言う。

githubを借りる許可が出なかったらその辺のマシンにgitをreposを立てる。みんなでreposを使う合意が取れなかったら自分だけでもgitで管理する。githubの利点はpull requestとコードレビューがしやすい点。

ソフトウェア資産を失わないようにという話をすれば大抵聞き入れてくれるはず。

ステージング環境がありません

その辺のマシン、もしくはさくらVPS1Gを借りてreposにpushされたらそこにデプロイされるようにしよう。(capistranoとかで)

本番環境しかないのでテストにつかうまともな初期データがありません

おそらく本番環境のDBの状態=仕様になっているのでしょう。3桁に迫るテーブルがある場合、まっさらなスキーマから手で初期データを作っていると日が暮れてしまいます。本番のDBをdumpしてきてそれをベースにテストを実行しましょう。ボトムアップではなく、トップダウンで初期データを少しずつあるべき状態にしてきましょう。

中長期的な作業をする時間がありません

本業(デスマ)も「このくらいやってれば普通以上だろう」ぐらいやりつつ開いた時間でやろう。もしくは業務時間外でやりましょう。

頑張る気が起きません

ひどい状態なら怒られない範囲でブログに書けばネタになるし同僚や誰かが助けてくれるかもしれません。着実に改善していくところをRPGみたいに楽しもう。ナイトメアモードのゲームだと思えばやりがいがあります。

関連:レガシーPHP改善日記シリーズ

こんなこと書いてたけど普通にできた。(simpletestは必要)

% cake testsuite app all

知らんかった・・・。

ついでに、phpunitを使ったseleniumのテストも一緒にできるshell作った。

app/vendors/shells/tasks/integrations.php:

<?php
class IntegrationsTask extends Shell
{
    public function startup() {}

    public function execute()
    {
        $this->out(`phpunit app/tests/integrations`);
    }
}

app/vendors/shells/test.php:

class TestShell extends Shell
{
    public $tasks = array('Cases', 'Integrations');

    public function startup() {}

    public function main()
    {
        $arg = isset($this->args[0]) ? $this->args[0] : '';
        switch ($arg) {
        case 'cases':
            $this->Cases->execute();
            break;
        case 'integrations':
            $this->Integrations->execute();
            break;
        default:
            $this->Cases->execute();
            $this->Integrations->execute();
        }
    }
}
% cake test