TwistingTwists

TwistingTwists

Using AshStateMachine and AshOban

Here is my ash_state_machine :


  # start -> send_next_question -> send_results -> stop

  state_machine do
    initial_states([:start])
    default_initial_state(:start)

    transitions do
      transition(:begin_quiz, from: :start, to: :send_next_question)
      transition(:continue_quiz, from: :send_next_question, to: :send_next_question)
      transition(:process_results, from: :send_next_question, to: :send_results)
      transition(:error, from: [:start, :send_next_question, :send_results], to: :stop)
    end
  end


  attributes do
    uuid_primary_key :id

    # default id should be there.
    attribute :quiz_id, :uuid, allow_nil?: false
    attribute :user_id, :uuid, allow_nil?: false

    attribute :quiz, :map,  allow_nil?: true
    attribute :user, :map, allow_nil?: true

    # reponse for the question
    attribute :current_response, :string, allow_nil?: true
    attribute :previous_question, :uuid, allow_nil?: true
    attribute :next_question, :uuid, allow_nil?: true

    # show errors
    attribute :error, :string
    attribute :error_state, :string
    # :state attribute is added for you by `state_machine`
    
  end

Here is how I think it should work:

  1. since there is a state send_next_question which will transition to itself (with delay of 1s) until all the quiz.questions becomes empty list.

  2. when quiz.questions becomes empty, send_next_question goes to send_results.

  3. ash_oban triggers a job each time send_next_question state is achieved.

  4. ash_oban triggers a job when send_results state is achieved.

a high level idea of implementing it wouldbe helpful. :slight_smile:

Most Liked

TwistingTwists

TwistingTwists

I agree on the GenServer part since wait time is less than a minute.
Nonetheless, this gives a good idea on how ash_oban and ash_state_machine work together.

Will manage the genserver for now :slight_smile:

zachdaniel

zachdaniel

Creator of Ash

I think AshOban will not be the best case for this. I think you will want a GenServer handling the state of the resource, and transitioning from state to state. When a quiz is started (or perhaps resumed on reconnection) you can load up the relevant state machine and begin interacting with it. Generally speaking, less than one minute feedback loops aren’t the best fit for Oban/AshOban in my experience.

AshOban triggers can be triggered in one(or both) of two ways:

trigger :send_next_question do
  scheduler_cron "* * * * * *" # trigger for any matches every one minute
  where expr(state == :send_next_question)
end

...

# schedule the next invocation automatically
update :send_next_question do
  change run_oban_trigger(:send_next_question)
  # or in a custom change `AshOban.run_trugger`
end

For that latter case, we don’t have a run_trigger_later, but we could add one or you could hand roll one pretty easily. When you combine both of these, typically the scheduler_cron and where act as a backup in case something goes wrong triggering the actions. You can also only use the second strategy, and pass scheduler_cron nil to not automatically check for matches and trigger the action.

However, this is going to amount to a lot of database back and forth during what looks to be intended to be a pretty tight loop. Your user would likely have a better experience if the quiz flow was designed as a GenServer I think. I can see a case for having tooling for this kind of thing built into ash_state_machine, i.e some state machines should be statable, keep track of some in memory state, and have an accompanying module that handles state transitions in memory or something. Maybe :slight_smile:

Where Next?

Popular in Questions Top

New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement