2011-07-23

[anyevent] 設定ファイルを SIGHUP で再読み込みする

最近は新進気鋭の Web Application Framework: Amon2 にも倣って、設定ファイルはPerlでハッシュリファレンスを返すように書いて、それをdoするようにしていて、シンプルで良いなと思っています。

AE_PerlIsm では、さらにブラックリスト追加などをTwitterへのStreming APIの接続を切らずに対応できるように、以下のようにシグナルにコールバック関数を登録する AE::signal 'HUP', \&callback を使って好きな時点で読み込めるようにしてみました。

この変更により、たとえば無名関数で書いたスパム判定ロジックを本体が動作したままアップデートすることも可能になります。

$config 内で $config を参照するのは循環参照でリークして良くない例なので修正。

hogehoge.pl (本体)

use strict;
use warnings;
use AnyEvent;
use AnyEvent::Twitter::Stream;

my $config_filename = 'hogehoge.conf.pl';
my $config;

reload_config();
$config or die;

main_loop();

sub main_loop {
    my $reload_config_t = AE::signal HUP => \&reload_config;

    my $streamer = AnyEvent::Twitter::Stream->new(
        username => $config->{username},
        password => $config->{password},

        on_tweet => sub {
            my $tweet = shift;
            return if $config->{is_spam}->($config, $tweet);

            ...
        },
    );

    AE::cv->recv;
}

sub reload_config {
    warn "reload_config";

    my $config_tmp = do $config_filename;

    if (defined $config_tmp) {
        $config = $config_tmp;
        warn "$config_filename: successfully loaded";
    } else {
        warn "$config_filename: syntax error: $@" if $@;
        warn "$config_filename: error: $!" if $!;
    }
}

hogehoge.conf.pl (設定ファイル)

use strict;
use utf8;
my $config = {
    username => 'hogehoge',
    password => 'foobar123',

    blacklist => [
        1111111,
        2222222,
        qr!3333*!,
    ],

    is_spam => sub {
        my ($config, $tweet) = @_;

        return $tweet->{screen_name} =~ /^spam/
            or $tweet->{screen_name} eq $config->{username};
    },
};