Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bluzky/as_fsm
A finite state machine implementation for elixir
https://github.com/bluzky/as_fsm
elixir finite-state-machine fsm
Last synced: 3 months ago
JSON representation
A finite state machine implementation for elixir
- Host: GitHub
- URL: https://github.com/bluzky/as_fsm
- Owner: bluzky
- Created: 2018-04-13T08:25:07.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2021-07-30T04:40:57.000Z (over 3 years ago)
- Last Synced: 2024-10-13T23:17:43.542Z (4 months ago)
- Topics: elixir, finite-state-machine, fsm
- Language: Elixir
- Homepage: https://hex.pm/packages/as_fsm
- Size: 27.3 KB
- Stars: 14
- Watchers: 3
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Elixir Finite state machine
This package is inspired by [ecto_fsm](https://github.com/bluzky/ecto_fsm) package
This package allows to use [finite state machine pattern](https://en.wikipedia.org/wiki/Finite-state_machine) in elixir.
> I have rewritten this library to make code simple and easier to use
**Install**```elixir
def deps do
[
{:as_fsm, "~> 2.0.0"}
]
end
```## Usage
**First you to define FSM module**
```elixir
defmodule TaskFsm do
use AsFsm, repo: MyApp.Repo
# by default state is check from column `state` of struct
# you can specify your own with
# use AsFsm, repo: MyApp.Repo, column: :status# define your event
defevent(:start, from: :idle, to: :running)
defevent(:pause, from: :running, to: :paused)
defevent(:stop, from: [:running, :paused], to: :idle)# you can define some hook
# it is automatically invoked if defineddef before_start(context) do
# do something then return context
context
enddef on_start(context) do
# do something then return context
context
end
end
```All appropriate event function will be generated. In this example we have
```elixir
def start(context), do: ....
def paus(context), do: ....
def stop(context), do: ....
```**Then use it**
- Trigger an even transition
```elixir
my_task
|> TaskFsm.new_context(other_params)
|> TaskFsm.start()
```- Or trigger by name
```elixir
my_task
|> TaskFsm.new_context(other_params)
|> TaskFsm.trigger(:start)
```## Understand the context
```elixir
@type :: %Context{
struct: struct(),
state: any(),
valid?: boolean(),
error: String.t() | nil,
multi: Ecto.Multi.t() | nil
}
```
- `struct` is your data
- `state` any data you want to pass to transition, it could be parameter from client
- `valid?` if it is true, then data will be persisted
- `error` error message in case `valid?` is false
- `multi` is an `Ecto.Multi` you can pass a multi to `new_context()`, it make sure all action you do in a transaction## Event hook
For each event you can define 2 hook
- `before_hook` you can define this hook to check for some condition before doing transation
- `on_hook` this is your hook to do some logic on transactionThese 2 hooks must return a context. If you want to stop this transition, set `valid?` to false and return the context.
## Custom persist struct
You can define your own function to persist struct state. This function is run within Multi so that it must return `{:ok, data} | {:error, reason}````elixr
def persist(struct, new_state, _context) do
# do your update logic
# or write log here
end
```
## Options- Custom property name by default property name is :state
```elixir
defmodule ExampleFsm douse AsFsm,
column: :status,
end
```