[SP-pm] Passando uma string que contém o código de uma classe usando o Gearman

Daniel de Oliveira Mantovani daniel.oliveira.mantovani at gmail.com
Fri May 21 00:14:47 PDT 2010


Cometi um erro de digitação,

no, cliente_envia_classe.pl

Ao invés de ser:
my $result_ref = $client->do_task( "load_spider" => "@code");

é:
my $result_ref = $client->do_task( "load_spider" => "$code");

[]'s


2010/5/21 Daniel de Oliveira Mantovani <daniel.oliveira.mantovani em gmail.com>:
> Estou usando o Gearman para fazer programação distribuída. Para quem
> não conhece,
> http://gearman.org/index.php
>
> Eu quero fazer uma classe e essa classe ser executa em qualquer "worker".
>
> Para simplificar:
>
> arquivo:Foo.pm
>
> package Foo;
>
> sub new {
>  my $class = shift;
>  $class = ref $class || $class;
>  my $argv = {@_};
>  return bless($argv,$class);
> }
>
> sub foo {
>  my $self = shift;
>  $self->{'foo'} = "@_";
> }
>
> 42;
>
> fim:Foo.pm
>
> Bom, para usar essa classe normalmente fazemos,
>
> arquivo:teste.pl
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
> use 5.10.0;
> use Foo;
>
> my $o = Foo->new;
> say $o->foo(qw(Hello World));
>
> fim:teste.pl
>
> Certo, é isso que eu quero fazer mas o "Foo.pm" vai ser "dinâmico".
> Eu quero fazer programação distribuída e executar o "Foo.pm" que no
> caso será um Web Scrap. Ou seja eu tenho vários serviços[0] rodando em
> servidores no mundo inteiro.
> Analisando a arquitetura do Gearman, eu quero enviar uma "classe" para
> o meu worker, que no caso vai ser um Web Scrap. Por exemplo, um da
> Amazon.
>
>
> O worker funciona da seguinte maneira,
>
> arquivo:worker.pl
>
> use strict;use warnings;
> use Gearman::Worker;
> my $worker = Gearman::Worker->new;
> $worker->job_servers('xxx.xxx.xxx.xxx:4730');
> $worker->register_function( 'load_spider' => \&foo );
> $worker->work while 1;
>
> sub foo {
>    return(shift->arg);
> }
>
> fim:worker.pl
>
>
> e o cliente,
>
> file:cliente.pl
>
> use strict;use warnings;
> use Gearman::Client;
>
> my $client = Gearman::Client->new;
> $client->job_servers('xxx.xxx.xxx.xxx:4730');
> my $result_ref = $client->do_task( "load_spider" => "Foo" );
> print "${$result_ref}\n";
>
> fim:cliente.pl
>
> O resultado será, ao executar o cliente.pl:
> $Foo
>
> Até aqui ótimo, só que ao invés de passar simplesmente um arquivo para
> uma função, eu quero passar uma classe inteira com o meu Web Scrap.
>
> Um exemplo de como fazer isso localmente:
>
> arquivo:local.pl
>
> use strict;
> use warnings;
> use 5.10.0;
>
> open my $file,'<','File.pm' or die $!;
> my @classe = <$file>;
> eval "@classe";
> my $o = Foo->new;
> say $o->foo(qw(Hello World));
>
> fim:local.pl
>
> Vai imprimir, "Hello World". Eu quero deixar claro que eu *preciso*
> fazer as classes serem "dinâmicas", porque eu vou fazer o Web Scrap
> local. E quando eu quiser executa-lo eu simplesmente escolho o melhor
> servidor, que no caso o Gearman vai fazer isso (escolher o melhor
> servidor).
>
>
> Agora, como fazer isso, como está no local.pl, mandar a "@classe" para
> o worker ?
>
> arquivo:worker_carregar_classe.pl
>
> use strict;
> use warnings;
>
> use Gearman::Worker;
>
> my $worker = Gearman::Worker->new;
> $worker->job_servers('xxx.xxx.xxx.xxx:4730');
> $worker->register_function( 'load_spider' => \&foo );
> $worker->work while 1;
>
> sub foo {
>    eval shift->arg; print $@ if $@;
>    my $o = Foo->new();
>    return($o->foo("Bar"));
> }
>
> fim:worker_carregar_classe.pl
>
>
> Pronto, o worker vai receber a string que contém o pacote todo em
> "shift->arg" o eval vai executar o código que vai carregar a classe
> para memória e eu vou poder fazer Foo::new.
>
> O cliente para mandar a string que contém o código pacote, para o
> worker_carrega_classe.pl
>
> arquivo:cliente_envia_classe.pl
>
> use strict;
> use warnings;
> use Gearman::Client;
>
> my $client = Gearman::Client->new;
> $client->job_servers('187.22.189.149:4730');
>
> open my $spider, '<', 'Submarino.pm' or die $!;
> my @go_spider  = <$spider>;
> my $code       = "@go_spider";
> my $result_ref = $client->do_task( "load_spider" => "@code");
> print "${$result_ref}\n";
>
> fim:cliente_envia_classe.pl
>
> Pronto, isso seria perfeito e deveria funcionar. Mas não funciona,
> quando eu tento passar uma string que contém o código de uma classe.
> Simplesmente o worker não responde. Ele funciona perfeitamente se você
> passa só um argumento como, "hello" como no exemplo. O problema não é
> no worker, eu posso retirar a função que contém o eval, e só deixar um
> print "Hello World", por exemplo que continua não funcionando. O único
> modo de fazer funcionar é retirando o "@code" como parâmetro e
> colocando coisas como, "foo","bar". Se eu tento passar o código de uma
> classe ele não aceita, nem ao menos chega ao "eval".
>
> Gostaria da ajuda de vocês, para saber uma maneira de fazer o que eu
> citei acima.
>
> Obrigado
>
> []'s
>
>
>
>
> --
> "If you’ve never written anything thoughtful, then you’ve never had
> any difficult, important, or interesting thoughts. That’s the secret:
> people who don’t write, are people who don’t think."
>



-- 
"If you’ve never written anything thoughtful, then you’ve never had
any difficult, important, or interesting thoughts. That’s the secret:
people who don’t write, are people who don’t think."


More information about the SaoPaulo-pm mailing list