std.concurrent.request-apply
applicative functions backed by request clients
Package request construction, bulk behavior, retries, transforms, and default clients as invokable applicative values.
1 Overview
ReqApplicative bridges std.lib.apply and the request orchestration layer. Calling an applicative builds one or more commands, selects single, bulk, transactional, or retry execution, and optionally transforms inputs and outputs.
2 Walkthrough
2.1 Construct an applicative
(require '[std.concurrent.request-apply :as request-apply])
(def add-request
(request-apply/req:applicative
{:type :single
:client +
:function (fn [args _opts] args)
:options {}
:transform {}}))
(add-request 1 2 3)
2.2 Select an execution mode
Use :bulk or :transact when the function returns several applicatives. Use :retry with a predicate and retry function to recover from selected failures.
(request-apply/req:applicative
{:type :bulk
:client client
:function build-commands
:options {:bulk {:async true}}
:transform {:in normalize-input
:out normalize-output}})
3 Extension point
Add another req-call method when an application needs a request execution strategy beyond the built-in single, bulk, transaction, and retry modes.
4 API
req-apply-in ^
[{:keys [options transform], :as app} rt args]
Added 3.0
runs a request applicative
v 3.0
(defn req-apply-in
([{:keys [options transform] :as app} rt args]
(if (nil? rt)
(req/req:in (req-call app rt args options))
(let [opts (if (:out transform)
(req/req:opts options {:post [(fn [ret]
((:out transform) app rt args ret))]})
options)]
(req-call app rt args opts)))))
link
(with-redefs [req-call (fn [& args] (swap! req/*inputs* conj args))] (let [captured (req-apply-in {:options {:async true}} nil [:hello])] [(= 1 (count captured)) (= [{:options {:async true}} nil [:hello] {:async true}] (vec (first captured)))])) => [true true] (with-redefs [req-call (fn [_ _ _ opts] opts)] (let [opts (req-apply-in {:options {} :transform {:out (fn [_ _ _ ret] [:wrapped ret])}} :client [:hello])] [(map? opts) (= 1 (count (:post opts))) (fn? (first (:post opts)))])) => [true true true]
v 3.0
(defmulti req-call
(fn [{:keys [type]} _client _args _opts]
type))
link
(with-redefs [req/req-fn (fn [client command opts] [client command opts])] (let [[client command opts] (req-call {:type :single :function (fn [args _] {:type :echo :args args})} :client [:hello] {:async true})] [client command (:async opts) (contains? opts :context)])) => [:client {:type :echo, :args [:hello]} true true]