[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:09:55 PDT 2010
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."
More information about the SaoPaulo-pm
mailing list