継続でget_multiとかまとめたい。

memcachedのgetsとかJSONRPCのbulkリクエストとかを出来る限り透過的にまとめたい。
Apps::MemcachedはCache::Memcached::Fastのラッパーをイメージしてくだしあ。

Scope::Session::start {
    my $promised = Apps::Memcached::Promise->new;

    for my $c (1..5){
        $promised->reserve(sub{
            my $rand = 5;
            for( 1..$rand) {
                my $result = Apps::Memcached->new->get("hello:$c:$_");
                ::ok "$c-$_ value";
            }
        });
    }
    $promised->join;
};

こんなかんじで、getしか書いてないんだけど、その時点で
ステートを停止して、一通り検査し終えたところでgets!して、
復元して最後まで回すみたいなやつやりたい。

試しに書いてみた:

package Apps::Memcached::Promise;
use strict;
use warnings;
use Apps::Memcached;

use Coro;
use Data::Util;

sub new {
    return bless {},shift;
}

sub reserve {
    my ($self,$logic) = @_;
    $self->{_reserved} ||= [];
    push @{ $self->{_reserved} },$logic;
}



sub join {
    my ($self) = @_;
    no warnings qw/redefine/;
    my @keys;
    local *Apps::Memcached::get = Data::Util::modify_subroutine(
        Apps::Memcached->can('get'),
        around => [
            sub {
                my ( $origin, $self, $key ) = @_;
                push @keys, $key;
                cede;
                return $origin->($self,$key);
            }
        ]
    );
    my @reserved = @{ $self->{_reserved} };
    my $wait = scalar @reserved;
    my @threads = map {
        my $logic = $_;
        async {
            cede;
            $logic->();
            $wait--;
        };
    } @{ $self->{_reserved} };
    while( $wait){
        cede;
        if( @keys){
            Apps::Memcached->new->get_multi(@keys);
            warn "get_multi keys:". join ',',@keys;
        }
        @keys = ();
    }
    return ;

}
1;
get_multi keys:hello:1:1,hello:2:1,hello:3:1,hello:4:1,hello:5:1 
ok 1
ok 2
ok 3
ok 4
ok 5
get_multi keys:hello:1:2,hello:2:2,hello:3:2,hello:4:2,hello:5:2 
ok 6
ok 7
ok 8
ok 9
ok 10
get_multi keys:hello:1:3,hello:2:3,hello:3:3,hello:4:3,hello:5:3 
ok 11
ok 12
ok 13
ok 14
ok 15
get_multi keys:hello:1:4,hello:2:4,hello:3:4,hello:4:4,hello:5:4 
ok 16
ok 17
ok 18
ok 19
ok 20
get_multi keys:hello:1:5,hello:2:5,hello:3:5,hello:4:5,hello:5:5 
ok 21
ok 22
ok 23
ok 24
ok 25
1..25