# `GeoGenius.Downloaders.Req`
[🔗](https://github.com/agoodway/geo_genius/blob/main/lib/geo_genius/downloaders/req.ex#L1)

Streams an artifact to disk with Req, hashing as it goes.

Req is an optional dependency: a host whose artifacts are all
operator-supplied never downloads anything and need not install it.
`available?/0` reports whether it is loaded, and `fetch/3` says so plainly
rather than raising `UndefinedFunctionError` deep inside a phase.

The body is written to `destination <> ".part"` as it streams and renamed
onto `destination` only once a 200 response has fully arrived. Any other
status, a transport failure, a raised exception, or an `exit`/`throw`
removes the partial file and leaves `destination` untouched.

Req-level retries are fixed off and cannot be re-enabled through `opts`. The
destination file handle is opened once and written to as chunks arrive; a
Req-level retry re-enters the adapter with a fresh response, so the hash
state and byte count carried on that response reset while the handle keeps
appending. The result is a file containing both attempts concatenated
together, with a reported `sha256`/`bytes` covering only the last one:
corruption that passes checksum verification.

Rate limiting is retried here instead, from the top and over a fresh handle.
A `429` or `503` response closes the handle, removes the partial file, waits,
and starts the request again, up to `opts[:max_attempts]` times (default
5). The wait honors a `Retry-After` header given in
seconds and otherwise doubles from 1000 ms per attempt, capped
at 60000 ms. Any other non-200 status is final. `opts[:sleep]`
replaces `Process.sleep/1` for tests.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
