Note

Julio.jl is still work-in-progress.

Example: Happy Eyeballs

using Sockets
using Julio
using Test

An implementation of Happy Eyeballs (RFC 8305) https://datatracker.ietf.org/doc/html/rfc8305

(TODO: verify)

function happy_eyeballs(host, port; delay = 0.3)
    addrs = getalladdrinfo(host)
    winner = Julio.Promise()
    decided = nothing
    allsockets = TCPSocket[]
    Julio.withtaskgroup() do tg
        issuccess = false
        closing = Threads.Atomic{Bool}(false)
        try
            failureevents = []
            for ip in addrs
                failed = Julio.Promise{Nothing}()
                push!(failureevents, failed)
                socket = TCPSocket()
                push!(allsockets, socket)
                Julio.spawn!(tg) do
                    try
                        connect(socket, ip, port)
                    catch err
                        if err isa Base.IOError
                            failed[] = nothing
                            return
                        elseif closing[]
                            return
                        end
                        rethrow()
                    end
                    Julio.tryput!(winner, socket)
                end
                Julio.select(
                    (fetch, winner) => socket -> begin
                        decided = socket
                        true
                    end,
                    (fetch, failed) => _ -> false,
                    (sleep, delay) => _ -> false,
                ) && break
            end
            if decided === nothing
                for failed in failureevents
                    Julio.select(
                        (fetch, winner) => socket -> begin
                            decided = socket
                            true
                        end,
                        (fetch, failed) => _ -> false,
                    ) && break
                end
            end
            issuccess = true
        finally
            closing[] = true
            for socket in allsockets
                if !issuccess || socket !== decided
                    close(socket)
                end
            end
        end
    end
    return decided
end
function test_happy_eyeballs()
    socket = happy_eyeballs("httpbin.org", 80)
    try
        @test socket isa TCPSocket
        @test isopen(socket)
    finally
        close(socket)
    end
end

This page was generated using Literate.jl.