はちゅにっき

こっちのブログはまったり更新

FurlX::Coro を使ってみたかった

節電対応で休日が日・月になった hatyuki です。ということで、明日がおやすみ!

「DB から引っ張ってきた 5,000 件くらいの URL が、全部 HTTP Status Code 200 を返してくるか調べたいんだけど。」
という、なさそうでやっぱない依頼をうけたのでささっと書いてみることに。

ぱっと思いついたのはこんな感じ。

use strict;
use warnings;
use Furl;
use My::Util qw/ db /;
use Test::More;

my $furl = Furl->new;
my $itr  = db->search('tables');
while (my $row = $itr->next) {
    my $res = $furl->head($row->url);
    is $res->code, 200, $row->url;
}

done_testing;

で実行してみたら Furl は確かに早いんだけど、さすがにチェックする URL の数が多すぎてちょっと時間かかりすぎる感じ。
そーいえば id:gfx さんが

Released FurlX-Coro!
http://d.hatena.ne.jp/gfx/20110625/1308978199

なんて記事を書いていたなぁ。と思い出したので FurlX::Coro を使ってみることに。
参照先の記事に書いてある内容そのままですが、こんな感じになりました。

use strict;
use warnings;
use Coro;
use FurlX::Coro;
use Test::More;
use My::Util qw/ db /;

my $itr = db->search('tables');
my @coros;

while (my $row = $itr->next) {
    push @coros, async {
        my $furl = FurlX::Coro->new;
        my $res  = $furl->head($row->url);
        is $res->code, 200, $row->url;
    };
}

$_->joins for @coros;

done_testing;

Furl の代わりに Coro と FurlX::Coro を use して、あとは Coro っぽい書き方をちょっと加えるだけなので、すごく簡単ですね。
で、実行してみたら超はや、、、あれ?
「おい!Load Average が 300 超えてるぞ!」
あー。そういえば URL って全部同一ドメインだった!
ということで Coro::Semaphore も使うことに。
こんな感じ。

use strict;
use warnings;
use Coro;
use Coro::Semaphore;
use FurlX::Coro;
use Test::More;
use My::Util qw/ db /;

my $itr = db->search('tables');
my @coros;

my $semaphore = Coro::Semaphore->new(10); # 10 並列まで
while (my $row = $itr->next) {
    push @coros, async {
        my $guard = $semaphore->guard;
        my $furl = FurlX::Coro->new;
        my $res  = $furl->head($row->url);
        is $res->code, 200, $row->url;
    };
}

$_->joins for @coros;

done_testing;

今度こそ、早く安全 (?) に HTTP Status Code を確認することができました。
やったね!

えっ?確認すべき URL があと 100,000 あるの?なんか間違ってない。。。?
そんな週末。

結論

  • FurlX::Coro すごく便利
  • 同時接続数を制限しないと、鬼の形相で人が飛んで来る
  • Coro で同時実行数を制御するには Coro::Semaphore が便利
  • 外部のサーバには絶対にやっちゃだめ
  • PHP でも Coro したいんだけど。。。


むしろ PHP を Coro したい。

perlbrew 環境下で Alien::SVN をインストールする

どうしても Perl *1 から Subversion を操作する必要があったので、どうやら一般的なモジュールのようなので、以下のモジュールを使ってみることに。

Alien-SVN
http://search.cpan.org/~mschwern/Alien-SVN/

と思ったら perlbrew 環境下ではすんなり cpanm できなかったのでメモ。
Debian というか、パッケージシステムの問題 (?) というか。
Debian は Testing な wheezy。

Subversion はいつもどおり aptitutde でインストール。

# aptitude install subversion

これで libsvn-perl も同時にインストールされるため、システムの Perl を使っている分には別途で Alien::SVN をインストールする必要はないみたい。
今回は perlbrew 環境下で、システムにインストールされている Perl とは違うバージョンを使っていたため、cpanm することに。
ただし、単純に

$ cpanm -l extlib Alien::SVN

すると、apr / apr-util / neon *2 がないよ!と言われて make に失敗するので

# aptitude install libapr1-dev libaprutil1-dev libneon27-gnutls-dev

すれば、インストールできるようになりましたとさ。
やったね。

Alien::SVN の使い方は、またの機会に。
「いまさら Subversion ?」は、なしだよ!

*1:PHP でもいいんだけどー。

*2:neon は必須ではないです。

Ark + DBIx::Skinny + Text::Xslate (+Tiffany) で NoPaste 的な何か

というわけで、だいぶ前につくってみたものですが、恥ずかしながらアップロードしてみたり。
いろんな機能を使うために、いろいろと遠回りしてたりもします。

Ark-Paste
http://github.com/magicalhat/p5-ark-paste

Catalyst + DBIC (+ Template-Toolkit) にくらべると、Ark + DBIx::Skinny (+ Text::Xslate) は軽くていいですね!

そのうちさくらの VPS サーバで動かしてみようと思います。

解説という名の言い訳も、後ほどしてみたいなー。

Shibuya.pm #14 にいってきました

今回のテーマは「IPAJPAは違う団体です」ということで、IPAJPA の両者が参加。
ということで、いつも通りてきとうなまとめ。

Perl 6 Language Update (dankogai さん)

  • 大まかには Perl6 も Perl5 もあんまり変わらないよ
    • 構文とかだいぶ違うようにみえるけど。。。
  • "Rakudo Star" がリリースされたけど、今はまだだいぶ遅い
    • 単純なスクリプトでも 5 と 6 では大きな差がある
    • それでも昔よりはだいぶ早くなった
  • sub の中に sub (Private Function) がかけるようになった。
sub fizzbuzz {
    sub fizz { };
    sub baz { };
}
  • try - catch が使えるようになる
    • まぁ、前から eval { }; if ($@) { } があったけどね
    • "try" の中に "CATCH" があるんだけど
      • どうしてこうなった
      • 変数のスコープ考えるとこっちのが便利じゃない?(会場内の Twitter から)
try {
    die;

    CATCH {
        say $@;
    }
}
  • そのた Perl6 の機能などのご紹介
    • 無限リスト
    • スマートマッチ
    • 後付ではない Object 指向
      • Moose で見慣れた記法
      • アロー(->)じゃなくてドット(.)
    • 正規表現の強化

ぼくのかんがえたさいきょうのYAPC::Asia (941 さん)

  • チケットかってね!

JPA活動報告 (lestrrat さん)

  • 今年も YAPC の運営やります
  • 地道にいろいろ活動してます
  • 地方 Mongers との交流はこれからも続けていきたい
  • Tシャツかってね!

memcached injection (佐名木 さん)

  • 最近某 SNS の memcached に障害が発生して話題になった
    • 今回はその件とは別
  • memcached は非常に簡単なテキストベースのプロトコル
    • 基本的には、Key と Value をテキストで送信して Store しているだけ
  • キー名のエスケープは memcache 側ではやっていない
    • Server / Client 側でサニタイズ処理をしてあげる必要がある
  • 各言語のライブラリによって、サニタイズ処理をしている場合と、していない場合がある
    • 処理していないライブラリを使う場合は、必ず自前で処理してね
    • Perl の Cache::Memcached はサニタイズしてないよ!
  • とはいえ、キーの値がユーザが指定した任意の値になるようなアプリは少ないはず
  • キーに対する Injection といえば SQL Injection
    • Colum に Injection できるというものが過去にあった。が非常に稀なケース
SELECT * FROM table WHERE column = 'hoge';
--                 ↑ ここが、ユーザが任意で指定できちゃうようなアプリ
  • memcached を使った攻撃方法があるって書いたら中国から大きな反響があった
    • どうやら攻撃が好きみたい
    • 攻撃されないようにね!

memcached の運用監視ノウハウ (kazeburo さん)

  • mixi で memcached 周りの障害が発生したことを Twitter で報告した
    • 大きな反響があり、多くの方に原因究明をしていただいた
    • それはそれでいいことだと思った
  • 障害から分かったことは memcached を安定稼動させることの重要性
  • 安定稼動とは PDCA サイクルである
  • 監視とは継続的なテストである
    • 継続的にテストするためには
      • 自動化しようね
      • 可視化しようね
  • どうやって監視していく?
    • 直近に実行したコマンドの終了ステータスを監視する
$ COMMAND
$ echo $?
0  <- COMMAND の終了ステータス
    • cronlog 使うと非0の場合のみに STDOUT / STDERR を出力してくれるので便利
      • cronlog は github の kazuho さんのとこで!
    • netcat (nc コマンド) も便利だよ
    • crontab に仕掛けるコマンドを以下のようにする
cronlog -- nc -w 1 -z localhost 11211 # nc の終了ステータスが 0 以外のときにメールがくる
    • コマンドに対する応答が返ってくるかを監視する
      • Nagios の Plugin 化してしまう
    • status を使ってコネクション数を監視する
    • daemontools とか使ってると障害を検出できないかもしれないよね
      • supervisor によって再起動されるため、監視と監視の間に障害が発生すると補足できない
      • uptime を使ってみてはどうか

身につけておきたい、今そこにあるシステムの救命措置 (IPA 園田 さん)

  • 脆弱性の報告は順調に増えている (良いことなのか、悪いことなのか)
    • DNS特需とかあって、急激なグラフの部分もあるけどね
  • 90日以上の長期化案件がけっこうある
    • 1年放置とかザラ
    • 1000日以上脆弱性が放置されているパターンもある
  • どうすんのこれ?を今考えてたりする
    • 稼働中のシステムの脆弱性の大半はエスケープのミス忘れたとかそんなもん。なのになんで直らない?
    • いっそのこと「脆弱なサイトはこちらでーす」と公開してしまいたいくらい
    • 現場的にはどんなプロセスなら現実的なの?
      • ネックなのは予算?技術?体制?顧客の理解?
  • 以下パネルディスカッション
    • 941 さんのすばらしいまとめ -> http://togetter.com/li/55216
    • Twitter の脆弱性もどんどん悪質化した
      • 公開してしまうと本気で攻撃しちゃう
    • IPA から報告をいれたくても報告先にたどり着くのにえらい時間がかかる場合がある

Perl 1,2,3,4 の歴史 (前田 さん)

  • Perl1 〜 Perl5 までの歴史
  • Tokyo.pm の大きな功績は miyagawa さんに Shibuya.pm を作らせたこと

Perl + Android (naoya さん)

  • SL4A
  • Perl だと Android.pm
    • 実際は localhost に JSON-RPC をしている
  • 結構簡単に echo サーバ / echo クライアントがかけたよ
    • 突き詰めると面白そう

Data::MessagePack (tokuhirom さん)

  • バイナリデータを永続化する
  • いろんな言語に対応している
  • Perlシリアライズする手法はいくつか
    • Storable
      • Perl 標準でついてくる
      • bless した Object とか Store できちゃう
      • データサイズすごく大きい
      • おそい
    • JSON(::XS)
      • はやい
      • PurePerl でも動くし XS でも動き、環境によって切り替わる
      • データサイズ大きい
    • Data::MessagePack
      • すごくはやい (gfx さんのチューニング)
      • データサイズが小さい
      • PurePerl もサポートした (makamaka さん)
      • bless したデータとかは Store できないよ

String::Filter 構造化テキストの正しいエスケープについて (kazuho さん)

  • XSS がおきにくい設計をするのは大切だよ
    • バグがあってもいいから、セキュアなコードを書きましょう
  • Parse してから Encode するが原則
    • Parser にどんな問題があっても Encode さえしっかりすれば XSS はおこらない
  • Encode 処理は最後にまとめて行ないましょう
  • Xslate などの適切にエスケープ処理をしてくれる Template Engine を使いましょう

Perl Parser Hacks vol.2 (gfx さん)

  • 3倍高速化の gfx さんが、まさかの 3倍トラブル
  • 構文木をごにょごにょしてしまうお話
    • 5.12.0 での実装 (pluggable keyword) は再コンパイルが必要 (?) で使いづらい
    • 5.13.5 での実装はそれが不要で面白いことができるんじゃないか
      • をデモを交えるはずが。。。
  • YAPC ではお待ちかねの Xslate について話しますよ

さいごに

今回も「偶然」出張だったので参加してきました!
うん、偶然。
というわけで、懇親会とかには参加できなかったのですが楽しかったです。
脆弱性あたりの話は難しそうですね。脆弱性の指摘があったときに、すぐに立ち回れる企業と、そうでない企業とありそうですし。
# Twitter にもでてたけれど、外部業者にお願いしていた場合とか
そう考えると、自分のとこもすばやく立ち回れるんだろうか。。。といった疑問も。
そういった意味でも kazuho さんのバグがあってもいいから、セキュアなコードを書くというのは、本当に意識していかなければいけないなぁと思います。
それでも見つかってしまう脆弱性については、すばやく対応することが大切ですよね!
Template Engine がその辺はよしなにしてくれるから!と知っていても、脆弱性についてきちんと理解しておくことも大切ですね。

Xslate に入門しつつ Tiffany とか Ark とか

最近はもっぱら PHP を書いている magicalhat です。
それでもやっぱり Perl が好き。

というわけで、id:gfx さんの新作 Xslate という新しいテンプレートエンジンが登場したとか、それがすごく速いとか、そんなウワサを耳にしたので入門してみることに。
ついでなので、最近鋭意お勉強中の Ark から Xslate を使ってみることにしました。
参考にしたのは、id:punitan さんが Blog で紹介されていた http://xslate.org/intro.html のサンプルプログラムです。
# いつものことですが、参考というよりもパクりです

Ark::View::Xslate をつくってみる

Ark が標準でサポートしているのは JSON / MT (Text::MicroTemplate::Extended) / TT (Template-Toolkit) のみなので、新しく Ark::View::Xslate をつくってみることに。
といっても、既存の Ark::View::MT をそのままコピーペして。。。
↓こんなかんじで完成。

Ark からつかってみる

作成した Ark::View::Xslate を使って http://xslate.org/intro.html のサンプルと同じ出力を得るための Ark のアプリケーションはこんな (↓) かんじに*1

Ark から Xslate してみる版
http://github.com/magicalhat/p5-axtest/tree/xslate

いまどき Controller にロジックを書くひとって。。。

なんかスマートじゃないよね。。。

何も考えずに Ark::View::MT を参考にコピペしてしまったので、なんか設定項目がたくさんあってスマートじゃないよねぇ。とか考えていたら

http://twitter.com/__gfx__/status/20446194779
http://twitter.com/__gfx__/status/20446202825

まったくもってその通りですね!
というわけで、options だけを残して。。。
と思っていたら、id:tokuhirom さんのこの記事が。

Tfall あらため Tiffany
http://d.hatena.ne.jp/tokuhirom/20100809/1281350651

Tiffany をつかってみる

ちょうどいいタイミングだし使ってみよう。
というわけで、今度は Ark::View::Tiffany を作ってみました。
↓こんなかんじ

この機会にちょっと Ark のソースコードを追いかけてみたりもしました。
が、それはまたの機会に。

Tiffany から Xslate / MT してみる

Tiffany は決して Template Engine を切り替えるものではない*2ので、使い方としては間違っている気がしますが、とりあえず Tiffany の機能を堪能するために、MT と Xslate が同じ View クラス (Ark::View::Tiffany) から利用できることを確認してみることに。
こんなかんじ↓ *3

Ark から Tiffany 経由で Xslate / MT してみる版
http://github.com/magicalhat/p5-axtest/tree/tiffany

Tiffany を使うことによるメリットは、WAF ごとにいちいち WAF::View::TemplateEngine を作成しなくても、いろんな Template Engine を利用できることですね。
実際に、今回の例だと Ark::View::Xslate を作らずに Xslate に対応することができ、また Ark::View::MT を利用することなく、MT の Template Engine を利用することができました。
Ark(::View::Tiffany) を使う場合は以下のように設定をすれば、(Tiffany が対応している) 好きな Template Engine を利用できます。
たぶん TT とかでも使えるとおもうけど、確認はしてないです。

MyApp.pm
package MyApp;
use Ark;
our $VERSION = '0.01';

use_model 'MyApp::Models';
my $home = MyApp::Models->get('home');

# Xslate を使う場合
config 'View::Tiffany' => {
    view => 'Text::Xslate',
    extension => '.tx',
    options => {
        path => $home->subdir('root', 'tmpl'),
        cache_dir => $home->subdir('tmp', 'xslate_cache'),
    },
};

# MT を使う場合はこっちを有効に
#config 'View::Tiffany' => {
#    view => 'Text::MicroTemplate::Extended',
#    options => {
#        include_path => [ $home->subdir('root', 'tmpl') ],
#        template_args => {
#            stash => sub { __PACKAGE__->context->stash },
#        },
#    },
#};

1;
MyApp::View

View 側は Tiffany がよしなにしてくれるので、名前を確保するだけ。
うん。スッキリ。

package MyApp::View;
use Ark 'View::Tiffany';

1;

完成?

とりあえずは完成したっぽいけれど、Ark::View::MT には、Form の Action がある場合には HTML をエスケープせずに、そのまま出力するように特殊な処理が入っており、この辺の Template Engine 固有の処理を、どうやって対処するのが適切なのかは考えどころかな?
などなどと思っています。

で、速いの?

むずかしいことはよくわかりませんがすごくはやいみたいです><

*1:Module をそろえて plackup すれば http://localhost:5000/ からアクセスできるよ

*2:イベントループ系のモジュールに対する AnyEvent みたいな立場?

*3:plackup して http://localhost:5000/xslate にアクセスすると Xslate で、http://localhost:5000/mt にアクセスすると MT で表示するよ

PerlCasual#02 へいってきました

Twitter では訳あって hatyuki に改名した magicalhat です。
懲りずにまた遠方から参加させていただきましたので、超簡単にメモ。
てゆーか殴り書きれべるだけど。

オープニング

  • Perl いいよね。CPAN いいよね。
    • Author のキャラクタを垣間見れるのがいい
    • Author への憧れは、プログラマとしてのモチベーションでもあるよね

Perl の真価は CPAN
っていうけれど、それをモジュール数ではなく、Autor として考えることに感動。
Perl の「コミュニティ」がすごいっていうのは、そういった人の繋がりが大きいからということですね。

Live Coding

  • Perlism っぽいものを作ってみよう
    • CPAN フル活用ですばやくいろいろ作れるよ
    • ドキュメントは perldoc で!
$ perldoc Module::Name
$ perldoc -f function_name  (←Perl の組み込み関数のヘルプ)
    • SYNOPSIS を見れば使い方は一通り分かるね!

ぷりんとでばっぐさいきょー。

LL

Vim Plugin のおはなし
  • snipMate.vim
    • snipet べんりだよ!
  • ref.vim
    • perldoc ひらけるよ!
  • prove.vim
    • prove できるよ!
JSON のおはなし
  • JSON 使うときにはエンコード・デコードに気をつけてね!

外からきた言葉を Perl 語に decode
外のひとが分かる言葉へ encode

Emacs のおはなし
  • TEXTAREA の内容を emacs で編集しよう
    • 以外なところに HTTP プロトコルが使われているよ

Vim

  • モード切替があるので変態
  • 設定 & Plugin でいろいろ拡張できるので、ぜひ試してみてね!
  • Perl::Tidy (ぱーるたいでぃ)

Emacs

  • モード切替がない分 vim より変態じゃない
  • anything.el という革命児 (インタフェース) を使うことでハッピーなプログラミングを

perlbrew

  • http://xrl.us/perlbrew
    • いろんなバージョンの Perl を自分の $HOME 以下にインストールできるよ
    • どちらかといえば開発者向けかもしれない
    • local::lib /cpanm / perlbrew Perl はもっとポータブルに!

懇親会

知らない人だらけでした><
ご挨拶できなかった方もいましたが、いろいろな方とお話することができました。
やっぱ少し輪に入りづらい部分もあるんですが。。。(性格的な意味で)
なんか Perl バリバリな方ばかりかとも思いましたが「メインは PHP なんですよ」という方も多く、本当にカジュアルに楽しめました。
Web に目がいきがちだけれど、やっぱり簡単なツールとしての需要も高いんだなぁ。
と、お話をしている中でも実感しました。

これから Perl を覚えたい!という方にはちょっと敷居が高かったのかもしれませんが、懇親会で親しくなれればすぐに覚えられそうですね><
なくらい、すごく人に恵まれた言語ですね。

bless { relationship => $humans }, 'Perl';

な感じ?

まとめ

もうこうなったら「とーいところから来る人」と言われるよう、継続的に参加していきたいです。
あと、hide-k さんのあばら骨の行方がひっそりと心配でした。

DBIx::Skinny で update_or_create

ができたらいいなー。
と思ったので、作ってみました。

DBIx-Skinny-Mixin-UpdateOrCreate
http://github.com/magicalhat/p5-dbix-skinny-update_or_create

DBIx::Class だと、利用することも多いので Skinny でもあれば便利かな?と思ってみたり。
オマケとして、UPDATE じゃなくて INSERT した場合には、関連するレコードも更新しなくちゃ!
とゆーパターンも想定して、DBIx::Class でも利用できる in_storage というメソッドもつけてみました。

my $row = Proj::Model->update_or_create(
    table_name => { id => 1} => { name => 'magicalhat'}
);

# -- insert したならば、別の処理をする
unless (Proj::Model->in_storage) {
    my $reg = Proj::Model->create(
        register_table => { registered_id => $row->id}
    );
}

とりあえず、自分が使う分にはべんり!
Mixin 簡単に作れて面白いですね。これからもなんか気づいたら作ってみよー。