GitXplorerGitXplorer
k

impresario

public
7 stars
4 forks
2 issues

Commits

List of commits on branch master.
Unverified
10b8e0530cfcd94f5520f7c5f4f61029b73e07dc

update readme

kkyleburton committed 11 years ago
Unverified
484ce13361b83109f2124e4266feb176d310f0ee

lein-release plugin: bumped version from 1.0.12 to 1.0.13-SNAPSHOT for next developemnt cycle

kkyleburton committed 11 years ago
Unverified
120fe74b208ca9204cf80632953b2f3d3929c0dc

lein-release plugin: preparing 1.0.12 release

kkyleburton committed 11 years ago
Unverified
cec4b8cd7ce3e1883fe7d68bcaa61e2fbb883726

Merge pull request #17 from relaynetwork/master

kkyleburton committed 11 years ago
Unverified
91f114933a30b02c357912d81bf15ec38795ba55

removed commented/old dependency list

committed 11 years ago
Unverified
9265ddcc773638ff9a9f297189fbdf1fbeafd70d

tests pass under all clojure versions

committed 11 years ago

README

The README file for this repository.

h1. Impresario

A light-weight workflow (state machine) library in Clojure.

h1. Overview

Impresario is a workflow system - mostly like a finite state machine, with the exception that an Impresario flow may transition through multiple nodes if the predicates defined in the flow allow for it.

Impresario flows are implemented as a map that defines the states, transitions, predicates that determine if those transitions should be followed and call back handlers which may be attached to specific events.

Workflow state is maintained in a map: the context. The context is availalbe to all of the predicates and triggers. Just as with many of the Clojure data strucutres, the context is immutable.

Predicates may access the context, but are unable to modify it. Triggers must return the context - which allows for modification by triggers.

Workflows once defined must be registered with Impresario in order to be used. When a workflow is registered, it is validated to ensure that: each state configured as the target of a transition exists; and each state in the flow is reachable (a state marked as a start state does not need to be reachable).

An Impresario flow must have a start state (marked with a @:start true@). The @on-enter!@ trigger for the :start state can be used to initialize the workflow's context.

h2. DSL

To make the process of defining the flows simpler, a DSL has been created. This is an example (from the unit tests) of a workflow that simulates a door. The door may be open or closed, and if the door is closed it may be locked. If the door is locked, it can not be opened.

(ns impresario.test.door-workflow
  (:use
   impresario.dsl
   impresario.core))

(on-enter! :start
  (assoc *context* :transitions []))

(defpredicate :start :closed
  true)

(defpredicate :open :closed
  (get *context* :close-door))

(defpredicate :closed :locked
  (get *context* :lock-door))

(on-enter! :locked
  (assoc *context* :locked? true))

(defpredicate :closed :open
  (and
   (not (get *context* :locked?))
   (not (get *context* :lock-door))))

(defpredicate :locked :closed
  (get *context* :locked?))

(on-transition! :locked :closed
  (dissoc *context* :locked?))

(on-transition-any!
  (update-in
   (dissoc *context* :close-door :lock-door :unlock-door)
   [:transitions]
   conj
   [*current-state* :=> *next-state*]))

(defmachine :door-workflow
  (state :start {:start true :transitions [:closed]})
  (state :closed {:transitions [:locked
                                :open]})
  (state :locked {:transitions [:closed]})
  (state :open   {:transitions [:closed]}))

(register-workflow :door-workflow *door-workflow*)

h3. Bindings

Impresario makes use of several bindings to allow handlers to not have to take a long list of parameters. The available bindings within a predicate or handler are:

  • workflow - the definition of the workflow
  • current-state - the current state
  • next-state - the subsequen state (if transitioning)
  • context - the context

h3. @defmachine@

This is used to define the workflow. It must be given a keyword which names the workflow. States are defined within the @defmachine@ form.

States are declared with the @state@ form. They must have a name and a map of properties. The properties may contain: @:start@, @:transitions@ or @:stop@. @:start@ indicates that the state is a start state, where the workflow may be entered. @:stop@ indicates that the state is terminal, and if reached the workflow should no longer transition.

NB: @defmachine@ will create a package level var with the name of your worklfow. In the example above it creates @door-workflow@. This var contains the definition of your workflow.

To support interactive development, if you type in a @defmachine@ and attempt to evalutate it without defining the required predicates, Impresario will include a simple template for the predicate as part of the error message so that you may cut and paste it into your editor as a baseline.

h3. @register-workflow@

This funtion adds your workflow into the Impresario registry. It takes the name of the workflow (as a keyword) and the workflow definition.

h3. @defpredicate@

This is used to define a function in your package that will act as a transition predicate between two states.

h3. @on-enter-any!@

This declares a trigger that is fired any time a state is entered. Note that the body of this handler must return the context.

h3. @on-enter!@

Given a state name and a body, this will be the handler called when the workflow transitions into the given state.

h3. @on-exit!@

Given a state name and a body, this will be the handler called when the workflow transitions out of the given state.

h3. @on-transition-any!@

The body of this form will be called any time any transition is made. @*current-state@ and @next-state@ will be set to the names of the states involved in the transition.

h3. @on-transition!@

Given a from state, a to state and a body, will invoke the body whenever the specified edge is followed in the workflow.

h1. Installation

h3. "Leiningen":https://github.com/technomancy/leiningen

pre. [com.github.kyleburton/impresario "1.0.12"]

h3. Maven

pre. com.github.kyleburton impresario 1.0.12

h1. Future Direction

h3. Workflow Versioning

Introduce a second form of register-workflow that accepts a version. Make the default (when unspecified) "1.0.0".

h3. global exception state

A declared state, with possible transition's out, but no explicit edges leading in. If any predicate or trigger throws an exception, this state is entered. This gives the exception state the ability to handle errors and transition to one of the other states - or abort the workflow completely (by re-raising the exception).

h3. Timeouts

Each node should have the ability to declare a particular edge to be followed after some amount of time has elapsed.

Workflows should support a 'global' timeout. If the workflow has not transitioned (or been woken up) in the declared time span, it should cause an exception within the workflow. This allows workflow instances to be expired, discarded, etc.