8000 GitHub - pyr/maniflow: lightweight interceptor type library for manifold
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

pyr/maniflow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

maniflow: utilities on top of manifold

Build Status

[spootnik/maniflow "0.1.5"]

Lifecycle management

The manifold.lifecycle namespace provides a lightweight take on a mechanism similar to interceptors or sieppari. A key difference with interceptors is that individual handlers have no access to the step chain and thus cannot interact with it. Guards and early termination are still provided.

A lifecycle is nothing more than a collection of handlers through which a value is passed.

In essence:

@(run 0 [(step inc) (step inc) (step inc)])

Is thus directly equivalent to:

(-> 0 inc inc inc)

Lifecycle steps

As shown above, each step in a lifecycle is a handler to run on a value. Steps can be provided in several forms, all coerced to a map.

{:id    :doubler
 :enter (fn [input] (* input 2))
 :guard (fn [context] ...)}

Function steps

When a step is a plain function, as in (run 0 [inc]), the resulting map will be of the following shape:

{:id    :step12345
 :enter inc}

If the function is provided as a var, the qualified name of the var is used as the id, so for (run 0 [#'inc]) we would have instead:

{:id    :inc
 :enter inc}

Accessing parts of the input

Often times, the payload being threaded between lifecycle steps will be a map. As with interceptors, it might be useful to hold on to information accumulated during the chain processing. To help with this, maniflow provides three parameters for steps:

  • :in: specifies a path that will be extracted from the payload and fed as input to the handler
  • :out: specifies where in the payload to assoc the result of the handler
  • :lens: when present, supersedes the previous two parameters and acts as though both :in and :out where provided
{:id    :determine-deserialize
 :enter (partial = :post)
 :in    [:request :request-method]
 :out   [::need-deserialize?])

Step guards

Based on the current state of processing, it might be useful to guard execution of a step against a predicate, keeping with the last example:

{:id    :deserialize
 :enter deserialize
 :lens  [:request :body]
 :guard ::need-deserialize?}

Discarding results

Sometimes,

{:id       :debug
 :enter    prn
 :discard? true}

Building steps with step

The manifold.lifecycle/step function is provided to build steps easily, the above can thus be rewritten:

(enter-step :determine-deserialize (partial = :post) :in [:request :request-method] :out ::need-deserialize?)
(enter-step :debug prn :discard? true)
(enter-step :deserialize deserialize :guard ::need-deserialize?)
(enter-step :handler run-handler)

Global options

When running a lifecycle, an options map can be passed in to further modify the behavior:

{:augment    (fn [context step] ...)
 :initialize (fn [value] ...)
 :executor   ...}
  • augment: A function of context and current step called for each step in the lifecycle.
  • initialize: A function of init value to prepare the payload.
  • executor: An executor to defer execution on.

Error handling

There are intentionally no facilitie 65B8 s to interact with the sequence of steps in this library. Exceptions thrown will break the sequence of steps, users of the library are encouraged to use manifold.deferred/catch to handle errors raised during execution.

All errors contain the underlying thrown exception as a cause and contain the last known context in their ex-data

(-> (d/run 0 [(step inc) (step #(d/future (/ % 0))) (step inc)])
    (d/catch (fn [e]
	            (type (.getCause e))   ;; ArithmeticException
				(:context (ex-data e)) ;; last context)))

Timing wrapper

Assuming a map payload, timing can be recorded for each step with the initialize and augment implementations provided in manifold.lifecycle.timing:

@(run
  {:x 0}
  [(step :inc inc :lens :x) (step :inc inc :lens :x)]
  timing/milliseconds)

{:timing
 {:created-at 1569080525132,
  :updated-at 1569080525133,
  :index 2,
  :output [{:id :inc, :timing 0} {:id :inc, :timing 1}]},
 :x 2}

About

lightweight interceptor type library for manifold

Resources

License

Stars

Watchers

Forks

Packages

No packages published
0