]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
netutil: provide Resolver implementation that uses the asyncio eventloop (#3111)
authorThomas Grainger <tagrain@gmail.com>
Fri, 18 Mar 2022 16:57:32 +0000 (16:57 +0000)
committerGitHub <noreply@github.com>
Fri, 18 Mar 2022 16:57:32 +0000 (12:57 -0400)
* provide Resolver implementation that uses the asyncio eventloop

* switch to the DefaultLoopResolver by default

maint/scripts/test_resolvers.py
tornado/netutil.py

index 82dec30e669fda7e6ec3c537dab31e104728df9b..aea3a61f54772311dc2a21e2271018bf98d78972 100755 (executable)
@@ -4,7 +4,7 @@ import socket
 
 from tornado import gen
 from tornado.ioloop import IOLoop
-from tornado.netutil import Resolver, ThreadedResolver
+from tornado.netutil import Resolver, ThreadedResolver, DefaultExecutorResolver
 from tornado.options import parse_command_line, define, options
 
 try:
@@ -29,7 +29,7 @@ def main():
         args = ['localhost', 'www.google.com',
                 'www.facebook.com', 'www.dropbox.com']
 
-    resolvers = [Resolver(), ThreadedResolver()]
+    resolvers = [Resolver(), ThreadedResolver(), DefaultExecutorResolver()]
 
     if twisted is not None:
         from tornado.platform.twisted import TwistedResolver
index 68943d82503f8519d1f0e110b3251af3d9745164..3567b74d7ee51ed4a734ae510ec42eb859c45cc9 100644 (file)
@@ -15,6 +15,7 @@
 
 """Miscellaneous network utility code."""
 
+import asyncio
 import concurrent.futures
 import errno
 import os
@@ -322,6 +323,7 @@ class Resolver(Configurable):
 
     The implementations of this interface included with Tornado are
 
+    * `tornado.netutil.DefaultLoopResolver`
     * `tornado.netutil.DefaultExecutorResolver`
     * `tornado.netutil.BlockingResolver` (deprecated)
     * `tornado.netutil.ThreadedResolver` (deprecated)
@@ -332,6 +334,10 @@ class Resolver(Configurable):
     .. versionchanged:: 5.0
        The default implementation has changed from `BlockingResolver` to
        `DefaultExecutorResolver`.
+
+    .. versionchanged:: 6.2
+       The default implementation has changed from `DefaultExecutorResolver` to
+       `DefaultLoopResolver`.
     """
 
     @classmethod
@@ -340,7 +346,7 @@ class Resolver(Configurable):
 
     @classmethod
     def configurable_default(cls) -> Type["Resolver"]:
-        return DefaultExecutorResolver
+        return DefaultLoopResolver
 
     def resolve(
         self, host: str, port: int, family: socket.AddressFamily = socket.AF_UNSPEC
@@ -407,6 +413,25 @@ class DefaultExecutorResolver(Resolver):
         return result
 
 
+class DefaultLoopResolver(Resolver):
+    """Resolver implementation using `asyncio.loop.getaddrinfo`."""
+
+    async def resolve(
+        self, host: str, port: int, family: socket.AddressFamily = socket.AF_UNSPEC
+    ) -> List[Tuple[int, Any]]:
+        # On Solaris, getaddrinfo fails if the given port is not found
+        # in /etc/services and no socket type is given, so we must pass
+        # one here.  The socket type used here doesn't seem to actually
+        # matter (we discard the one we get back in the results),
+        # so the addresses we return should still be usable with SOCK_DGRAM.
+        return [
+            (fam, address)
+            for fam, _, _, _, address in await asyncio.get_running_loop().getaddrinfo(
+                host, port, family=family, type=socket.SOCK_STREAM
+            )
+        ]
+
+
 class ExecutorResolver(Resolver):
     """Resolver implementation using a `concurrent.futures.Executor`.
 
@@ -421,8 +446,8 @@ class ExecutorResolver(Resolver):
        The ``io_loop`` argument (deprecated since version 4.1) has been removed.
 
     .. deprecated:: 5.0
-       The default `Resolver` now uses `.IOLoop.run_in_executor`; use that instead
-       of this class.
+       The default `Resolver` now uses `asyncio.loop.getaddrinfo`;
+       use that instead of this class.
     """
 
     def initialize(