Skip to content

Instantly share code, notes, and snippets.

@ssanderson
Created May 15, 2018 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ssanderson/f625716602a4bd7c8ead0dd4befad8ea to your computer and use it in GitHub Desktop.
Save ssanderson/f625716602a4bd7c8ead0dd4befad8ea to your computer and use it in GitHub Desktop.
import gevent
import gevent.pool
import gevent.event
import gevent.socket
import gevent.monkey
gevent.monkey.patch_all()
class UnhappyEyeballs(Exception):
pass
def map_staggered(group, func, targets, sleep_time, result):
for t in targets:
# Start the next attempt.
group.spawn(func, t)
# Wait until either ``sleep_time`` elapses, or one of the tasks
# completes successfully.
result.wait(timeout=sleep_time)
# If the result is ready, we're done.
if result.ready():
return
# If we get here, everyone failed (or took too long).
result.set_exception(UnhappyEyeballs("Took too long to connect."))
def open_tcp_socket(hostname, port, *, timeout=0.250):
group = gevent.pool.Group()
result = gevent.event.AsyncResult()
targets = gevent.socket.getaddrinfo(
hostname, port, type=gevent.socket.SOCK_STREAM,
)
def attempt(target):
*socket_config, _, socket_target = target
socket = gevent.socket.socket(*socket_config)
socket.connect(socket_target)
result.set(socket)
group.spawn(map_staggered, group, attempt, targets, timeout, result)
try:
return result.wait()
finally:
group.kill()
print(open_tcp_socket("debian.org", "https"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment