Created
October 30, 2019 00:14
-
-
Save renatocron/190f9a4efb92df8bd386650d4088e9dc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use strict; | |
use Mojo::Promise; | |
use Mojo::UserAgent; | |
use DDP; | |
my $ua = Mojo::UserAgent->new->with_roles('+Queued')->inactivity_timeout(1); | |
my $max_fail_num = 100; | |
my $results_count = {}; | |
my @retry_pos = (0, 0.5, 1, 2, 4, 5, 10, 20, 25, 30, 40); | |
$_ = $_ / 100 for @retry_pos; # Test only! | |
sub _exp_retry_fail { | |
my $x = shift; | |
my $t = $retry_pos[$x] || $retry_pos[-1]; | |
# print "Retry N=$x T=$t\n"; | |
return $t; | |
} | |
sub _success_cb { | |
my ($insistent_promises, $url, $fail_count) = @_; | |
$fail_count ||= 0; | |
return sub { | |
my ($tx) = @_; | |
$results_count->{x}{$url}{$tx->res->code}++; | |
if ($tx->res->code == 200) { | |
$insistent_promises->resolve($tx->res); | |
} | |
else { | |
$fail_count++; | |
my $exp_retry = &_exp_retry_fail($fail_count); | |
if ($fail_count < $max_fail_num) { | |
Mojo::IOLoop->timer( | |
$exp_retry => sub { | |
$ua->get_p($tx->req->url->to_abs) | |
->then( | |
_success_cb($insistent_promises, $url, $fail_count)) | |
->catch( | |
_fail_cb($insistent_promises, $url, $fail_count)); | |
} | |
); | |
} | |
else { | |
$insistent_promises->reject("Too many errors on $url"); | |
} | |
} | |
} | |
} | |
sub _fail_cb { | |
my ($insistent_promises, $url, $fail_count) = @_; | |
$fail_count ||= 0; | |
return sub { | |
my ($err) = @_; | |
#p ['_fail_cb', $err]; | |
$results_count->{x}{$url}{'timeout'}++; | |
my $exp_retry = &_exp_retry_fail($fail_count); | |
$fail_count++; | |
if ($fail_count < $max_fail_num) { | |
Mojo::IOLoop->timer( | |
$exp_retry => sub { | |
$ua->get_p($url) | |
->then( | |
_success_cb($insistent_promises, $url, $fail_count)) | |
->catch(_fail_cb($insistent_promises, $url, $fail_count)); | |
} | |
); | |
} | |
else { | |
$insistent_promises->reject('Too many conections fails', $url); | |
} | |
}; | |
} | |
my %current_p; | |
my $errored; | |
my $pid = 0; | |
for my $num (1 .. 200) { | |
my $insistent_promises = Mojo::Promise->new; | |
my $mine_pid = $pid++; | |
$current_p{$mine_pid} = $insistent_promises; | |
my $url = 'http://localhost:3000/maybe_fail?num=' . $num; | |
$ua->get_p($url)->then(&_success_cb($insistent_promises, $url, 0)) | |
->catch(_fail_cb($insistent_promises, $url, 0)); | |
$insistent_promises->then( | |
sub { | |
my ($res) = @_; | |
$results_count->{p}{$res->json->{num}}{$res->code}++; | |
} | |
)->catch( | |
sub { | |
print STDERR "cancel everythiiiiiiiiiiing!!!\n\n\n"; | |
$errored++; | |
#Mojo::Promise->reset; | |
} | |
)->finally( | |
sub { | |
delete $current_p{$mine_pid}; | |
} | |
); | |
Mojo::Promise->all($insistent_promises); | |
if (scalar keys %current_p > 5) { | |
Mojo::Promise->race(values %current_p)->wait; | |
} | |
} | |
use DDP; | |
p [scalar keys %current_p]; | |
my @values = values %current_p; | |
Mojo::Promise->all(@values)->wait if @values; | |
if ($errored) { | |
die "Please do not commit!!!\n"; | |
} | |
p $results_count; | |
exit; | |
# I tried this but did not worked: | |
my $is_done = 0 | |
; # TODO check if queue is empty, because it may never return run the event if not! | |
$ua->on( | |
queue_empty => sub { | |
use DDP; | |
p "on is queue_empty!"; | |
$is_done = 1; | |
} | |
); | |
while (1) { | |
Mojo::IOLoop->start unless Mojo::IOLoop->is_running; | |
Mojo::IOLoop->next_tick( | |
sub { | |
if (!$is_done) { | |
Mojo::IOLoop->stop; | |
} | |
} | |
); | |
} | |
# this never run | |
p $results_count; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment