2013-07-01 2 views
0

Прежде всего я новичок в Perl и Mojo, так что я сделаю все возможное, с этим ..: DMojolicious REST + IOLoop одновременное обслуживание

Проблема заключается в том, что мне нужно работать параллельно, поэтому этой службе необходимо обрабатывать несколько вызовов каждую секунду. Эта служба позволит другим службам подключаться через REST для загрузки и обработки файлов. Я делаю некоторые тесты по этой идее без успеха.

Я тестировал около Mojo :: IOLoop, но я думаю, что я неправильно понял некоторые понятия о том, что, поскольку каждая реализация с использованием циклов и таймеров идет совершенно неправильно ...

На самом деле мой рабочий процесс идет здесь :

(1) Получить REST вызов

(2) Проверьте URL при условии над MongoDB

(3) Скачать файл associed для этого Монго объекта.

Так на самом деле это работает, но я не могу видеть, как реализовать это для того, чтобы работать параллельно ...

#!/usr/bin/env_perl 
use Mojolicious::Lite; 
use MongoDB; 

my $mongo  = MongoDB::MongoClient->new(host => 'xxxx.mongohq.com',port => 'xxxxx',  username => 'xxxxx', password => 'xxxxx', db_name => 'xxxxx'); 
my $database = $mongo->get_database('xxxxx'); 
my $collection = $database->get_collection('xxxxx'); 

any [qw/ get post /] => '/:action/:objid' => sub { 

    my $self = shift; 

    #Parsing objectid... 
    my $objectid = $self->param('objid'); 
    my $id = MongoDB::OID->new(value => $objectid); 

    my $all = $collection->find({_id => $id}); 
    my $dts = $all->next; 

    download($dts->{parsedoc}->{url},"final_name.xml"); 

}; 

app->start; 

sub download { 
    say "Starting new download.."; 
    my $ua = Mojo::UserAgent->new(max_redirects => 5); 
    my $tx = $ua->get($_[0]); 
    $tx->res->content->asset->move_to($_[1]); 
    say "Download ends."; 
} 

Что является лучшим способом для реализации IOLoop здесь? Я использовал несколько примеров таймера mojo, но, возможно, мне нужно изменить порядок потока приложений? Заранее спасибо.

+0

IOLoop не работает параллельно, но работает без блокировки. Таким образом, вам нужен неблокирующий клиент Mongo. Я знаю, что автор Mojolicious писал письмо под названием Mango, но в настоящий момент он находится в альфа-состоянии. –

ответ

2

Как я упоминал в своем комментарии, Mojo :: IOLoop не относится к параллелизму, но с циклами событий. Это означает, что операции, которые могут занять много времени, могут быть запущены, а затем продолжаться только один раз, без блокировки других процессов. В вашем примере оба вызова Mongo и загрузка - это такие длительные процессы, которые можно захотеть вставить в цикл событий. Mojolicious :: UserAgent не блокируется при использовании с обратным вызовом (действие, вызванное после завершения операции). Чтобы сделать то же самое с Mongo, вам нужно будет убедиться, что ваша библиотека Mongo может использоваться неблокирующимся способом.

Я издевался над небольшим примером, который игнорирует часть Монго (упражнение для читателя) и использует UserAgent неблокирующим способом.

#!/usr/bin/env perl 
use Mojolicious::Lite; 

helper download => sub { 
    my ($c, $url, $target) = @_; 
    my $ua = $c->app->ua->max_redirects(5); 

    say "Starting new download ($url) ..."; 
    $ua->get($url, sub { 
    my ($ua, $tx) = @_; 
    say "Finished download ($url) ..."; 
    $tx->res->content->asset->move_to($target); 

    say "File saved ($url --> $target)"; 
    $c->render(text => "File saved ($url --> $target)"); 
    }); 
}; 

any [qw/ get post /] => '/:action/:objid' => sub { 
    my $self = shift; 
    $self->render_later; # prevent auto-render 

    #Parsing objectid 
    my $objectid = $self->param('objid'); 
    #verify url here ... 

    # example url 
    my $url = 'http://www.google.com'; 

    $self->download($url,"final_name.xml"); 
}; 

app->start; 
+0

Спасибо, Джоэл, я думаю, в этом все дело. На самом деле я потерялся с концепцией Loop в Perl. Я тестировал ваше решение и отлично работаю, несмотря на некоторые таймауты бездействия (я думаю, что это происходит от «отложенного» рендеринга во время больших загрузок). – Courier

+0

Первая итерация этого кода только что показала «загрузка началась» и оставила загрузку для продолжения на стороне сервера. Это одна возможность. Другой - открыть веб-сайт клиенту, чтобы он был информирован о достигнутом прогрессе. Во всяком случае, это вся реализация. :-) –

Смежные вопросы