Project

finist

0.01
No commit activity in last 3 years
No release in over 3 years
Finist is a finite state machine that is defined and persisted in Redis.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0

Runtime

>= 0
 Project Readme

Finist

Redis based Finite State Machine.

Description

Finist is a finite state machine that is defined and persisted in Redis.

Community

Meet us on IRC: #lesscode on freenode.net.

Related projects

Getting started

Install Redis. On most platforms it's as easy as grabbing the sources, running make and then putting the redis-server binary in the PATH.

Once you have it installed, you can execute redis-server and it will run on localhost:6379 by default. Check the redis.conf file that comes with the sources if you want to change some settings.

Usage

Finist requires a Redic compatible client. To make things easier, redic is listed as a runtime dependency so the examples in this document will work.

require "finist"

# Initialize with a Redis client, the name of the machine and the
# initial state. In this example, the machine is called "order" and
# the initial status is "pending". The Redis client is connected to
# the default host (127.0.0.1:6379).
machine = Finist.new(Redic.new, "order", "pending")

# Available transitions are defined with the `on` method
# `machine.on(<event>, <initial_state>, <final_state>)`
machine.on("approve", "pending", "approved")
machine.on("cancel", "pending", "cancelled")
machine.on("cancel", "approved", "cancelled")
machine.on("reset", "cancelled", "pending")

Now that the possible transitions are defined, we can check the current state:

machine.state
# => "pending"

And we can trigger an event:

machine.trigger("approve")
# => ["approved", true]

The trigger method returns an array of two values: the first represents the current state, and the second represents whether a transition occurred.

Here's what happens if an event doesn't cause a transition:

machine.trigger("reset")
# => ["approved", false]

Here's a convenient way to use this flag:

state, changed = machine.trigger("reset")

if changed
  printf("State changed to %s\n", state)
end

If you need to remove all the transitions for a given event, you can use rm:

machine.rm("reset")

Note that every change is persisted in Redis.

Representation

Each event is represented as a hash in Redis, and its field/value pairs are the possible transitions.

For the FSM described in the examples above, the keys are laid out as follows:

# Current state
finist:order (string)

# Transitions for event `approve`
finist:order:approve (hash)
	pending   -> approved

# Transitions for event `cancel`
finist:order:cancel (hash)
	pending   -> cancelled
	approved  -> cancelled

# Transitions for event `reset`
finist:order:reset (hash)
	cancelled -> pending

Installation

$ gem install finist