IO::As...esolver(3pm)
π IO::Async::Resolver π
okay so bestie, welcome to IO::Async::Resolver(3pm) β straight outta User Contributed Perl Documentation, and it's giving async name resolution realness. let's get into it π
β¨ NAME β¨
"IO::Async::Resolver" β performing name resolutions asynchronously π¦
β¨ SYNOPSIS β¨
so this object isn't something you just go and new yourself β it comes to you indirectly via an IO::Async::Loop:
use Future::AsyncAwait;
use IO::Async::Loop;
my $loop = IO::Async::Loop->new;
my @results = await $loop->resolver->getaddrinfo(
host => "www.example.com",
service => "http",
);
foreach my $addr ( @results ) {
printf "http://www.example.com can be reached at " .
"socket(%d,%d,%d) + connect('%v02x')\n",
@{$addr}{qw( family socktype protocol addr )};
}
my @pwent = await $loop->resolve( type => 'getpwuid', data => [ $< ] );
print "My passwd ent: " . join( "|", @pwent ) . "\n";
β¨ DESCRIPTION β¨
This module extends an IO::Async::Loop to use the system's name resolver functions asynchronously. Like, it provides a bunch of named resolvers, and each one is an async wrapper around exactly one resolver function. cute, right? π«Ά
Here's the tea though: because your system may not even have async versions of its resolver functions, this class is implemented using an IO::Async::Function object that wraps the normal (blocking) functions. In that case, name resolutions get performed asynchronously from the rest of the program, but they'll likely be done by a single background worker process, so they'll be processed in the order they were requested. which meansβ¦ a single slow lookup will hold up the queue of other requests behind it. π literally the group chat of lookups, one slow typer holding everybody up.
To mitigate this, you can use multiple worker processes β peep the "workers" argument to the constructor. π
Also, the "idle_timeout" parameter for the underlying IO::Async::Function object is set to a default of 30 seconds, and "min_workers" is set to 0. This ensures there are no spare processes sitting idle during the common case of no outstanding requests. no freeloaders here, periodt. π
β¨ METHODS β¨
The following methods documented in "await" expressions return Future instances.
πΈ resolve
@result = await $loop->resolve( %params );
Performs a single name resolution operation, as given by the keys in the hash. one job, one lookup, let's go.
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. The exact meaning depends on the specific function chosen by the"type"; see BUILT-IN RESOLVERS.timeout => NUMBERβ Optional. Timeout in seconds, after which the resolver operation will abort with a timeout exception. If you don't supply it, a default of10seconds applies.
On failure, the fail category name is "resolve"; the details give the individual resolver function name (e.g. "getaddrinfo"), followed by other error details specific to the resolver in question.
->fail( $message, resolve => $type => @details )
πΈ resolve (void)
$resolver->resolve( %params );
When you're not returning a future, you can give additional parameters containing the continuations to invoke on success or failure:
on_resolved => CODEβ A continuation that is invoked when the resolver function returns a successful result. It will be passed the array returned by the resolver function.
$on_resolved->( @result )
on_error => CODEβ A continuation that is invoked when the resolver function fails. It will be passed the exception thrown by the function.
πΈ getaddrinfo
@addrs = await $resolver->getaddrinfo( %args );
A shortcut wrapper around the "getaddrinfo" resolver, taking its arguments in a more convenient form. bestie said "make it user friendly" and they did β¨
host => STRINGservice => STRING
The host and service names to look up. At least one must be provided. (one of them, minimum, no skipping π )
family => INT or STRINGsocktype => INT or STRINGprotocol => INT
Hint values used to filter the results.
flags => INTβ Flags to control thegetaddrinfo(3)function. See the"AI_*"constants in Socket's"getaddrinfo"function for more detail.passive => BOOLβ If true, sets the"AI_PASSIVE"flag. This is provided as a convenience so the caller doesn't have to go import the"AI_PASSIVE"constant from"Socket"themselves. you're welcome π«Άtimeout => NUMBERβ Time in seconds after which to abort the lookup with a"Timed out"exception.
On success, the future will yield the result as a list of HASH references; each one containing one result. Each result will contain fields called "family", "socktype", "protocol" and "addr". If it was requested by "AI_CANONNAME" then the "canonname" field will also be present.
On failure, the detail field will give the error number, which should match one of the "Socket::EAI_*" constants.
->fail( $message, resolve => getaddrinfo => $eai_errno )
As a specific optimisation, this method will try to perform a lookup of numeric values synchronously, rather than asynchronously, if it looks likely to succeed. like, why spin up a whole worker when the answer's already sitting right there? iconic behaviour honestly.
Specifically, if the service name is entirely numeric, and the hostname looks like an IPv4 or IPv6 string, a synchronous lookup will first be performed using the "AI_NUMERICHOST" flag. If this gives an "EAI_NONAME" error, then the lookup is performed asynchronously instead.
πΈ getaddrinfo (void)
$resolver->getaddrinfo( %args );
When you're not returning a future, you can give additional parameters containing the continuations to invoke on success or failure:
on_resolved => CODEβ Callback which is invoked after a successful lookup.
$on_resolved->( @addrs );
on_error => CODEβ Callback which is invoked after a failed lookup, including for a timeout.
$on_error->( $exception );
πΈ getnameinfo
( $host, $service ) = await $resolver->getnameinfo( %args );
A shortcut wrapper around the "getnameinfo" resolver, taking its arguments in a more convenient form. sibling energy to getaddrinfo above, goes the other direction π
addr => STRINGβ The packed socket address to look up.flags => INTβ Flags to control thegetnameinfo(3)function. See the"NI_*"constants in Socket's"getnameinfo"for more detail.numerichost => BOOLnumericserv => BOOLdgram => BOOL
If true, set the "NI_NUMERICHOST", "NI_NUMERICSERV" or "NI_DGRAM" flags.
numeric => BOOLβ If true, sets both the"NI_NUMERICHOST"and"NI_NUMERICSERV"flags. two for one, we love a bundle deal.timeout => NUMBERβ Time in seconds after which to abort the lookup with a"Timed out"exception.
On failure, the detail field will give the error number, which should match one of the "Socket::EAI_*" constants.
->fail( $message, resolve => getnameinfo => $eai_errno )
As a specific optimisation, this method will try to perform a lookup of numeric values synchronously, rather than asynchronously, if both the "NI_NUMERICHOST" and "NI_NUMERICSERV" flags are given.
πΈ getnameinfo (void)
$resolver->getnameinfo( %args );
When you're not returning a future, you can give additional parameters containing the continuations to invoke on success or failure:
on_resolved => CODEβ Callback which is invoked after a successful lookup.
$on_resolved->( $host, $service );
on_error => CODEβ Callback which is invoked after a failed lookup, including for a timeout.
$on_error->( $exception );
β¨ FUNCTIONS β¨
π¦ register_resolver
register_resolver( $name, $code );
Registers a new named resolver function that can be called by the "resolve" method. β οΈ Heads up: all named resolvers must be registered before the object is constructed. no late arrivals, this is a strict guest list.
$nameβ The name of the resolver function; must be a plain string. This name will be used by the"type"argument to the"resolve"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 the"resolve"method. The returned list will be passed to the"on_resolved"callback. If the code throws an exception at call time, it will be passed to the"on_error"continuation. If it returns normally, the list of values it returns will be passed to"on_resolved".
β¨ 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. no notes, they just mirror the perl behaviour:
getpwnam getpwuid
getgrnam getgrgid
getservbyname getservbyport
gethostbyname gethostbyaddr
getnetbyname getnetbyaddr
getprotobyname getprotobynumber
The following three resolver names are implemented using the Socket module. π₯
getaddrinfo
getaddrinfo_array
getnameinfo
The "getaddrinfo" resolver takes arguments in a hash of name/value pairs and returns a list of hash structures, exactly as the "Socket::getaddrinfo" function does. For neatness it takes all its arguments as named values; taking the host and service names from arguments called "host" and "service" respectively; all the remaining arguments are passed into the hints hash. This name is also aliased as simply "getaddrinfo". cute β¨
The "getaddrinfo_array" resolver behaves more like the "Socket6" version of the function. It takes hints in a flat list, and 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. deconstructed, sliced, served π
As an extra convenience to the caller, both resolvers will also accept plain string names for the "family" argument, converting "inet" and possibly "inet6" into the appropriate "AF_*" value, and for the "socktype" argument, converting "stream", "dgram" or "raw" into the appropriate "SOCK_*" value. so you can just say what you mean, iykyk π
The "getnameinfo" resolver returns its result in the same form as "Socket".
Because this module simply uses the system's "getaddrinfo" resolver, it will be fully IPv6-aware if the underlying platform's resolver is. This allows programs to be fully IPv6-capable. πβ¨
okay that's the first half bestie, stay tuned because there is more π
π EXAMPLES π
okay bestie so here's a somewhat contrived example that shows you how to implement a brand new resolver function β¨ (yes, the original literally calls it "contrieved", we're being polite about it π ). This one is just vibing with in-memory data, but a real function would probably go call some OS functions to actually get you an answer.
And in traditional Unix style, you get a pair of functions β each one looks up the entity by a different type of key, but both of them hand back the same type of list. That's purely a convention btw, it is in no way required or enforced by IO::Async::Resolver itself. do whatever you want, it's your resolver π«Ά
@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";
};
like. look at that. register_resolver twice, two lil subs, one < guard that dies if you hand it a bad index π, a foreach that walks 0 .. $#numbers looking for a name match, and a die "Bad name $name" for when nothing hits. that's the whole recipe. iconic. no cap π₯
π AUTHOR π
Paul Evans <leonerd@leonerd.org.uk> π
so that's the whole page bestie, we made it π this one came to you out of the User Contributed Perl Documentation, running on perl v5.40.1, dated 2026-02-21, and the page itself is IO::As...esolver(3pm) β go forth and resolve some things π
β¨πΈ
π¦ where this page comes from
- ubuntu stonking: libio-async-perl 0.805-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms