Skip to content
/ process Public

Provides a Clojure library to layer functions into a single process workflow.

Notifications You must be signed in to change notification settings

pliant/process

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

About

Provides a Clojure library to layer functions into a single process workflow. Like the Clojure multimethod functionality, process allows for the ability to execute branches of logic based on the context of function call(arguments, etc).

Similaritities multimethod process
Define a callable function clojure.core/defmulti pliant.process/defprocess
Define branches of logic to execute clojure.core/defmethod pliant.process/deflayer

But process differs in how the dispatching is performed. Where multimethod defines a single dispatch function and matches the value it returns to a single method to execute, process allows for each layer that is added to it, starting with the first layer in order, to determine if it will execute or not, as well as whether it will allow the next layer to be executed.

Differences multimethod process
Dispatching Single dispatch function that is matched to a single method to execute Each layer determines if it is executed.
Workflow of execution None. Only one method is executed. Can execute one or many layers on a single call, as well as skipping over layers and performing callbacks.
Default logic execution Available when method is added with :default dispatch value Inherent in the defining of defmethod
Ordering vs Prefer Prefers one method over another with same dispatch value with prefer-method Can set order of execution of layers with before

Usage

Creating a process is just like creating a function, except instead of using defn you use pliant.process/defprocess .

(use 'pliant.process)

(defprocess myprocess
  "This is my process doc"
  [arg1 arg2]
  (println "Running default logic with args:" arg1 arg2))

The process function myprocess can be called just like a normal function.

user=> (myprocess 1 2)
Running default logic with args: 1 2
nil

Adding a layer to the process is done using pliant.process/deflayer.

(deflayer myprocess mylayer1 
  [arg1 arg2] 
  (if (= arg2 4) 
    (println "Running layer1 logic with args:" arg1 arg2) 
    (continue)))
user=> (myprocess 1 2)
Running default logic with args: 1 2
nil
user=> (myprocess 1 4)
Running layer1 logic with args: 1 4
nil

Layering

Differences emerge from multimethod when execution is based off of different criteria:

(deflayer myprocess mylayer2 
  [arg1 arg2] 
  (if (:doit arg1) 
    (println "Running layer2 logic with args:" arg1 arg2) 
    (continue)))

(deflayer myprocess mylayer3
  [arg1 arg2] 
  (if (roles/is-manager (session/user))
    (println "Running layer3 logic with args:" arg1 arg2) 
    (continue)))

Ordering Execution

By default layers are executed in the order that they are read into Clojure. To change the order you can currently use the pliant.process/before function.

user=> (before mylayer3 mylayer2)
nil

Flow Control

Controlling the flow of a process is performed by calling one of the flow control functions at the end of your logic, which returns a value to the processes internal controller. If a layer returns any value, including nil, that is not generated from one of the flow control functions the execution of the process is considered complete and that value is returned. The available flow control functions are:

Control Flow Function Instruction
pliant.process/continue Continue to and attempt to execute the next layer on the process.
pliant.process/skip Continue to and attempt to execute the next layer on the process. Skip a layer if it matches any of the layer functions that have been provided to the skip function.
pliant.process/callback Continue to and attempt to execute the next layer on the process. When finished executing layers execute the function provided with the value returned from the last layer.
pliant.process/skipback Continue to and attempt to execute the next layer on the process. Combines the ability to skip layers and perform a callback.

Continue Example

(deflayer myprocess mycontinue 
  [arg1 arg2] 
  (if (= arg1 arg2) 
    true 
    (continue)))

Skip Example

(deflayer myprocess myskip 
  [arg1 arg2] 
  (if (= arg1 arg2) 
    (skip mycontinue) 
    (continue)))

Callback Example

(deflayer myprocess mycallback 
  [arg1 arg2] 
  (if (= arg1 arg2) 
    (callback (fn [val] (if val "Yes" "Nope"))) 
    (continue)))

Skipback Example

(deflayer myprocess myskipback
  [arg1 arg2] 
  (if (= arg1 arg2) 
    (skipback (fn [val] (if val "Yes" "Nope")) mycontinue) 
    (continue)))

Process As Method

In order to combine the patterns that multimethod and process provide, the pliant.process/as-method function enables integration between the two.

(defmulti handle-http uri->process) ;; uri->keyword psuedo fn to change a http request uri to a keyword

(defprocess root [request] (redirect "/login"))
(defprocess login [request] (render-login))

(as-method root handle-http :get)
(as-method login handle-http :get-login)

(deflayer login shib-login [request] (if (auth/use-shib? request) (redirect-to-shib request) (continue))

About

Provides a Clojure library to layer functions into a single process workflow.

Resources

Stars

Watchers

Forks

Packages

No packages published