Liking cljdoc? Tell your friends :D

hive-dsl

Clojars Project cljdoc release License: MIT

The error-handling and value vocabulary the hive libraries are written in. A Result type, algebraic data types, total coercions, bounded state, and lifecycle scopes — portable .cljc with no dependency beyond Clojure, data.json and core.async.

Failures here are values, not control flow. A function that can fail returns (r/err :kind {:ctx …}); callers thread with let-ok / ok-> and never have to guess which exception a library will throw.

Coordinates

;; deps.edn
io.github.hive-agi/hive-dsl {:mvn/version "0.5.17"}

Result

(require '[hive-dsl.result :as r])

(r/ok 42)                               ;; => {:ok 42}
(r/err :db/timeout {:url url})          ;; => {:error :db/timeout, :url url}

;; Monadic let — binds :ok values, short-circuits on the first error
(r/let-ok [conn (connect! url)
           rows (query conn sql)]
  (r/ok (count rows)))

;; Thread-first with smart-wrap: a step returning a Result binds,
;; a step returning a plain value is auto-wrapped in ok
(r/ok-> (validate-order order catalog)
        price-order
        (acknowledge create-letter)
        log-order)

;; Supervision boundary — catch ANY throwable, return the fallback.
;; Error context rides along as metadata, not as a log line.
(r/rescue [] (traverse ids))            ;; => [] on failure
(::r/error (meta result))               ;; => {:message "…" :form "(traverse ids)"}

;; Selective catch, when you care WHAT failed
(r/guard java.io.IOException nil (slurp path))

let-ok is strict: a Result-bound right-hand side that evaluates to a non-Result throws with category :result/non-result-binding, naming the offending symbol — so a function that quietly stopped returning a Result is a loud failure rather than a silent one. Bind plain values with :let [v expr].

map-ok, map-err, bind, on-error, with-error-handler, ensure-result and rescue-log cover the rest of the surface. hive-dsl.result.taxonomy registers the error-category vocabulary so failures stay a closed, greppable set.

ADTs

(require '[hive-dsl.adt :as adt])

(adt/defadt EventType
  "Event types for hivemind communication."
  [:event/started  {:task string?}]
  [:event/progress {:message string?}]
  :event/completed)

(event-type :event/started {:task "X"})
;; => {:adt/type :EventType, :adt/variant :event/started, :task "X"}

(adt/adt-case EventType evt
  :event/started   (str "task: " (:task evt))
  :event/progress  (str "msg: "  (:message evt))
  :event/completed "done")

defadt generates the type var, a kebab-case constructor, a …? predicate, a ->… keyword coercion, and EventTypeMalli — one malli :multi schema for the whole ADT. adt-case checks exhaustiveness at macro-expansion time: a missing variant or a typo is a compile error, not a runtime nil.

Closed sets get an ADT. The variant table is the single definition; validation, serialize / deserialize and hive-dsl.adt.schema/adt->malli are all projections of it.

The rest

NamespaceProvides
hive-dsl.resultResult type, let-ok, ok->, rescue, guard
hive-dsl.result.taxonomyRegistry of error kinds
hive-dsl.result.agentopAgent-flavoured combinators — retry-on, with-budget, with-persona, fan-in
hive-dsl.adtdefadt, adt-case, variant construction and validation
hive-dsl.coerceTotal coercions — ->int, ->double, ->boolean, ->keyword, ->vec, ->enum, coerce-map
hive-dsl.bounded-atomSize-capped atom with sweeping, so a cache cannot grow without bound
hive-dsl.gatePermit gate returning Results
hive-dsl.lifecycleStart/stop scopes, managed executors and channels
hive-dsl.managed-channelcore.async channels owned by a scope — pub/sub and go-loops that close cleanly
hive-dsl.resourceAcquire/release scopes
hive-dsl.batchTransaction batching with a transparent batch scope
hive-dsl.context.identityCaller-id and project-scope encoding
hive-dsl.typed.emitTyped Clojure annotations emitted from the ADT tables

Portability

The shipped namespaces are .cljc and are exercised on the JVM, on ClojureScript, and on cloture (Clojure on Common Lisp). The portable stratum is bounded by the poorest runtime that tests it, which is why the source avoids conveniences the third arm lacks.

Malli value objects live under schemas/, which is deliberately never on :paths — malli does not run on the native targets, so no shipped namespace may see it.

License

MIT.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close