2012年11月29日

Perl Advent Calendar Japan 2012 は明後日からです、みんな参加して寿司を食べよう!

今年は、真夏なのに advent calendar やってる人がいてて????な顔をしていた yappodoll です今晩和。

今年も advent calendar の季節が始まります。

Perl Advent Calendar 2012 Japan ももちろん開催します!
しかしみんなシャイな娘が多過ぎて参加者集まってません!

毎年有用な記事が集まるこのイベントに貴女も参加しませんか!?!?//

今年も Hacker TrackCasual Track も準備万端です!
Teng Track や Acme Track や DevOps Track など、あなたのやりたいトラックももちろん開催しますよ!

さぁ僕たちとあどべんとカレンダーを食べてみんな美味しい寿司を食べましょう//


スペイン・ワインの愉しみ
鈴木 孝寿
新評論
売り上げランキング: 320195

Posted by Yappo at 19:04 | Comments (0) | TrackBack

2012年11月28日

DSN に sql-mode=... 付けてもなんもなんないんだよ糞が!

最初の方に追記しておくと生DBI限定の話です。僕のしらない wrapper モジュールだと動くのかもしれません。
けど、こういうエントリを僕が書いてる時点で、そういうモジュールは筋悪いんだとおもいます。

人のプロジェクトのコードを見てたら

my $dbh = DBI->connect('dbi:mysql:dbname=geekdb;sql-mode=STRICT_TRANS_TABLES', 'yappo', 'moneyfriend', %attr);
みたいな感じの DSN があったんですよね。
他にも attribute てんこもりだったんで、それコミットした人に聞いて見たら「秘伝のタレです」的なのが帰ってきたので、僕も何も考えないで「これでSTRICT_TRANS_TABLES効いたら、まぁ捗るから付けとこう」って感じでコピペして付けてたんだけど、さいきん鉄板 DBI 選手権あったのでコメント書いたら「有効になるわけねーだろ!」的な椅子が飛んできて、調べたら確かに意味ない設定でした。

エントリ書いてからもっかい確かめようと思って実装みてたんですが、延々と XS コード出てきて説明面倒になってきたので禿げてないでコード書いてみた。
DBI 1.622
DBD::mysql 4.022

だめなばあい

MySQL のドキュメントを見ると「STRICT_TRANS_TABLES は厳格なんで ENUM に定義してない値とかいれてもエラーだよ」って書いてあるので、分かりやすく ENUM で定義されてないデータを突っ込んでみる。

use strict;
use warnings;
use 5.012;
use DBI;

my $dbh = DBI->connect(
    'dbi:mysql:dbname=geekdb;sql-mode=STRICT_TRANS_TABLES', 'yappo', 'moneyfriend',
    +{
        PrintError => 0,
        RaiseError => 1,
        AutoCommit => 1,
    }
);

$dbh->do(q{DROP TABLE IF EXISTS geeks});
$dbh->do(q{CREATE TABLE geeks (                                                                             
    geek ENUM('matz', 'dan') NOT NULL                                                                          
)});


$dbh->do(q{INSERT INTO geeks (geek) VALUES('dan')});
my($geek1) = $dbh->selectrow_array('SELECT geek FROM geeks LIMIT 1');
say $geek1;
$dbh->do(q{DELETE FROM geeks});

$dbh->do(q{INSERT INTO geeks (geek) VALUES('hyoshiok')});
my($geek2) = $dbh->selectrow_array('SELECT geek FROM geeks LIMIT 1');
say $geek2;

これを実行すると、普通に実行されてるが $geek1 で dan を表示してるのに $geek2 では何も表示しないで終わってる。
これは hyoshiok という文字列が geek の ENUM に定義されてないから、なにも入れられてないって事で STRICT_TRANS_TABLES が有効になってなさそう。。。。!

大丈夫な例

椅子とともに SET SESSION sql_mode=... しろと言われたので、 connect 時に SQL を打ってみる。
ここで何も考えないで $dbh->do つかってやっちゃうと reconnect した時とかに無効になるので、筋良く Callbacks オプションを使う。
説明は椅子プロさんの解説が Perl Advent Calendar に乗ってた!

use strict;
use warnings;
use 5.012;
use DBI;

my $dbh = DBI->connect(
    'dbi:mysql:dbname=geekdb;sql-mode=STRICT_TRANS_TABLES', 'yappo', 'moneyfriend',
    +{
        PrintError => 0,
        RaiseError => 1,
        AutoCommit => 1,
        Callbacks  => +{
            connected => sub {
                my $dbh = shift;
                $dbh->do(q{SET SESSION sql_mode=STRICT_TRANS_TABLES});
                return;
            },
	},
    }
);

$dbh->do(q{DROP TABLE IF EXISTS geeks});
$dbh->do(q{CREATE TABLE geeks (                                                                             
    geek ENUM('matz', 'dan') NOT NULL                                                                          
)});

$dbh->do(q{INSERT INTO geeks (geek) VALUES('dan')});
my($geek1) = $dbh->selectrow_array('SELECT geek FROM geeks LIMIT 1');
say $geek1;
$dbh->do(q{DELETE FROM geeks});

$dbh->do(q{INSERT INTO geeks (geek) VALUES('hyoshiok')});
my($geek2) = $dbh->selectrow_array('SELECT geek FROM geeks LIMIT 1');
say $geek2;

今度のケースを実行すると。。。

dan
DBD::mysql::db do failed: Data truncated for column 'geek' at row 1 at ./hoge.pl line 32.
ちゃんとエラーが出てくれてて STRICT_TRANS_TABLES が有効になってるっぽい!111

まとめ

DSN を良きにしてくれる O/R Mapper とかあるのかなとおもって DBIC みてもそういう実装じゃないし、そもそも DSN 変な拡張入れる筋悪なの使う人は迷惑なので、実際なくて良かった。

ということで、接続してから

SET SESSION sql_mode=...;
すべし、と椅子プロさんに指摘頂きました。

本日の教訓

コピペでプロジェクト始めるやつは空気椅子で仕事してろや!

Posted by Yappo at 13:37 | Comments (0) | TrackBack

2012年11月26日

サービスをつぶさない為に Web アプリを書く時にやっとくと良い事2選

テンプレートのエラーが出た時にアプリケーションのログだけに書くのでは無く、誰にでも「ここがえらってるよ!」って見えるようにしとくと間違いが少なくなる傾向があるのでテンプレートエンジンでフック出来るようになっておいてたら、それをうまく使うと良い。

また、テンプレートエンジンがレンダリングしてるフェーズで DB にクエリが飛ぶような構造で書いてあると、非エンジニアのカジュアルにテンプレートいじる人が甚大なクエリを実装してしまう可能性があるので、これも早期に発見しないとサービスが止まってしまい会社の売り上げが下がってしまい社員が路頭に迷うケースが発生してしまうので、これらも未然に防がなければならない。

Text::Xslate + Amon2 ならこうかける。

package MyProje::Web;
...;
{
    my $view_conf = __PACKAGE__->config->{'Text::Xslate'} || +{};
    if ($ENV{PLACK_ENV} eq 'development') {
        $view_conf->{warn_handler} = sub {
            warn @_;
            Text::Xslate->print(
                Text::Xslate::mark_raw('<span style="color: red; font-size: 1.8em;">'),
                '[[', @_, ']]', 
                Text::Xslate::mark_raw('</span>')
            );
        };
    }
    my $view = Text::Xslate->new(%{ $view_conf });
    sub create_view { $view }
}
...
sub render {
    my ($c, $tmpl, $vars) = @_;
    if ($ENV{PLACK_ENV} eq 'development') {
        require DBIx::Tracer;
        $tracer = DBIx::Tracer->new(
            sub {
                return unless Text::Xslate->current_engine;
                my %args = @_;
                my $sql = $args{sql};
                warn "Do not execute query in a view: $sql";
                Text::Xslate->print(
                    Text::Xslate::mark_raw('<span style="color: red; font-size: 1.8em;">'),
                   "[[ Do not execute query in a view: $sql ]]",
                   Text::Xslate::mark_raw('</span>')
                );
            }
        );
    }
    $c->SUPER::render($tmpl, $vars);
}

ログに吐いておいたらエンジニアくらいにしか気づかないが、ブラウザから分かるように真っ赤に大きく明らかなエラーっぽいのを返す事でアンテナの感度が低めな人にも「なんかおかしいよこれ」って言ってもらえるので、結果的には事故が未然に防げておいしいご飯と暖かい布団で生活出来るようになるわけである。

こんかいは、うっかり Perl で例を書いたが他の言語でも応用が利くでしょう。

参考文献
Xslate 1.0006 released! - Islands in the byte stream
How can I deny a DB access in a view? - tokuhirom's blog.

2012年11月08日

ExclusiveLock::Guard という排他ロック簡単にやるモジュール書いた

ファイルを使って排他ロックするには、適当にロックファイルを作って flock $fh, LOCK_EX とかすると思います。
flock で使ったファイルハンドルが close されたら自動的に unlock されるので、最初っから Guard な感じなんだけどロック用のファイルも一緒に消したいので ExclusiveLock::Guard ってのを作った。

use ExclusiveLock::Guard;
my $lock = ExclusiveLock::Guard->>new('/tmp/megazaru.lock');

って書くだけで $lock が生きてる間はロックかかってて、ロック外れたらファイルも一緒に消してくれるというだけの物。

ノンブロッキングなインターフェィスが欲しければ

use ExclusiveLock::Guard;
my $lock = ExclusiveLock::Guard->>new('/tmp/megazaru.lock', nonblocking =>l 1);
die '別の人にロックされてるよ'  unless $lock->is_locked;

みたいな風に書けます。

MySQL::NameLocker 使えば同じ事を MySQL の SET_LOCK 使って実装してるんだけど、ファイルロックでこういうの無かったので。

Posted by Yappo at 17:53 | Comments (0) | TrackBack

2012年11月05日

WEB+DB PRESS Perl連載枠「Perl Hackers Hub」のまとめ

そろそろ3周目も無事おわりそうなので、今までやった事をまとめて検討したい。

Vol.55 2010年2月24日発売 【第1回】PSGI/Plack……フレームワークとサーバをつなぐエンジン……宮川達彦
ベッケンバウアーだったんだけど、縁があって第一回目に。
Vol.56 2010年4月24日発売 【第2回】AnyEventでイベント駆動プログラミング……牧 大輔
たしか非同期プログラミングのブームが終焉してて実用的に使われだしてた時期だったかなと。
Vol.57 2010年6月24日発売 【第3回】DBIx::Classでデータベース操作……村瀬 大輔,Japan Perl Association[監修]
まだまだ Skinny とかは早過ぎたし、世界的なビッグウェーブの DBIC で ORM のネタをダストか云々だった気がした
Vol.58 2010年8月24日発売 【第4回】Twitterから学ぶ,Web APIのキホン……和田 裕介,Japan Perl Association[監修]
まっしゅあっぽーまっしゅあっぽーていうネタも必要だよねて気な
Vol.59 2010年10月23日発売 【第5回】Xslate……次世代テンプレートエンジン……藤 吾郎,Japan Perl Association[監修]
Xslate 売り出し期に突入してたし、テンプレートエンジンも TT 以外の物を見るようにしないとね的な感じと YAPC 連動だっけか
Vol.60 2010年12月22日発売 【第6回】UNIXプログラミングの勘所……奥 一穂,Japan Perl Association[監修]
プログラミングの基本のキの字を解説するのも捗りますねとかそういう感じだったかな
Vol.61 2011年2月24日発売 【第7回】新人さんのための仕事で使えるPerl基礎知識……横山 彰子,Japan Perl Association[監修]
ここまで、わりとガチだったので Perl とか良くわからない人向けに特にガチでも無い一目線で Perl の導入記事かいてもらうと、案外捗りそうだという紙の声が聞こえたりした
Vol.62 2011年4月23日発売 【第8回】Perlによる大規模システム開発・設計のツボ……広木 大地,Japan Perl Association[監修]
Perl を使った大規模システムの大規模チーム開発のプロフェッショナルによる、新人向けのチーム開発のいろは
Vol.63 2011年6月24日発売 【第9回】高速なWeb APIの実装とテスト…… Mobage APIを支えるノウハウ……嶋田 裕二(xaicron),Japan Perl Association[監修]
前号とは違った側面での高スループットを出すシステムをどうやって作るか生大好きみたいな
Vol.64 2011年8月24日発売 【第10回】ジョブキューで後回し大作戦……TheSchwartz,Qudo,Q4M……小林 篤,Japan Perl Association[監修]
Webサイト作るのにもキューってのは多用されてるので、そろそろ話題に出しましょうという
Vol.65 2011年10月22日発売 【第11回】ログでアプリケーションの改善プロセスを回す……長野 雅広,Japan Perl Association[監修]
開発に取ってはログは基本中の基本というところで、ログの人にいろいろ解説してもらう
Vol.66 2011年12月23日発売 【第12回】小飼 弾のPerlハッカーに逢いたい♥……小飼 弾,Japan Perl Association[監修]
最初から YAPC と絡めたいよねという事で、だったらアルファギークに逢いたいの時の感じがやりやすいらしいという事で、いろいろいってたらだいぶ豪勢になった
Vol.67 2012年2月24日発売 【第13回】メタオブジェクトプロトコル入門……Shawn M Moore,牧 大輔,Japan Perl Association[監修]
日本に住んでない人にも書いてもらいたいよねーとは思ってて、ちょうど YAPC の前夜祭で快諾もらってしかも話題的にも良い題材で書いてもらえる事になった
Vol.68 2012年4月24日発売 【第14回】最新Perl使いこなし術 ……リファレンスの引き方,5.10以降の新機能……cho45(さとう),Japan Perl Association[監修]
Perl5.10 以降の機能について紙媒体であまり出てないとおもってたので、分かりやすい解説書く事で定評のあるちょさんに
Vol.69 2012年6月23日発売 【第15回】Perl meets beats ……鳴らして学ぶシンセサイザー入門……伊藤 智章,Japan Perl Association[監修]
関東以外の人にも積極的に書いてもらいたくて、運良く書いてくれる人が見つかりつつ、今までとはだいぶ違う面白い記事になった
Vol.70 2012年8月24日発売 【第16回】Perl内部構造の深遠に迫る……藤 吾郎(gfx),Japan Perl Association[監修]
ほんとは一人一回が良いと思ってたんだけど、 Xslate の時にこのネタと天秤にかけてて不採用だったんだけど、やっぱりコアネタ欲しいということで、だいぶ捗る記事に
Vol.71 2012年10月24日発売 【第17回】Webアプリケーションのパフォーマンス改善……藤原 俊一郎,Japan Perl Association[監修]
iscon二連続優勝に導いた人によるパフォーマンスチューニングの極意が書いてあるのですごいですね
Vol.72 Amon2 tokuhirom
よくよく考えたら WAF の話とか出てきてなかったし、 Amon2 は少なくとも日本では一般的な物になったので改めてきちんと紙に出しましょう。という
Vol.73 なにかなー?だれかなー?
誰にお願いしよう
シーズン4
へとつづくのかな。。。!?そろそろ naoya さんの出番とかこないかな

改めて見直してみるとネタ被ってなくてすごいw
あとこれ、一人だけで絶対に書けない濃度だからやばいな、これ発案した人凄いなと思いました。


WEB+DB PRESS Vol.71
WEB+DB PRESS Vol.71
posted with amazlet at 12.11.05
竹迫 良範 Jxck じょさん 後藤 秀宣 藤原 俊一郎 奥野 幹也 堤 智代 森田 創 中島 聡 A-Listers はまちや2 相澤 歩 柴田 博志 池田 尚史 梅澤 雄一郎 九岡 佑介 近藤 宇智朗 佐藤 鉄平 mala
技術評論社
売り上げランキング: 395
Posted by Yappo at 14:03 | Comments (0) | TrackBack