NAME
IO::Async::Resolver
- performing name resolutions asynchronously
SYNOPSIS
This object is used indirectly via an IO::Async::Loop
:
use IO::Async::Loop;
my $loop = IO::Async::Loop->new();
$loop->resolve( type => 'getpwuid', data => [ $< ],
on_resolved =>
sub { print "My passwd ent: " . join( "|", @_ ) . "\n" },
on_error =>
sub { print "Cannot look up my passwd ent - $_[0]\n" },
);
$loop->loop_forever;
DESCRIPTION
This module extends an IO::Async::Loop
to use the system's name resolver functions asynchronously. It provides a number of named resolvers, each one providing an asynchronous wrapper around a single resolver function.
Because the system may not provide asynchronous versions of its resolver functions, this class is implemented using a IO::Async::DetachedCode
object that wraps the normal (blocking) functions. In this case, name resolutions will be performed asynchronously from the rest of the program, but will likely be done by a single background worker process, so will be processed in the order they were requested; a single slow lookup will hold up the queue of other requests behind it. To mitigate this, multiple worker processes can be used; see the workers
argument to the constructor.
METHODS
$loop->resolve( %params )
Performs a single name resolution operation, as given by the keys in the hash.
The %params
hash keys the following keys:
- type => STRING
-
Name of the resolution operation to perform. See BUILT-IN RESOLVERS for the list of available operations.
- data => ARRAY
-
Arguments to pass to the resolver function. Exact meaning depends on the specific function chosen by the
type
; see BUILT-IN RESOLVERS. - on_resolved => CODE
-
A callback that is invoked when the resolver function returns a successful result. It will be passed the array returned by the resolver function.
- on_error => CODE
-
A callback that is invoked when the resolver function fails. It will be passed the exception thrown by the function.
FUNCTIONS
register_resolver( $name, $code )
Registers a new named resolver function that can be called by the resolve
method. All named resolvers must be registered before the object is constructed.
- $name
-
The name of the resolver function; must be a plain string. This name will be used by the
type
argument to theresolve()
method, to identify it. - $code
-
A CODE reference to the resolver function body. It will be called in list context, being passed the list of arguments given in the
data
argument to theresolve()
method. The returned list will be passed to theon_resolved
callback.
The IO::Async::DetachedCode
object underlying this class uses the storable
argument marshalling type, which means complex data structures can be passed by reference. Because the resolver will run in a separate process, the function should make sure to return all of the result in the returned list; i.e. modifications to call arguments will not be propagated back to the caller.
BUILT-IN RESOLVERS
The following resolver names are implemented by the same-named perl function, taking and returning a list of values exactly as the perl function does:
getpwnam getpwuid
getgrnam getgrgid
getservbyname getservbyport
gethostbyname gethostbyaddr
getnetbyname getnetbyaddr
getprotobyname getprotobynumber
The following two resolver names are implemented using the same-named functions from the Socket::GetAddrInfo
module.
getaddrinfo getnameinfo
The getaddrinfo
resolver mangles the result of the function, so that the returned value is more useful to the caller. It splits up the list of 5-tuples into a list of ARRAY refs, where each referenced array contains one of the tuples of 5 values. The getnameinfo
resolver returns its result unchanged.
EXAMPLES
The following somewhat contrieved example shows how to implement a new resolver function. This example just uses in-memory data, but a real function would likely make calls to OS functions to provide an answer. In traditional Unix style, a pair of functions are provided that each look up the entity by either type of key, where both functions return the same type of list. This is purely a convention, and is in no way required or enforced by the IO::Async::Resolver
itself.
@numbers = qw( zero one two three four
five six seven eight nine );
register_resolver( 'getnumberbyindex', sub {
my ( $index ) = @_;
die "Bad index $index" unless $index >= 0 and $index < @numbers;
return ( $index, $numbers[$index] );
} );
register_resolver( 'getnumberbyname', sub {
my ( $name ) = @_;
foreach my $index ( 0 .. $#numbers ) {
return ( $index, $name ) if $numbers[$index] eq $name;
}
die "Bad name $name";
} );
TODO
Look into (system-specific) ways of accessing asynchronous resolvers directly
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>