> 22 сент. 2016 г., в 12:39, Ruslan Zakirov <[email protected]>
> написал(а):
>
>
> 2016-09-22 11:16 GMT+03:00 Eugene Ponizovsky <[email protected]
> <mailto:[email protected]>>:
> Руслан, если я правильно все рассчитал, то этот callback не будет вызван,
> если не осталось ни одной нормальной ссылки на $self, так как сам callback
> помещается в $self далее по коду, и он будет уничтожен вместе с последней
> ссылкой на объект клиента. Есть ли у Вас пример, в котором это приводит к
> ошибке?
>
> Возможно вы правы. Это были домыслы на основе чтения кода.
>
> Вот натолкнулся на более актуальную проблему и это уже в тестах:
> EV: error in callback (ignoring): Can't call method "_process_reply" on an
> undefined value at
> /Users/ruz/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/AnyEvent/RipeRedis.pm
> line 448, <DATA> line 2231.
>
Хм. Да, действительно. При некоторых случаях ошибка воспроизводится. Внес
небольшой фикс. Спасибо за репорт.
https://cpan.metacpan.org/authors/id/I/IP/IPH/AnyEvent-RipeRedis-0.27_01.tar.gz
> Это как раз случилось из-за того что клиент прибиваю раньше времени. Ошибка
> конечно у меня, но она не привела к "Client object destroyed prematurely."
>
> Кстати как вы это решаете у себя? Я в большинстве случаев создаю коннект,
> выполняю ряд операций без callback'а и только на после последней передаю
> callback, где резолвлю promise (дергаю переданный callback). В некоторых
> случаях совсем нетривиально подсчитать какая команда будет последней.
>
Если выполнять простые операции (get, set, incr и т.д.), то последовательность
их выполнения совпадает с последовательностью вызова методов в коде, так как
они все выполняются через один коннект. Но для составных операций (например для
такой как eval_cached), последовательность выполнения может быть другой, так
как под капотом может быть выполнено две команды EVALSHA и следом EVAL.
В общем случае синхронизировать асинхронные операции можно через счетчик
операций. Например так:
my $oprn_num = 10;
my $reply_cnt = $oprn_num;
my @errors;
my $cv = AE::cv;
my $cb = sub {
my $reply = shift;
my $err = shift;
if ( defined $err ) {
push( @errors, $err );
}
return if --$reply_cnt > 0;
if ( @errors ) {
# обработка ошибок
}
else {
# выполняем код, который нужно выполнить, когда все асинхронные операции
# успешно выполнены.
}
$cv->send;
};
foreach ( 1 .. $oprn_num ) {
$client->execute( $cb );
}
$cv->recv;
Или воспользоваться таким модулем как Future https://metacpan.org/pod/Future
> --
> Best regards, Ruslan.
> --
> Moscow.pm mailing list
> [email protected] | http://moscow.pm.org
--
Moscow.pm mailing list
[email protected] | http://moscow.pm.org