refactor(swarm-queue-client): typed errors for the bucket and the guard

Finishes the anyhow removal for the parts this branch adds: the status
bucket's open-or-create and the connected-client precondition. Two
variants, one of them behind the `kv` feature because the error type it
wraps does not exist without it — the error enum respects the same gate
the module does.

NotConnected is deliberately distinct from Connect: one is a connect that
was attempted and refused, the other is a request made before any
connection exists. The first is a deployment problem and the second is a
caller-ordering one, which is the whole reason a caller wants an enum
rather than a string.

The controller's `store` now returns the queue client's error rather than
an anyhow one: `OnceCell::get_or_try_init` takes its error type from the
closure, so widening there would mean converting inside the closure for
no gain. `view` `?`s it and anyhow converts at that boundary — the
library keeps a typed error, the binary keeps anyhow, and no call site
pays for the split.
This commit is contained in:
atlas 2026-08-15 23:14:06 +02:00
commit 3273971328
3 changed files with 33 additions and 6 deletions

View file

@ -155,7 +155,16 @@ impl StatusReader {
///
/// Whichever side arrives first creates it, and both sides ask for the
/// same shape, so this is a race with one outcome.
async fn store(&self) -> Result<&async_nats::jetstream::kv::Store> {
///
/// Returns the queue client's own error rather than an `anyhow::Error`:
/// `OnceCell::get_or_try_init` takes its error type from the closure,
/// so widening here would mean converting *inside* the closure for no
/// gain. `view` below `?`s it and anyhow converts there — which is the
/// whole point of the library keeping a typed error while the binary
/// keeps anyhow.
async fn store(
&self,
) -> std::result::Result<&async_nats::jetstream::kv::Store, swarm_queue_client::Error> {
self.store
.get_or_try_init(|| swarm_queue_client::status::open_or_create(&self.client))
.await