TOP>2008年05年

2008年05月30日

今日の英語

#moose で hi というと que tal, tokuhirom などと話かけられるが、これは how are you の意味なので動転してはいけない。

スペイン語らしい。 id:miyagawa++

2008年05月27日

DJabberd の簡単な使い方

Wassr というすばらしいサイトがあるのですが、そのサイトでは XMPP でユーザーの更新情報を得ることができたり、発言情報をえたりできます。

このサイトで、それを実現させているのは、bradfitz の DJabberd というソフトウェアみたいです。これを使うと、容易に XMPP Server を構築することができます。Perl でできているので、割と簡単につくれます。もちろん bradware なので、bradware っぽい感じではあります。わからないことがあったら Livejournal のコードを読む必要があるので要注意です。

DJabberd は Danga::Socket を使った IO 多重化の1スレッドで動いています。Danga::Socket で構築されていますので、Gearman::Client::Async を使うことができます。というか、基本的に重い処理はすべて Gearman にやらせるようにしないと、サーバーがふんづまりますので、基本的にはすべての処理は Gearman にやらせるようにします。


さて、そんな DJabberd ですが、Wassr では

  • Wassr::DJabberd::RosterStorageAlwaysBoth
  • Wassr::DJabberd::Bot
  • Wassr::DJabberd::AdminExtension

という3つのモジュールを定義しているようです。


RosterStorageAlwaysBoth というのは、とりあえず話しかけてきた人を全員友達扱いにします。


Bot は、その名のとおりボットのコアです。DJabberd::Bot を継承しています。DJabberd::Bot はソース読まないと使い方わからないので、がんばって解読します。基本的には process_text というメソッドを上書きすればいい。それだけです。

    # $text is flagged utf8.
    # $from is DJabberd::JID
    # $from->as_bare_string; : jid string
    # $ctx  is DJabberd::BotContext
    # $ctx->reply required 'flagged utf8 string'

というような引数の状況でよばれます。jid というのは、Jabber ID の略で、ユーザーの識別符号ですね。DJabberd の中では DJabberd::JID というオブジェクトで表現されています。

さて、これで済めば、なにも問題はないのですが、DJabberd::Bot はエラーの処理がちゃんとできてなくて、エラーパケットもそのまま process_text メソッドにわたってきます。しかしながら、エラーパケットであるという情報を得る手段が process_text の引数にはありません。なので、send_stanza メソッドを ad-hoc に拡張しています。

sub send_stanza {
    my ($self, $stanza) = @_;

    if ($stanza->isa('DJabberd::Message')) {

######### XXX START TOKUHIROM PATCH
        if ($stanza->attr('{}type') ne 'chat') {
            warn "unknown packet type " . $stanza->attr('{}type');
            return;
        }
######### XXX END TOKUHIROM PATCH

以下略


AdminExtesion というのは、DJabberd の admin port(perlbal の admin port みたいなもの) のコマンドを拡張しているだけの存在です。DJabberd::Connection::Admin::CMD_* を定義して、admin port から情報を流し込めるようにしています。

2008年05月26日

メンテナ以外に実行させたくないテストを設置する簡単な方法

22:56 tokuhirom: http://perl-mongers.org/2008/05/typo-and-test-spelling.html
22:56 tokuhirom: これなんだけど
22:57 tokuhirom: 俺の pmsetup だと、MANIFEST.SKIP に ^t/9\d_.*\.t って書いて skip してある
22:57 tokuhirom: たぶんこれは、miyagawa さんのバージョンからぱくってきたような気がする。
22:58 tokuhirom: miyagawa さんか yappo さんか typo さんか、そのへん。
22:58 tokuhirom: (つまり、pmsetup 公開している人のうちのだれか。
22:58 tokuhirom: >tomyhero さん
22:58 typester: しかしいないようだw
22:58 tokuhirom: なぬ

ENV で分岐させてもいいんだけど、いちいち設定するのめんどいから 9/\/id_*.t を全部スキップしちゃうとかいう風に命名規則をつくると楽。


とかおもってたんだけど、最近は xt/ っていうディレクトリをつかう流れだそうな。一回聞いてたんだけどさっぱり忘れてた。

see also:

2008年05月06日

[moose][perl]Moose の traits がすばらしすぎるの件

みなさんこんにちは。Roppongi.PM の id:tokuhirom です。あいかわらず Moose よんでます。stevan のコードはわかりやすいのですが、普段あんまりつかわないような概念が多くて、その概念を理解する方に時間がかかりがちですね。

さて、本題です。

has の metaclass アトリビュートはたしかに便利なのだが、この手法だと、再利用性にとぼしいです。複数の機能をもったものを同時につかうことができないですね。

どちらかというと、アトリビュートのメタクラスを指定する感じじゃなくて、アトリビュートのメタクラスに Role をぶっこめた方が便利だなあ、と誰でも思うはず。

そんなあなたのための機能が、traits です。これは Moose::Cookbook にもまだのってない機能なので、あまり知られてないかもしれません。

↓のようにして trait は定義します。基本的に定義の仕方は通常のMoose::Role とおなじです。

package My::Attribute::Trait;
use Moose::Role;

has 'alias_to' => (is => 'ro', isa => 'Str');

after 'install_accessors' => sub {
    my $self = shift;
    $self->associated_class->add_method(
        $self->alias_to, 
        $self->get_read_method_ref
    );
};

install_accessors メソッドの after を hook して、alias を定義しています。とても簡潔ですばらしいですね。

これをつかうときは、こんなかんじですなー。

package My::Class;
use Moose;

has 'bar' => (
    traits   => [qw/My::Attribute::Trait/],
    is       => 'ro',
    isa      => 'Int',
    alias_to => 'baz',
);

んで、これが実際にどうやってつかわれるかというと、

my $anon_class = Moose::Meta::Class->create_anon_class(
  superclasses => [ 'Moose::Meta::Attribute' ],
  roles        => [ qw/My::Attribute::Trait/ ],
  cache        => 1,
);
$anon_class->new(
  bar => (
    is       => 'ro',
    isa      => 'Int',
    alias_to => 'baz',
  )
);

ってな感じですな。匿名クラスはこんなところでも活躍していますねー。

基本的には metaclass 指定するよりは traits つかうのがよさそうですね。