|
|
@@ -18,8 +18,7 @@ It is by no means exhaustively implementing every TestRail API function.
|
|
|
=head1 IMPORTANT
|
|
|
|
|
|
All the methods aside from the constructor should not die, but return a false value upon failure (see exceptions below).
|
|
|
-When the server is not responsive, expect a -500 response, and retry accordingly.
|
|
|
-I recommend using the excellent L<Attempt> module for this purpose.
|
|
|
+When the server is not responsive, expect a -500 response, and retry accordingly by setting the num_tries parameter in the constructor.
|
|
|
|
|
|
Also, all *ByName methods are vulnerable to duplicate naming issues. Try not to use the same name for:
|
|
|
|
|
|
@@ -77,6 +76,8 @@ Creates new C<TestRail::API> object.
|
|
|
|
|
|
=item BOOLEAN C<DO_POST_REDIRECT> (optional) - Follow redirects on POST requests (most add/edit/delete calls are POSTs). Default false.
|
|
|
|
|
|
+=item INTEGER C<MAX_TRIES> (optional) - Try requests up to X number of times if they fail with anything other than 401/403. Useful with flaky external auth, or timeout issues. Default 1.
|
|
|
+
|
|
|
=back
|
|
|
|
|
|
Returns C<TestRail::API> object if login is successful.
|
|
|
@@ -89,8 +90,8 @@ Does not do above checks if debug is passed.
|
|
|
=cut
|
|
|
|
|
|
sub new {
|
|
|
- state $check = compile(ClassName, Str, Str, Str, Optional[Maybe[Str]], Optional[Maybe[Bool]], Optional[Maybe[Bool]]);
|
|
|
- my ($class,$apiurl,$user,$pass,$encoding,$debug, $do_post_redirect) = $check->(@_);
|
|
|
+ state $check = compile(ClassName, Str, Str, Str, Optional[Maybe[Str]], Optional[Maybe[Bool]], Optional[Maybe[Bool]], Optional[Maybe[Int]]);
|
|
|
+ my ($class,$apiurl,$user,$pass,$encoding,$debug, $do_post_redirect,$max_tries) = $check->(@_);
|
|
|
|
|
|
die("Invalid URI passed to constructor") if !is_uri($apiurl);
|
|
|
$debug //= 0;
|
|
|
@@ -111,7 +112,9 @@ sub new {
|
|
|
browser => new LWP::UserAgent(
|
|
|
keep_alive => 10,
|
|
|
),
|
|
|
- do_post_redirect => $do_post_redirect
|
|
|
+ do_post_redirect => $do_post_redirect,
|
|
|
+ max_tries => $max_tries // 1,
|
|
|
+ retry_delay => 5,
|
|
|
};
|
|
|
|
|
|
#Allow POST redirects
|
|
|
@@ -172,11 +175,24 @@ sub debug {
|
|
|
return $self->{'debug'};
|
|
|
}
|
|
|
|
|
|
+=head2 B<retry_delay>
|
|
|
+
|
|
|
+There is no getter/setter for this parameter, but it is worth mentioning.
|
|
|
+This is the number of seconds to wait between failed request retries when max_retries > 1.
|
|
|
+
|
|
|
+ #Do something other than the default of 5s, like spam the server mercilessly
|
|
|
+ $tr->{retry_delay} = 0;
|
|
|
+ ...
|
|
|
+
|
|
|
+=cut
|
|
|
+
|
|
|
#Convenient JSON-HTTP fetcher
|
|
|
sub _doRequest {
|
|
|
state $check = compile(Object, Str, Optional[Maybe[Str]], Optional[Maybe[HashRef]]);
|
|
|
my ($self,$path,$method,$data) = $check->(@_);
|
|
|
|
|
|
+ $self->{num_tries}++;
|
|
|
+
|
|
|
my $req = clone $self->{'default_request'};
|
|
|
$method //= 'GET';
|
|
|
|
|
|
@@ -193,7 +209,7 @@ sub _doRequest {
|
|
|
$req->content($content);
|
|
|
$req->header( "Content-Type" => "application/json; charset=".$self->{'encoding'} );
|
|
|
|
|
|
- my $response = $self->{'browser'}->request($req);
|
|
|
+ my $response = eval { $self->{'browser'}->request($req) };
|
|
|
|
|
|
#Uncomment to generate mocks
|
|
|
#use Data::Dumper;
|
|
|
@@ -204,7 +220,19 @@ sub _doRequest {
|
|
|
#print $fh "\n\n}\n\n";
|
|
|
#close $fh;
|
|
|
|
|
|
+ if ($@) {
|
|
|
+ #LWP threw an ex, probably a timeout
|
|
|
+ if ($self->{num_tries} >= $self->{max_tries}) {
|
|
|
+ $self->{num_tries} = 0;
|
|
|
+ confess "Failed to satisfy request after $self->{num_tries} tries!";
|
|
|
+ }
|
|
|
+ cluck "WARNING: TestRail API request failed due to timeout, or other LWP fatal condition, re-trying request...\n";
|
|
|
+ sleep $self->{retry_delay} if $self->{retry_delay};
|
|
|
+ goto &_doRequest;
|
|
|
+ }
|
|
|
+
|
|
|
return $response if !defined($response); #worst case
|
|
|
+
|
|
|
if ($response->code == 403) {
|
|
|
confess "ERROR 403: Access Denied: ".$response->content;
|
|
|
}
|
|
|
@@ -213,9 +241,18 @@ sub _doRequest {
|
|
|
}
|
|
|
|
|
|
if ($response->code != 200) {
|
|
|
- cluck "ERROR: Arguments Bad? (got code ".$response->code."): ".$response->content;
|
|
|
- return -int($response->code);
|
|
|
+ #LWP threw an ex, probably a timeout
|
|
|
+ if ($self->{num_tries} >= $self->{max_tries}) {
|
|
|
+ $self->{num_tries} = 0;
|
|
|
+ cluck "ERROR: Arguments Bad? (got code ".$response->code."): ".$response->content;
|
|
|
+ return -int($response->code);
|
|
|
+ }
|
|
|
+ cluck "WARNING: TestRail API request failed (got code ".$response->code."), re-trying request...\n";
|
|
|
+ sleep $self->{retry_delay} if $self->{retry_delay};
|
|
|
+ goto &_doRequest;
|
|
|
+
|
|
|
}
|
|
|
+ $self->{num_tries} = 0;
|
|
|
|
|
|
try {
|
|
|
return $coder->decode($response->content);
|