2013-10-21 2 views
5

Mojoliciousのアプリケーションでは、リンクをクリックするとODTファイルをHTMLに変換しようとしています。シェルコマンドである "soffice"を使ってファイルを変換します。ファイルの変換には時間がかかります。私は進行状況を彼に通知するためにユーザーにステータスメッセージを送信します。 Mojo :: Logオブジェクトに書き込むことによって、これらのステータス更新メッセージを送信します。次に、私はこのログオブジェクトをEventSourceルートに登録します。MojoliciousでAnyEvent run_cmdを使用すると、「AnyEvent :: CondVar:再帰的なブロック待機が試みられました」

次に、ファイルをループし、AnyEvent :: Util run_cmdを使用して外部 "soffice"プログラムを実行します。

for my $file (@{ $filelist }) { 
    my $output_dir = './output_dir'; 
    my $cmd = "soffice --headless --convert-to html --outdir '$output_dir' '$file'"; 
    my $cv = AnyEvent->condvar; 
    my $w; 
    $w = run_cmd($cmd, 
       '>' => sub { my $out = shift; 
           &WriteToLog({ status => "cmd output '$out'..." }); 
           undef $w; 
           $cv->send; 
       }, 

       '2>' => sub { my $err = shift; 
           &WriteToLog({ status => "ERROR '$err'..." }); 
           undef $w; 
           $cv->send; 
       } 
      ); 

    $cv->recv; 
} 

かなりのコピーとメインAnyEventチュートリアルから貼り付け。変換するファイルがわずかしかない場合(約2または3)、すべてうまくいく。 EventSource接続を介して送信されたステータスメッセージは、クライアントブラウザに表示されます。その後、すべてのファイルが変換された後、Webページがレンダリングされます。

さらに多くのファイルを処理する場合、いくつかのファイルが変換され、スレッドタイトルのエラーメッセージが表示されます。

上記のコードを含むルートのルーティングは、このです:

my $initdocs = $r->under->to('docroute#initdocs'); 
$initdocs->get('/showdocs')->to('docroute#showdocs'); 

上記のコードは「initdocs」経路です。

何か助けていただければ幸いです。前もって感謝します。

+2

ただ将来、[tag:perl]タグを追加すると、より多くの人々があなたのモジョールな質問を見るのに役立ちます。 –

答えて

3

Creating single Thread Server with AnyEvent

AnyEvent recursive Blocking..

あなたはAnyEventを使用している場合は、通常CondVarsに対処する必要があります。 CondVarを使用すると、CondVarがトリガーされるときに呼び出されるコールバックを登録するか、recvを呼び出すか、CondVarがトリガーされるまでブロックされるコールバックを登録します。 Mojo :: Controllerのルートでは、ユーザーに表示するすべてのデータを取得するまで、ブロックすることをお勧めします。

はCondVarを使用して、以下の(架空の)例を見てみましょう:

未テスト:

get '/' => sub { 
    ... 
    my $cv = AnyEvent->condvar; 
    my $timer = AnyEvent->timer(after => 1, cb => sub { $cv->send(1) }); 
    my $result = $cv->recv; 
    ... 
}; 

あなたは述べ、ランタイムエラーが発生します "AnyEvent :: CondVar:再帰的なブロックが検出待ちます"。おそらくこれは、Morboもexit_guardとしてCondVarを使用しているため、無期限に実行することができます(CondVarでのブロックはメインループを実行する簡単な方法です)。

私のアプローチではなくCondVar上のブロッキング>ループを、このようなEVとして、特定のイベントループを使用し、EV-を呼び出すために、次のようになります。

EV->loop 
4

私はあなたがやろうとしているものだと思う呼び出すことですサーバースレッドの残りの部分をブロックせずにsoffice(ブロッキング)処理を実行します。私はAEの専門家ではないが、私はそれがrun_cmdのこととは思わない。しかし、それはfork_callのものに近いです。私は単純なブロッキング呼び出しを行うが、あなたが同じように簡単sofficeを呼び出すことができ、私の例では

#!/usr/bin/env perl 

use Mojolicious::Lite; 
use EV; 
use AnyEvent::Util 'fork_call'; 

any '/' => sub { 
    my $c = shift; 
    $c->render_later; 
    fork_call { `sleep 5 && echo 'hi'` } sub { 
    my $data = shift; 
    $c->render(text => $data); 
    }; 
}; 

app->start; 

:おそらく、何がやりたいことより、このようなものです。

クライアントに戻る前に複数のファイルを変換しなければならない場合があるので、優れたファイルMojo::IOLoop::Delayを使用してプロセスを管理したい場合があります。

#!/usr/bin/env perl 

use Mojolicious::Lite; 
use EV; 
use AnyEvent::Util 'fork_call'; 

my @jobs = (
    q{sleep 5 && echo 'hi'}, 
    q{sleep 5 && echo 'bye'}, 
); 

any '/' => sub { 
    my $c = shift; 
    $c->render_later; 
    my $delay = Mojo::IOLoop->delay; 
    $delay->on(finish => sub { 
    shift; $c->render(text => join '', @_); 
    }); 
    fork_call { `$_` } $delay->begin(0) for @jobs; 
}; 

app->start; 

もう一度、私は出力をキャプチャしてレンダリングコールに送信しますが、すべてのジョブが終了するまで待ってから戻ることを確認します。あなたの本当のユースケースに近い何かがあるかもしれない:

#!/usr/bin/env perl 

use Mojolicious::Lite; 
use EV; 
use AnyEvent::Util 'fork_call'; 
use Capture::Tiny 'capture'; 

any '/' => sub { 
    my $c = shift; 
    my $files = $c->every_param('file'); 
    $c->render_later; 
    my $delay = Mojo::IOLoop->delay; 
    $delay->on(finish => sub { 
    shift; $c->render(json => \@_); 
    }); 
    my $output_dir = './output_dir'; 
    for my $file (@$files) { 
    my $cmd = "soffice --headless --convert-to html --outdir '$output_dir' '$file'"; 
    fork_call { [ capture { system $cmd } ] } $delay->begin(0); 
    } 
}; 

app->start; 

これは、ルート(/?file=myfile&file=otherfile)へのparamとして渡された各ファイル名にとsofficeを実行します。その後、stdout、stderr、およびreturn codeは、jsonとしてクライアントにレンダリングされます(これは明らかに実行されていなければなりません)。

+0

私はちょうど(このポストがポップアップしたので)この質問が私にこのモジュールをcpanで作るよう促したと言いたいと思っています。https://metacpan.org/pod/Mojo::Ioloop::ForkCall –

関連する問題