This is a general question about how to approach a problem, not a feature request. If the best approach will be to change ash_state_machine
I'd be happy to work on this on a fork.
The problem
I want to model a system that has to react to inputs, call some services and based on their output transition to next state.
I'm not sure how to do this in using ash_state_machine
.
Describe the solution you'd like
Because I'm a noob when it comes to Ash I'd be interested to hear whether my use case is handled with current library or the best approach would be to work on the DSL to customize some transition code. The biggest problem is I see several places where I can put logic that will handle state transitions based on inputs and I'm not sure which approach is the most natural.
Describe alternatives you've considered
Natural approach - packing everything into transition functions
This means that each state knows how to handle the inputs and the corresponding transition has to decide what would be the next state after getting results from external service.
In this approach I'd have transitions like
transition :handle_some_state, from: some_state, to: [:next_state, :another_next_state]
The problem with this approach is that I would have to pass arguments which seems cumbersome - I tried to write something like
update :handle_some_state do
argument :input, :string
change GetServiceResults
change TransitionSomeState
end
I'm fine with this syntax but I don't know how to actually use this transition - I tried to call State.handle_some_state
but I don't know how to provide input
.
For example when I try to call state |> State.handle_some_state!(input: "foo")
I get
** (NimbleOptions.ValidationError) unknown options [:input], valid options are: [:internal?, :timeout, :tracer, :verbose?, :action, :authorize?, :stacktraces?, :tenant, :actor, :after_action, :return_notifications?, :notification_metadata]
(nimble_options 1.0.2) lib/nimble_options.ex:343: NimbleOptions.validate!/2
(ash 2.14.15) lib/ash/api/api.ex:2035: Ash.Api.update!/3
(stdlib 3.15) erl_eval.erl:685: :erl_eval.do_apply/6
(elixir 1.14.2) lib/module/parallel_checker.ex:107: Module.ParallelChecker.verify/1
Custom module to dispatch transitions
Let's call this TransitionDispatcher
. In this approach the dispatcher know what services to call and based on their outputs it transitions the state.
This approach seems like it's a wrong way to use state machines - basically this dispatcher would have select the transition, which raises the question what is the purpose of using state machine in the first place.
Express the feature either with a change to resource syntax, or with a change to the resource interface**
I'm not really sure whether my use case can be handled with current ash_state_machine
or whether it would make sense to provide a way to set some functions to transition ...
or change
(in action definitions) that will determine what should be the next state based on service results.
Additional context
I am writing a rule-based chatbot, my transitions will call some external NLP services that among others will find the intent, and based on that select the next state.
Ash seems like a good fit for this because Elixir is a great language for writing backend, and out of the box Ash provides features that will handle minutiae of chatbot engine.
Anyway thank you for the library, I'm really excited about Ash as a person coming from Python - it seems like many issues plaguing Python's ecosystem that generate accidental complexity do not exist in Ash.