1""" 2Extra bits to make your job easier. 3""" 4 5importrandom 6fromsocketimportAddressFamily,SocketKind 7 8 9importanyio10importhttpx1112from.importSessionPool1314
[docs]15classConstantPoolMixin(SessionPool):16"""17 A trivial pool mixin that uses the passed in URL(s).18 """1920urls:list[str]2122def__init__(self,urls:str|list[str]):23ifisinstance(urls,str):24self.urls=[urls]25else:26self.urls=list(urls)27super().__init__()28
343536asyncdef_get_ips(hostname:str|bytes,port:int|None=None):37"""38 Look up the IPs for a given hostname39 """40forgaiinawaitanyio.getaddrinfo(hostname,port):41matchgai:42case(AddressFamily.AF_INET,SocketKind.SOCK_STREAM,_,_,(addr,_)):43yieldaddr44case(45AddressFamily.AF_INET6,46SocketKind.SOCK_STREAM,47_,48_,49(addr,_,_,scope),50):51# IPv6 flow is without purpose and cannot be represented in addresses52ifscope:53yieldf"{addr}%{scope}"54else:55yieldaddr56case_:57continue5859
[docs]60classDnsPoolMixin(SessionPool):61"""62 Uses DNS round robin to find pool members.6364 Assumes that CouchDB is not behind a vhost or uses TLS.65 """6667url:httpx.URL6869def__init__(self,url:str):70self.url=httpx.URL(url)71super().__init__()72
[docs]73asyncdefiter_servers(self):74# The domain stack already does our shuffling75asyncforipin_get_ips(self.url.raw_host,self.url.port):76if":"inip:77ip=f"[{ip}]"78yieldstr(self.url.copy_with(host=ip))