-
Notifications
You must be signed in to change notification settings - Fork 1
Adds StateMachine GenServer and examples #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Codecov Report❌ Patch coverage is
🚀 New features to boost your workflow:
|
- **Statifier.StateMachine**: GenServer wrapper around StateChart for async processing
- Supports SCXML file paths and XML string initialization
- Async event processing with send_event/2-3
- Query methods: active_states/1, get_state_chart/1
- Proper error handling with descriptive error tuples via {:shutdown, reason}
- **Statifier.send/2-3**: Async event sending to StateMachine processes
- **Statifier.send_sync/2-3**: Sync event sending to StateChart (delegates to Interpreter)
- File and XML string initialization with proper validation
- Async event processing with GenServer cast
- Clean separation between sync (StateChart) and async (StateMachine) workflows
- Comprehensive test coverage (9 new tests)
- Descriptive error handling preserving full error context
- All 867 tests pass
- No credo issues
- No dialyzer warnings
- Full type specs and documentation
Phase 1 establishes the foundation for async state chart processing
while maintaining compatibility with existing sync API.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- **Statifier.Supervisor**: DynamicSupervisor for StateMachine process lifecycle
- start_child/2-3: Create supervised StateMachine processes
- terminate_child/2: Gracefully terminate StateMachine processes
- which_children/1: List all supervised processes
- count_children/1: Get process counts and statistics
- Automatic restart on crashes with :one_for_one strategy
- **Dual initialization modes**: Handles both direct and supervisor-based startup
- Direct: `StateMachine.start_link(init_arg, opts)`
- Supervised: Uses `{init_arg, opts}` tuple format
- **Named process support**: Full GenServer name registration through supervisor
- **Proper child specifications**: Custom child specs with permanent restart strategy
- **OTP-compliant supervision**: DynamicSupervisor with configurable strategies
- **Process isolation**: Individual StateMachine crashes don't affect others
- **Cluster-ready architecture**: Foundation for future distributed deployment
- **Comprehensive testing**: 11 new tests covering all supervision scenarios
- **Automatic restart behavior**: Crashed processes restart with same configuration
- All 878 tests pass (+11 new tests)
- No credo issues
- No dialyzer warnings
- Full type specs and documentation
```elixir
{:ok, supervisor} = Statifier.Supervisor.start_link()
{:ok, pid} = Statifier.Supervisor.start_child(supervisor, "machine.xml")
{:ok, named_pid} = Statifier.Supervisor.start_child(supervisor, xml, name: :my_machine)
children = Statifier.Supervisor.which_children(supervisor)
%{active: count} = Statifier.Supervisor.count_children(supervisor)
:ok = Statifier.Supervisor.terminate_child(supervisor, pid)
```
Phase 2 establishes proper OTP supervision for async StateMachine processes,
enabling production-ready process management and fault tolerance.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create Statifier.StateMachineBehaviour defining optional callbacks - Add __using__ macro to Statifier.StateMachine for generating boilerplate - Implement callback support in StateMachine GenServer: * State transition callbacks (enter, exit, transition) * Action callbacks (send, assign, log) * Lifecycle callbacks (init, snapshot) - Add comprehensive test suite for macro system - Support named GenServers and snapshot intervals - All tests passing with 91.2% coverage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit implements the foundational examples infrastructure for demonstrating Statifier's GenServer-based workflow capabilities: - **Purchase Order Approval Workflow**: Complete business process example - Multi-level approval routing based on amounts (≤$5K manager, >$5K exec) - SCXML definition with conditional transitions and data model - GenServer implementation with business logic callbacks - State persistence, logging, and comprehensive error handling - **Examples Infrastructure**: Extensible framework for future workflows - Mix project with proper dependency management and path references - CLI interface for running and listing examples - Structured testing with @describetag :example tags - Demo scripts with realistic business scenarios - **Production Patterns**: Real-world workflow engine foundations - Debug logging enabled by default for state machine visibility - Comprehensive test coverage for all approval paths - Documentation with usage examples and API reference - Callback system for notifications and business logic integration - SCXML workflow definitions in approval_workflow/scxml/ - StateMachine modules using Statifier.StateMachine macro - Comprehensive tests covering happy path and rejection scenarios - Mix aliases for `examples.run` and `examples.test` commands - Ready for Phase 2 enhancements (persistence, complex workflows) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit resolves the start_link/1 default argument conflict and test tag placement issues that were preventing examples from compiling: ## Fixed Issues - **start_link conflict**: Removed custom start_link/1 with defaults that conflicted with macro-generated function. Now uses generated start_link from Statifier.StateMachine macro without override. - **@describetag placement**: Fixed @describetag placement inside describe blocks. Added module-level @tag :example as requested. - **Compilation success**: Examples now compile and run successfully - `mix compile` works without errors - `mix examples.run list` shows available examples - `mix examples.run approval_workflow` executes demo ## Current Status ✅ **Infrastructure**: Examples compile and CLI works ❌ **Event data**: SCXML assign actions not working properly ❌ **Tests**: 6/8 tests failing due to event data issues ## Next Steps Phase 1 infrastructure is complete but event data assignment needs debugging. The SCXML expressions `_event.data.po_id` → `po_id` are not working as expected. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Maps internal :warn log level to :warning for compatibility with Elixir 1.15+ which deprecated :warn in favor of :warning. The fix maintains backward compatibility by keeping :warn as the internal API while properly mapping to :warning when calling Elixir's Logger functions. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Updates StateMachine to properly pass log_level and log_adapter options through to the Interpreter during initialization. This allows examples to enable trace logging for detailed debugging of state machine execution. Changes: - StateMachine now extracts and passes interpreter options (log_level, log_adapter) - Demo script updated to use log_level: :trace for all scenarios - Removed custom handle_init that was trying to configure logging incorrectly - Updated documentation to list available logging options Note: Trace logs are generated but mapped to :debug level in Elixir's Logger since it doesn't have a native :trace level. Ensure Logger.configure(level: :debug) to see trace output. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
The examples config was using compile_time_purge_matching to remove all logs below :info level at compile time, preventing debug and trace logs from ever being generated. Removed the compile-time purging and set default level to :debug to allow trace logs (which map to debug in Elixir's Logger) to be shown when requested. Now when running examples with log_level: :trace, you will see: - Processing microstep (trace level) - Transition evaluations (debug level) - Action executions (debug level) - Configuration changes (debug level) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Auto-formatted code using mix format and applied Credo linting suggestions across the codebase. Changes include: - Consistent indentation and spacing - Removed trailing whitespace and added final newlines - Fixed line length violations - Improved code readability and consistency This maintains code quality standards while preserving all functionality from the trace logging and examples implementation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Core implementation migration with full code quality compliance: - Migrates PurchaseOrderMachine from examples_old to umbrella app structure - Updates module namespaces from Examples.ApprovalWorkflow to ApprovalWorkflow - Relocates SCXML file to priv/scxml/purchase_order.xml in app structure - Adds comprehensive @SPEC type specifications for all functions - Implements proper module aliasing to eliminate nested module warnings - Fixes unused variable naming for consistency (credo compliance) - Adds formatter configuration for umbrella project with Statifier integration - Updates tests to verify basic workflow functionality The core state machine is now fully functional in the new structure with all credo quality checks passing. Ready for Phase 2 comprehensive testing migration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Introduces a comprehensive GenServer-based StateMachine system with production-ready examples and enhanced developer experience.
Key Changes
StateMachine GenServer Infrastructure:
Examples Umbrella Application:
Enhanced Developer Experience:
Technical Improvements:
The examples now serve as production-ready templates for building workflow engines with Statifier, showcasing advanced SCXML features in real Elixir applications.