Skip to content

Instantly share code, notes, and snippets.

@gempesaw
Created October 18, 2014 22:32
Show Gist options
  • Select an option

  • Save gempesaw/c67624c01f432d4888b5 to your computer and use it in GitHub Desktop.

Select an option

Save gempesaw/c67624c01f432d4888b5 to your computer and use it in GitHub Desktop.
spin assert class
package Honeydew::Common::Waiter;
$Honeydew::Common::Waiter::VERSION = '0.19';
# ABSTRACT: A Waiter class to spin assert your NON-BLOCKING time-dependent operations
use strict;
use warnings;
use Moo;
use Carp;
has 'assert' => (
is => 'rw',
required => 1,
);
has 'timeout' => (
is => 'rw',
predicate => 'has_timeout'
);
has 'interval' => (
is => 'rw',
lazy => 1,
default => sub { 1 }
);
has 'max_timeout' => (
is => 'rw',
lazy => 1,
builder => sub {
my $self = shift;
return 30 unless $self->has_timeout;
if ($self->timeout =~ /(\d+) seconds?/) {
return $1;
}
elsif ($self->timeout =~ /(\d+) minutes?/) {
return $1 * 60;
}
elsif ($self->timeout =~ /^\d+$/) {
return $self->timeout;
}
else {
croak 'The timeout is invalid: ' . $self->timeout;
}
},
init_arg => undef
);
has '_start_time' => (
is => 'ro',
lazy => 1,
default => sub { time }
);
sub spin {
my ($self) = @_;
$self->_start_time(time);
while ($self->_timeoutNotElapsed) {
my $assert = $self->assert->();
return $assert if $assert;
sleep($self->interval);
}
return "";
}
sub _timeoutNotElapsed {
my ($self) = @_;
my $elapsed = time - $self->_start_time;
my $timeout = $self->max_timeout;
return $elapsed < $timeout;
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Honeydew::Common::Waiter - A Waiter class to spin assert your NON-BLOCKING time-dependent operations
=head1 VERSION
version 0.19
=head1 SYNOPSIS
my $waiter = Honeydew::Common::Waiter->new(
assert => sub { return non_blocking_sub() },
);
my $status = $waiter->spin;
# by default, the waiter will invoke the assert sub once a second
# for thirty seconds, or until the assert sub returns true.
return $status if $status;
=head1 ATTRIBUTES
=head2 assert
Required; must be a coderef. It will be executed once every
L</interval> seconds until it returns true or the maximum time is
exceeded.
=head2 timeout;
Optional; defaults to 30 seconds. Specify the maximum duration for
L</spin> to wait for the L</assert> to become true. Accepts seconds as
integers, or seconds with a label, or minutes with the label.
timeout => 5 # 5 seconds
timeout => 5 seconds # the same
timeout => 5 minutes # 300 seconds
=head2 interval
Optional; defaults to 1 second. Specify the number of seconds as an
integer to sleep between checks.
=head1 METHODS
=head2 spin
Use this method to spin assert that your condition must be true. It
checks that we haven't exceeded the timeout before executing the
NON-BLOCKING assert coderef. If the coderef returns false, it sleeps
for the designated interval before trying again.
=head1 SEE ALSO
Please see those modules/websites for more information related to this module.
=over 4
=item *
L<Honeydew|Honeydew>
=back
=head1 BUGS
Please report any bugs or feature requests on the bugtracker website
https://arnoldmedia.jira.com/browse/HDEW
When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.
=head1 AUTHOR
Daniel Gempesaw <dgempesaw@sharecare.com>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2014 by Sharecare, Inc..
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment