The Async library for ruby is pure magic. Asynchronously running arbitrary ruby code, without having to deal with the pesky coloured functions of other languages, is beautiful and powerful.
I haven't explored the sister project, async-http, much at all until recently. I'm building a rails project which has both a web interface and an API. Posts to the API cause a cascade of model updates which trigger Turbo Streams refreshes in the browser.
A client gem makes the API calls. As they're all simple fire-and-forget POST messages, they're ideal for wrapping in async. Something like this:
def post(document, to:)
Async do
internet = Async::HTTP::Internet.new
body = document.to_json
endpoint = to
internet.post(endpoint, headers, body)
ensure
internet.close
end
end
This worked really well until my web server decided to negotiate HTTP/2 connections and the client died after the first POST.
warn: Async::HTTP::Client: connected to #<Addrinfo: [::1]:3000 TCP (localhost)>
| Waiting for Async::HTTP::Protocol::HTTP1 pool to drain: #<Async::Pool::Controller(1/∞) 1/1/1>
I really was tearing my hair out and briefly considered sending POSTs with the venerable HTTParty wrapped in an async block (I'm going to gush again about no coloured functions❤️)
This is all I needed to do: it's sets up a background reader to process the async HTTP response! doh!
def post(document, to:)
Async do
internet = Async::HTTP::Internet.new
body = document.to_json
endpoint = to
Async do
internet.post(endpoint, headers, body)
end
ensure
internet.close
end
end