Liking cljdoc? Tell your friends :D
elasticpath logo

Fonda

An async pipeline approach to functional core - imperative shell from by Gary Bernhardt's Boundaries talk.

Asynchronous pipeline of steps

Fonda sequentially executes an (a)synchronous series of steps, one after the other, augmenting a context map.

After the steps are run, the optional loggers are called.

After the loggers are called, the callbacks will be called.

Fonda distinguishes between exceptions and anomalies as errors.

Anomalies are just data that define a recoverable "business" error, as opposed to a thrown JavaScript js/Error, Promise error or Java Exception, which never meant to be caught and are usually caused by programming bugs.

By default, Fonda wraps the anomalies in a map with the key :cognitect.anomalies/anomaly.

It is possible to redefine what an anomaly is by passing the predicate anomaly? to the configuration.

Syntax

(execute config steps initial-ctx on-success on-anomaly on-exception)
  • config A map with:
KeyOptional?Notes
:anomaly?YesA function that gets a map and determines if it is an anomaly
:log-exceptionYesA function that gets called with the runtime when there is an exception
:log-anomalyYesA function that gets called with the anomalies runtime context when a step returns an anomaly
:log-successYesA function that gets called after all the steps succeed
  • steps: Each item on the steps collection must be either a Tap or a Processor

###Tap:

KeyOptional?Notes
:tapNoA function that gets the context but doesn't augment it
:nameNoThe name of the step

###Processor:

KeyOptional?Notes
:processorNoA function that gets the context returns a result that is assoced into the context on the given path
:pathNoPath where to assoc the result of the processor
:nameNoThe name of the step
  • initial-ctx The context data that gets passed to the steps functions. Must be a map.

  • on-success Callback that gets called with the context if all steps succeeded.

  • on-anomaly Callback that gets called with an anomaly when any step returns one.

  • on-exception Callback that gets called with an exception when any step triggers one.

Error and Anomaly Handling

  • If any step returns an anomaly, or triggers an exception, the execution of the steps stops and the global taps will be called.

  • If any step returns an anomaly, the log-anomaly will be called with the RuntimeContext, and then the on-anomaly callback

  • If any step triggers an exception, the log-exception will be called with the RuntimeContext, and then on-exception callback.

Processor steps

Processors are maps with the following keys:

  • :processor A function that gets a context map and returns data. Can be asynchronous. If it returns an anomaly, or it triggers an error, further steps execution will be short-circuited.
  • :path A vector that determines where in the context will the resolve result be associated.
  • :name A descriptive name for the step

Tap steps

Taps are maps with the following keys:

  • :tap A function that gets the context map. If it succeeds, the result is then ignored. It will still block the steps processing if it is asynchronous, and it will interrupt the steps execution if it returns an anomaly, or it triggers an exception
  • :name A descriptive name for the step

Runtime context

Log functions are called with the runtime context. The runtime context is a map that contains, among other things, the context that is passed to each step. It also contains:

  • :step-log A collection of step logs. By default only step names are logged.

Example

(fonda/execute
  {:log-exception   (fn [{:keys [ctx error step-log]}] 
                      (js/console.log "Exception happened:" error))
   
   :log-anomaly     (fn [{:keys [ctx anomaly step-log]}] 
                      (js/console.log "An anomaly happened:" anomaly))
   
   :log-success     (fn [{:keys [ctx step-log]}] 
                      (js/console.log "Operation successful!"))
   }
  
  [
   ;; Processor that retrieves data remotely
   {:processor      (fn [ctx] 
                      (ajax/get "http://remote-thing-url"))
    :name             "get-remote-thing"
    :path             [:remote-thing] }
   
   ;; Processor that processes the data
   {:processor      (fn [{:keys [remote-thing]}] 
                       (process-remote-thing remote-thing))
    :name             "process-thing"
    :path             [:remote-thing-processed]}
   
   ;; Tap that logs things
   {:tap            (fn [{:keys [remote-thing]}] 
                      (js/console.log "remote thing:"))}
   ]

  ;; On success
  (fn [{:keys [remote-thing-processed]}] 
   (call-on-success-cb remote-thing-processed))
   
  ;; On anomaly
  (fn [anomaly] 
   (call-on-anomaly-cb anomaly))
   
  ;; On error
  (fn [error] 
   (call-on-error-cb error)))

Trivia

The name fonda got inspired by Jane Fonda's step fitness programs.

As with the fitness program, fonda consist of well-curated steps.

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close