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]

req-call ^

Added 3.0

extensible function for a request applicative

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]

req:applicative ^

[m]
Added 3.0

constructs a request applicative

v 3.0
(defn req:applicative
  ([m]
   (map->ReqApplicative m)))
link
(req:applicative {:type :single :client :demo}) => (contains {:type :single :client :demo})