ExMachine.ServerMachine (ex_machine v0.1.3)
View SourceGenServer-based statechart execution server.
This module provides a GenServer wrapper around ExMachine statecharts, allowing statecharts to run as supervised processes that can handle events asynchronously and maintain their state across multiple interactions.
Features
- Supervised Process: Runs as a GenServer that can be supervised
- Asynchronous Event Processing: Handle events without blocking callers
- State Persistence: Maintains statechart state across events
- Event Queuing: Built-in event queue for handling concurrent events
- Monitoring: Built-in logging and monitoring capabilities
- Fault Tolerance: Automatic restart and recovery through supervisor trees
Usage
To use ExMachine.ServerMachine, you typically create a module that defines your statechart and then start it as a GenServer:
defmodule MyStatechartServer do
use ExMachine.ServerMachine
# Define your statechart
def init_statechart() do
%{
initial: "idle",
states: %{
"idle" => %{
transitions: %{
"start" => "working"
}
},
"working" => %{
transitions: %{
"complete" => "idle",
"error" => "error"
}
},
"error" => %{
transitions: %{
"reset" => "idle"
}
}
}
}
end
# Optional: customize initial context
def init_context() do
%{
start_time: System.system_time(:second),
error_count: 0
}
end
end
# Start the server
{:ok, pid} = MyStatechartServer.start_link(name: :my_statechart)
# Send events
MyStatechartServer.send_event(pid, :start)
MyStatechartServer.send_event(pid, {:complete, %{result: "success"}})
# Get current state
current_state = MyStatechartServer.get_state(pid)
Supervision
ExMachine.ServerMachine processes can be easily supervised:
defmodule MyApp.Supervisor do
use Supervisor
def start_link(init_arg) do
Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__)
end
def init(_init_arg) do
children = [
{MyStatechartServer, name: :my_statechart}
]
Supervisor.init(children, strategy: :one_for_one)
end
end
Advanced Features
Custom Event Handling
defmodule AdvancedStatechartServer do
use ExMachine.ServerMachine
# Override handle_event for custom processing
def handle_event(event, state) do
# Custom preprocessing
event = preprocess_event(event)
# Call default handler
result = super(event, state)
# Custom postprocessing
postprocess_result(result)
end
end
State Change Callbacks
defmodule CallbackStatechartServer do
use ExMachine.ServerMachine
# Called whenever state changes
def on_state_change(old_config, new_config, context) do
Logger.info("State changed from #{inspect(old_config)} to #{inspect(new_config)}")
end
# Called on macrostep completion
def on_macrostep_complete(completed_macrostep) do
Metrics.increment("statechart.macrosteps")
Metrics.histogram("statechart.transition_count", length(completed_macrostep.transitions))
end
end
Error Handling
The ServerMachine includes built-in error handling for common scenarios:
- Invalid Events: Events that don't trigger any transitions are ignored
- Action Failures: Failed actions are logged but don't crash the server
- Guard Failures: Failed guards prevent transitions but don't crash
- Malformed Events: Invalid event formats are logged and ignored
Performance Considerations
- Events are processed sequentially to maintain statechart semantics
- Large contexts should avoid deep copying by using references
- Consider using
cast
for fire-and-forget events - Use
call
when you need confirmation of event processing
NOTE
This module is currently a placeholder and needs implementation. The documentation above represents the intended API and functionality.