鈍足ランナーのIT日記

走るのが好きな5流のITエンジニアのブログ。

趣味の範囲は広いけど、どれも中途半端なクソブロガー楽しめるWebアプリを作ってあっと言わせたい。サーバーサイドPerl(Mojolicious)、クライアントサイドVue.js。Arduinoにも触手を伸ばす予定。

グローバル変数にMojo::Transaction::Websocketを格納しようとしたが・・・

さて、先日のチャットアプリ、1ワーカーでしか動かないを改造中。 こちらを参照ください。1Webアプリ(Mojolicious)=1ルーム=1ワーカー

以下、動かないソースをさらす。

package Chat::Web::Chat;
use Mojo::Base 'Mojolicious::Controller';
use DateTime;
use Encode qw/from_to decode_utf8 encode_utf8/;
use Cache::FastMmap;

my $cache = Cache::FastMmap->new();

sub index {
  my $self = shift;

  my $channel = $self->param("channel");

  $self->render('chat/index', {channel => $channel});
}

sub update_names{
  my $json = Mojo::JSON->new;
  my $channel = shift;
  my $clients = $cache->get($channel);
  my @names = ();
  for my $key(keys %$clients) {
    push @names, $clients->{$key}->{name};
  }

  for (keys %$clients) {
    $clients->{$_}->{tx}->send(
    decode_utf8($json->encode({
      names  => \@names,
    }))
    );
  }
}


# This action will render a template
sub echo {
    my $self = shift;
    
    my $channel = $self->param("channel");

    Mojo::IOLoop->stream($self->tx->connection)->timeout(600);

    $self->app->log->debug(sprintf 'Client connected: %s', $self->tx);
    my $id = sprintf "%s", $self->tx;

    my $clients = $cache->get($channel);
    if (!defined $clients){
      $clients = {};
    }
    $clients->{$id} =  {tx => $self->tx, name =>'',channel => $channel};

    $cache->set($channel, $clients);

    $self->on(message =>
        sub {
            my ($self, $arg) = @_;
            my ($key,$value) = split(/\t/,$arg);

            $self->app->log->debug(sprintf 'Client connected: %s', $self->tx);

            if ($key eq "name"){
              $clients->{$id}->{name} = $value || '名無し';
              update_names($channel);
              return;
            }

            my $msg = $value;

            my $dt   = DateTime->now( time_zone => 'Asia/Tokyo');

            my $json = Mojo::JSON->new;

            for (keys %$clients) {
                $clients->{$_}->{tx}->send(
                    decode_utf8($json->encode({
                        hms  => $dt->hms,
                        text => $msg,
                        name => $clients->{$_}->{name},
                    }))
                );
            }
        }
    );

    $self->on( finish => 
        sub {
            my $channel = $clients->{$id}->{channel};
            my $name = $clients->{$id}->{name};
            $self->app->log->debug('Client disconnected' || $channel || $name);
            delete $clients->{$id};
            update_names($channel);
        }
    );
}

1;

以下のようなエラーになります。

[Tue Jun  3 07:50:22 2014] [debug] GET "/aaa/echo".
[Tue Jun  3 07:50:22 2014] [debug] Routing to controller "Chat::Web::Chat" and action "echo".
[Tue Jun  3 07:50:22 2014] [debug] Client connected: Mojo::Transaction::WebSocket=HASH(0x80ebd070)
[Tue Jun  3 07:50:22 2014] [error] Can't store CODE items at /usr/lib/perl5/5.14/i686-cygwin-threads-64int/Storable.pm line 338, at /usr/lib/perl5/site_perl/5.14/i686-cygwin-threads-64int/Cache/FastMmap.pm line 737.

おそらくコードレフは格納できませんというエラーなんですが、 格納できたとしても、おそらく動かないのではないかな・・ 他のワーカーのWebsocketに対してゴニョゴニョできるようには思えないので、 ということで、このソースは没で違う方法を現在思索中。