Skip to content

Commit 852ba9d

Browse files
authored
Merge pull request #148 from mojolicious/fetch_retry
Add support for multiple download attempts for assets that need to be fetched
2 parents f44e08f + 5398671 commit 852ba9d

File tree

2 files changed

+75
-3
lines changed

2 files changed

+75
-3
lines changed

lib/Mojolicious/Plugin/AssetPack/Store.pm

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use Mojo::URL;
88
use Mojolicious::Types;
99
use Mojolicious::Plugin::AssetPack::Asset;
1010
use Mojolicious::Plugin::AssetPack::Util qw(diag checksum has_ro DEBUG);
11+
use Time::HiRes qw(sleep);
1112

1213
use constant CACHE_DIR => 'cache';
1314

@@ -26,6 +27,8 @@ has asset_class => 'Mojolicious::Plugin::AssetPack::Asset';
2627
has default_headers => sub { +{"Cache-Control" => "max-age=31536000"} };
2728
has fallback_headers => sub { +{"Cache-Control" => "max-age=60"} };
2829
has fallback_templates => sub { +{%FALLBACK_TEMPLATES} };
30+
has retry_delay => 3;
31+
has retries => 0;
2932

3033
has _types => sub {
3134
my $t = Mojolicious::Types->new;
@@ -257,14 +260,22 @@ sub _download {
257260

258261
return $asset if $attrs{url}->host ne 'local' and $asset = $self->_already_downloaded($url);
259262

260-
my $tx = $self->ua->get($url);
261-
my $h = $tx->res->headers;
263+
my $tx;
264+
my $retries = $self->retries;
265+
while (1) {
266+
$tx = $self->ua->get($url);
267+
last unless my $err = $tx->error;
268+
269+
if ($retries-- > 0) {
270+
sleep $self->retry_delay;
271+
next;
272+
}
262273

263-
if (my $err = $tx->error) {
264274
$self->_log->warn("[AssetPack] Unable to download $url: $err->{message}");
265275
return undef;
266276
}
267277

278+
my $h = $tx->res->headers;
268279
my $ct = $h->content_type || '';
269280
if ($ct ne 'text/plain') {
270281
$ct =~ s!;.*$!!;
@@ -388,6 +399,20 @@ This is currently an EXPERIMENTAL feature.
388399
389400
See L<Mojolicious::Static/paths> for details.
390401
402+
=head2 retry_delay
403+
404+
my $delay = $self->retry_delay;
405+
$self = $self->retry_delay(0.5);
406+
407+
Delay in seconds between download attempts for assets that need to be fetched, defaults to C<3>.
408+
409+
=head2 retries
410+
411+
my $retries = $self->retries;
412+
$self = $self->retries(5);
413+
414+
Number of times asset downloads will be attempted for assets that need to be fetched, defaults to C<0>.
415+
391416
=head2 ua
392417
393418
$ua = $self->ua;

t/fetch-retry.t

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use lib '.';
2+
use t::Helper;
3+
4+
use Mojo::IOLoop;
5+
use Mojo::Server::Daemon;
6+
use Mojolicious;
7+
8+
my $t = t::Helper->t(pipes => [qw(Css Fetch)]);
9+
10+
my $app = Mojolicious->new;
11+
$app->config->{attempts} = 0;
12+
$app->routes->get(
13+
'/test.css' => sub {
14+
my $c = shift;
15+
return $c->render(data => 'Internal server error', status => 500) if $c->app->config->{attempts}++ <= 2;
16+
$c->render(data => 'body { color: #00f }');
17+
}
18+
);
19+
my $responses = [];
20+
$app->hook(
21+
before_dispatch => sub {
22+
shift->on(finish => sub { push @$responses, shift->res->code });
23+
}
24+
);
25+
my $daemon = Mojo::Server::Daemon->new(listen => ['http://*'], ioloop => $t->app->asset->ua->ioloop, app => $app);
26+
my $port = $daemon->start->ports->[0];
27+
28+
subtest 'Defaults' => sub {
29+
is $t->app->asset->store->retries, 0, 'no retries by default';
30+
is $t->app->asset->store->retry_delay, 3, '3 second retry delay by default';
31+
};
32+
33+
subtest 'Download asset with multiple attempts' => sub {
34+
$t->app->asset->store->retries(3)->retry_delay(0.1);
35+
$t->app->asset->process('app.css' => "http://127.0.0.1:$port/test.css");
36+
37+
$t->get_ok('/')->status_is(200)->content_like(qr{Hello world});
38+
$t->get_ok($t->tx->res->dom->at('link')->{href})->status_is(200)->content_like(qr{body.+color.+00f});
39+
is_deeply $responses, [500, 500, 500, 200], 'right responses';
40+
};
41+
42+
done_testing;
43+
44+
__DATA__
45+
@@ index.html.ep
46+
%= asset 'app.css'
47+
Hello world

0 commit comments

Comments
 (0)