proxyhunter
view release on metacpan or search on metacpan
lib/App/ProxyHunter.pm view on Meta::CPAN
}
close $fh;
return;
}
unless (defined $config) {
die $usage;
}
$config = App::ProxyHunter::Config->new(path => $config);
my $model = App::ProxyHunter::Model->new(
connect_info => [
sprintf('dbi:%s:database=%s', $config->db->driver, $config->db->name) .
($config->db->host ? ';host='.$config->db->host : ''),
$config->db->login,
$config->db->password,
{
%{$config->db->driver_cfg},
AutoInactiveDestroy => 1
}
],
schema_class => 'App::ProxyHunter::Model::Schema::' . $config->db->driver
);
if (defined $create_schema) {
while (my $query = $model->schema_class->get_create_query()) {
$model->do($query);
}
return;
}
for my $engine (@{$config->searcher->engines}) {
$engine = 'App::ProxyHunter::SearchEngine::'.$engine;
eval "require $engine"
or croak "Can't load search engine module $engine: $@";
}
if (defined $daemon) {
$SIG{INT} = $SIG{TERM} = sub {
unlink $daemon if length($daemon) > 0;
exit;
};
eval {
require Proc::Daemon;
};
if ($@) {
croak 'You need to install Proc::Daemon to perform daemonization: ', $@;
}
Proc::Daemon::Init({
work_dir => '.',
length($daemon)>0 ? (pid_file => $daemon) : ()
});
}
$model->update('proxy', {in_progress => 0}); # clean
my @coros;
if ($config->checker->enabled) {
push @coros, $class->_start_checkers($config, $model);
}
if ($config->rechecker->enabled) {
push @coros, $class->_start_recheckers($config, $model);
}
if ($config->speed_checker->enabled) {
push @coros, $class->_start_speed_checkers($config, $model);
}
if ($config->searcher->enabled) {
push @coros, $class->_start_searcher($config, $model);
}
$_->join() for @coros;
}
sub _start_checkers {
my ($class, $config, $model) = @_;
my @coros;
my @queue;
my $delay;
for (1..$config->checker->workers) {
push @coros, async {
my $type_checker = Net::Proxy::Type->new(
strict => $config->checker->strict,
noauth => 1,
url => $config->checker->http_url,
keyword => $config->checker->http_keyword,
https_url => $config->checker->https_url,
https_keyword => $config->checker->https_keyword,
);
$type_checker->http_strict(1);
my $speed_checker = $config->checker->speed_check ?
LWP::UserAgent->new(agent => 'Mozilla 5.0', timeout => 10, parse_head => 0) :
undef;
while (1) {
unless (@queue) {
if ($delay) {
Coro::Timer::sleep $delay;
next;
}
unless (@queue = $class->_get_queue($model, {checked => 0}, {order_by => 'checkdate'})) {
$delay = CORO_DELAY;
Coro::Timer::sleep $delay;
$delay = 0;
next;
}
}
my $proxy = shift @queue;
my ($type, $conn_time) = $class->_check($type_checker, $config->checker->types, $proxy)
or do {
$proxy->delete();
next;
};
$proxy->set('type', $type);
$proxy->set('conn_time', $conn_time);
if ($speed_checker) {
my $speed = $class->_check_speed($speed_checker, $config->speed_checker, $proxy)
or do {
$proxy->delete();
next;
};
$proxy->set('speed', $speed);
$proxy->set('speed_checkdate', DateTime->now(time_zone => TZ));
}
$proxy->set('checked', 1);
$proxy->set('checkdate', DateTime->now(time_zone => TZ));
$proxy->set('in_progress', \0); # force update
$proxy->set('success_total', 1);
$proxy->update();
}
}
}
return @coros;
}
sub _start_recheckers {
my ($class, $config, $model) = @_;
my @coros;
my @queue;
my $delay;
for (1..$config->rechecker->workers) {
push @coros, async {
my $type_checker = Net::Proxy::Type->new(
strict => $config->rechecker->strict,
noauth => 1,
url => $config->checker->http_url,
keyword => $config->checker->http_keyword,
https_url => $config->checker->https_url,
https_keyword => $config->checker->https_keyword,
);
$type_checker->http_strict(1);
my $speed_checker = $config->rechecker->speed_check ?
LWP::UserAgent->new(agent => 'Mozilla 5.0', timeout => 10, parse_head => 0) :
undef;
while (1) {
if ($delay) {
Coro::Timer::sleep $delay;
next;
}
unless (@queue) {
unless (@queue = $class->_get_queue($model, {checked => 1}, {order_by => 'checkdate'})) {
$delay = CORO_DELAY;
Coro::Timer::sleep $delay;
$delay = 0;
next;
}
my $sec_after_last_check = DateTime->now(time_zone => TZ)->
subtract_datetime_absolute($queue[0]->checkdate)->seconds;
if ($sec_after_last_check < $config->rechecker->interval) {
$delay = $config->rechecker->interval - $sec_after_last_check;
Coro::Timer::sleep $delay;
$delay = 0;
next;
}
}
my $proxy = shift @queue;
my $fail;
if (my ($type, $conn_time) = $class->_check($type_checker, $config->checker->types, $proxy)) {
$proxy->set('type', $type);
$proxy->set('conn_time', $conn_time);
if ($speed_checker) {
if (my $speed = $class->_check_speed($speed_checker, $config->speed_checker, $proxy)) {
$proxy->set('speed', $speed);
}
else {
$fail = 1;
$proxy->set('speed', 0);
}
$proxy->set('speed_checkdate', DateTime->now(time_zone => TZ));
}
}
else {
$fail = 1;
}
if ($fail) {
$proxy->set('fails_total', $proxy->fails_total+1);
$proxy->set('fails', $proxy->fails+1);
if ($proxy->fails > $config->rechecker->fails_before_delete) {
$proxy->delete();
next;
}
}
else {
$proxy->set('fails', 0);
$proxy->set('success_total', $proxy->success_total+1);
}
$proxy->set('checkdate', DateTime->now(time_zone => TZ));
$proxy->set('in_progress', \0); # force update
$proxy->update();
}
}
}
return @coros;
}
sub _start_speed_checkers {
my ($class, $config, $model) = @_;
my @coros;
my @queue;
my $delay;
for (1..$config->speed_checker->workers) {
push @coros, async {
my $speed_checker = LWP::UserAgent->new(agent => 'Mozilla 5.0', timeout => 10, parse_head => 0);
while (1) {
if ($delay) {
Coro::Timer::sleep $delay;
next;
}
unless (@queue) {
unless (@queue = $class->_get_queue(
$model,
{checked => 1},
{order_by => 'speed_checkdate'},
$config->speed_checker->interval)) {
$delay = CORO_DELAY;
Coro::Timer::sleep $delay;
$delay = 0;
next;
}
my $sec_after_last_check = DateTime->now(time_zone => TZ)->
subtract_datetime_absolute($queue[0]->speed_checkdate)->seconds;
if ($sec_after_last_check < $config->speed_checker->interval) {
$delay = $config->speed_checker->interval - $sec_after_last_check;
Coro::Timer::sleep $delay;
$delay = 0;
next;
}
}
my $proxy = shift @queue;
if (my $speed = $class->_check_speed($speed_checker, $config->speed_checker, $proxy)) {
$proxy->set('speed', $speed);
$proxy->set('success_total', $proxy->success_total+1);
}
else {
$proxy->set('fails', $proxy->fails+1);
if ($proxy->fails > $config->rechecker->fails_before_delete) {
$proxy->delete();
next;
}
$proxy->set('speed', 0);
$proxy->set('fails_total', $proxy->fails_total+1);
}
my $now = DateTime->now(time_zone => TZ);
$proxy->set('checkdate', $now);
$proxy->set('speed_checkdate', $now);
$proxy->set('in_progress', \0); # force update
$proxy->update();
}
}
}
}
sub _start_searcher {
my ($class, $config, $model) = @_;
( run in 1.378 second using v1.01-cache-2.11-cpan-39bf76dae61 )