Async-Event-Interval
view release on metacpan or search on metacpan
- Fixes #16; _rand_shm_lock() now returns 1 + ($$ % 32767) so the value
fits in IPC::Shareable 1.14+'s SEM_PROTECTED semaphore slot
- shared_scalar() segments are now tied with protected => _shm_lock() to
close the IPC::Shareable->clean_up_all foot-gun that could wipe them
out from under a running event; the owning event's DESTROY still
removes them via IPC::Shareable->remove
- %events bootstrap loop is now capped at SHM_CREATE_RETRIES (100)
attempts and croaks with the last underlying error instead of
spinning forever when shmget fails persistently
- All reads/writes to %events now go through _events_read (LOCK_SH) /
_events_write (LOCK_EX) to synchronize access across processes
- events() now returns a read-locked deep copy snapshot; mutations to
the returned hashref do not affect the live %events
- info() now returns a shallow copy snapshot, consistent with events()
- _rand_shm_key() now generates hex strings within the 32-bit SHM key
range (0x0â0x7FFFFFFF), replacing the 12 random letters which also
removes the srand()-in-a-loop pattern
- shared_scalar() no longer stores tied refs inside %events;
%events now holds an arrayref of hex key strings instead,
eliminating a same-process FETCH deadlock in IPC::Shareable
- $SIG{__WARN__} moved to local inside _event() so it no longer
{
"abstract" : "Scheduled and one-off restartable asynchronous events",
"author" : [
"Steve Bertrand <steveb@cpan.org>"
],
"dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010",
"license" : [
"perl_5"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
---
abstract: 'Scheduled and one-off restartable asynchronous events'
author:
- 'Steve Bertrand <steveb@cpan.org>'
build_requires:
File::Temp: '0'
Mock::Sub: '0'
Test::More: '0'
Test::SharedFork: '0'
configure_requires:
ExtUtils::MakeMaker: '0'
dynamic_config: 1
lib/Async/Event/Interval.pm view on Meta::CPAN
}
sub _vim{} # vim navigation marker; intentionally empty
1;
__END__
=head1 NAME
Async::Event::Interval - Scheduled and one-off restartable asynchronous events
=for html
<a href="https://github.com/stevieb9/async-event-interval/actions"><img src="https://github.com/stevieb9/async-event-interval/workflows/CI/badge.svg"/></a>
<a href='https://coveralls.io/github/stevieb9/async-event-interval?branch=master'><img src='https://coveralls.io/repos/stevieb9/async-event-interval/badge.svg?branch=master&service=github' alt='Coverage Status' /></a>
=head1 SYNOPSIS
Here's an example of a simple asynchronous event that fetches JSON data from a
website every two seconds using a shared scalar variable to hold the decoded
JSON hashref, while allowing the main application to continue running in the
foreground. Multiple events can be used simultaneously if desired.
See the L</SCENARIOS/EXAMPLES> section for further usage examples.
use warnings;
use strict;
use Async::Event::Interval;
lib/Async/Event/Interval.pm view on Meta::CPAN
}
sub callback {
my $api_json = some_web_api_call(); # '{"data": [1, 2, 3]}';
$$api_data_href = decode_json($api_json);
}
=head1 DESCRIPTION
Very basic implementation of asynchronous events triggered by a timed interval.
If a time of zero is specified, we'll run the event only once while providing
the ability to re-run it manually at any time in the future.
B<Signal handling>: The module installs C<$SIG{INT}> and C<$SIG{TERM}>
handlers at load time to ensure shared memory segments are cleaned up when the
host process is killed by a signal. The handlers stop any running event
children, remove all shared memory segments, then re-raise the signal with the
default handler so the process exits with the correct status. If you install
your own handlers for these signals, call C<Async::Event::Interval::_end(1)>
from them before exiting to avoid leaking segments.
t/05-base.t view on Meta::CPAN
my $mod = 'Async::Event::Interval';
my $file = 't/test.data';
{
my $e = $mod->new(0.2, \&perform, 10);
$e->start;
is -e $file, undef, "event is asynchronious";
sleep 2;
$e->stop;
my $data;
{
local $/;
open my $fh, '<', $file or die $!;
t/20-restart.t view on Meta::CPAN
my $mod = 'Async::Event::Interval';
my $file = 't/test.data';
{
my $e = $mod->new(0.2, \&perform, 10);
$e->restart;
is -e $file, undef, "event is asynchronious";
sleep 2;
$e->stop;
my $data;
{
local $/;
open my $fh, '<', $file or die $!;
$data = <$fh>;
t/61-error_and_waiting_fields.t view on Meta::CPAN
use lib 't/lib';
use TestHelper;
use Test::More;
use Time::HiRes ();
use Async::Event::Interval;
my $mod = 'Async::Event::Interval';
# Poll-until-condition with a wall-clock deadline. Replaces fixed select()
# sleeps in blocks that wait for an asynchronous state transition (callback
# crash registers, restart clears flag, etc.) so the tests are robust on
# slow VMs without inflating wall-clock on healthy runs. Returns 1 on
# condition met, 0 on deadline hit.
sub poll_until {
my ($cond, $timeout) = @_;
$timeout //= 5;
my $deadline = Time::HiRes::time() + $timeout;
while (! $cond->()) {
return 0 if Time::HiRes::time() >= $deadline;
( run in 2.294 seconds using v1.01-cache-2.11-cpan-9581c071862 )