Skip to content

Instantly share code, notes, and snippets.

@renatocron
Created October 30, 2019 00:29
Show Gist options
  • Save renatocron/b43dd692c01d77cb0aff3fa5d4d4ec89 to your computer and use it in GitHub Desktop.
Save renatocron/b43dd692c01d77cb0aff3fa5d4d4ec89 to your computer and use it in GitHub Desktop.
perl lost-and-found/promises-retry-test.pl
time vsz ( diff) rss ( diff) shared ( diff) code ( diff) data ( diff)
0 116440 ( 116440) 39960 ( 39960) 7388 ( 7388) 2944 ( 2944) 32912 ( 32912) starting work
4 489688 ( 373248) 44448 ( 4488) 7388 ( 0) 2944 ( 0) 79120 ( 46208) Iteration 1000
10 492144 ( 2456) 47088 ( 2640) 7388 ( 0) 2944 ( 0) 81576 ( 2456) Iteration 2000
14 492144 ( 0) 47088 ( 0) 7388 ( 0) 2944 ( 0) 81576 ( 0) Iteration 3000
17 492144 ( 0) 47088 ( 0) 7388 ( 0) 2944 ( 0) 81576 ( 0) Iteration 4000
22 492144 ( 0) 47088 ( 0) 7388 ( 0) 2944 ( 0) 81576 ( 0) Iteration 5000
26 492144 ( 0) 47088 ( 0) 7388 ( 0) 2944 ( 0) 81576 ( 0) Iteration 6000
30 492144 ( 0) 47088 ( 0) 7388 ( 0) 2944 ( 0) 81576 ( 0) Iteration 7000
32 493068 ( 924) 47880 ( 792) 7388 ( 0) 2944 ( 0) 82500 ( 924) Iteration 8000
37 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 9000
41 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 10000
46 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 11000
49 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 12000
55 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 13000
57 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 14000
61 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 15000
64 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 16000
67 493068 ( 0) 47880 ( 0) 7388 ( 0) 2944 ( 0) 82500 ( 0) Iteration 17000
70 493596 ( 528) 48408 ( 528) 7388 ( 0) 2944 ( 0) 83028 ( 528) Iteration 18000
74 493596 ( 0) 48408 ( 0) 7388 ( 0) 2944 ( 0) 83028 ( 0) Iteration 19000
79 493596 ( 0) 48408 ( 0) 7388 ( 0) 2944 ( 0) 83028 ( 0) Iteration 20000
80 493596 ( 0) 48408 ( 0) 7388 ( 0) 2944 ( 0) 83028 ( 0) Last Iteration
Printing in line 164 of lost-and-found/promises-retry-test.pl:
[
[0] 20000,
[1] 5344
]
use strict;
use Mojo::Promise;
use Mojo::UserAgent;
use DDP;use Memory::Usage;
my $mu = Memory::Usage->new();
my $ua = Mojo::UserAgent->new->inactivity_timeout(1);
my $max_fail_num = 100;
my $total_success=0;
my $total_err=0;
#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++;
$total_err++;
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++;
$total_err++;
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;
$mu->record('starting work');
for my $num (1 .. 20000) {
my $insistent_promises = Mojo::Promise->new;
my $mine_pid = $pid++;
$current_p{$mine_pid} = $insistent_promises;
my $url = 'http://localhost:8080/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) = @_;
$total_success++;
}
)->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);
$mu->record('Iteration ' . $num) if $num % 1000 == 0;
if (scalar keys %current_p > 5) {
Mojo::Promise->race(values %current_p)->wait;
}
}
my @values = values %current_p;
Mojo::Promise->all(@values)->wait if @values;
$mu->record('Last Iteration');
$mu->dump();
if ($errored) {
die "Please do not commit!!!\n";
}
p [$total_success, $total_err];
exit;
use Mojolicious::Lite;
use utf8;
get '/maybe_fail' => sub {
my $c = shift;
my $status = rand > 0.2 ? 200 : 400;
if (rand > 0.99){
$c->render_later; # timeout a few
return;
}
$c->render(json => {num => $c->req->param('num'),}, status => $status,);
};
# Start the Mojolicious command system
app->start;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment