Filo stops being server-only: it now ships a Hrana client built on the same
codec, plus an authorization seam that works on both transports. Everything here is
additive — a host on 0.1.0 upgrades without code changes.
Added
Filo.Client— a Hrana client mirroring the server's codec, so there is no
second implementation of the wire format to drift from. One client is one Hrana
stream over one owned connection, with baton threading, so a transaction is a
burst ofexecute/3on a held connection. Scope is the Hrana 2/3 HTTP JSON
pipeline. The HTTP round-trip is aFilo.Client.Transportbehaviour; the default
Filo.Client.Transport.Mintuses the optional:mintdependency, so
server-only hosts never pull it in.- Transparent stream resume. A dropped connection is retried with the same
baton, resuming the Hrana stream instead of abandoning it. This matters behind a
load balancer that recycles an idle client keep-alive after N requests — that used
to kill a held transaction mid-flight. - An optional
:authorizeseam gating every stream open, on both transports.
It is a Filo callback rather than a plug because WebSocket clients send no upgrade
header: the credential arrives in the Hranahelloframe, which only Filo sees. - Authorize context threaded to
Executor.open/2.:authorizemay return
{:ok, context}; Filo threads that host-opaque value intoopen/2for every
stream the connection opens — the HTTP stream that opens in its own process, the
stateless v1 open, and every WebSocketopen_streamafter the hello.open/2is
in@optional_callbacks, so an executor that only implementsopen/1keeps
working and the context is dropped. Not a breaking change. - Streams monitor their connection owner and tear down when it dies, so an
orphaned stream cannot outlive the process that opened it.
Changed
- Cursor entries batch into ~32 KiB transport chunks instead of one write per
ndjson entry. - Direct-to-iodata JSON row encoding (
Filo.Value.encode_json,rows: :json)
and pre-encoded row fragments on the JSON paths, with iodata carried through to
the send sites — fewer intermediate binaries per result. - Idle-timer cancellation is async, and the host can set a process policy for
stream processes.
Fixed
- A malformed WebSocket text frame now closes with 1007 (invalid frame payload
data) rather than a bare 1000, so a client can tell a protocol error from a normal
close.
Install
{:filo, "~> 0.2.0"}Published on Hex: https://hex.pm/packages/filo · Docs: https://hexdocs.pm/filo/0.2.0