piotrmurach / finite_machine

A minimal finite state machine with a straightforward syntax.
https://piotrmurach.github.io/finite_machine/
MIT License
807 stars 38 forks source link

Event deferral #14

Closed piotrmurach closed 6 years ago

piotrmurach commented 10 years ago

@kjwierenga I'm planning to add event deferring reference

My suggestion for syntax would be to do

wait_until_transition :state_name { |event| .... }

This would save the callback in internal queue and wait until the particular condition is met. In similar manner I would have wait_unitl_enter, wait_until_exit etc... Does it sound reasonable?

kjwierenga commented 10 years ago

It's not so much about the callbacks. In my opinion the actual event should be deferred and so there should be an event queue (not a callback queue).

Each time a new event is received the first thing to do is to process events from the event queue in the order in which they were received (and put on the queue; to retain proper event ordering).

The challenge is to come up with a nice syntax to specify event deferral in specific states (because so far state is implicitly defined (in the transitions).

Inspired by http://redboltz.wikidot.com/deferred-events, maybe something like this?

events {
  event :event2, :state1 => :state2
  event :event2, :state2 => :state3
  event :event1, :state3 => :state4
  event :event1, :state4 => :state5
  event :event1, :state5 => :state6

  event :event1, :state1 => :state1, :defer => true
  event :event1, :state2 => :state2, :defer => true
  event :event1, :state1 => :state1, :defer => true
}

callbacks {
  on_before     { |event| puts "received #{event.name}" }
  on_transition { |event| puts "#{event.name} #{event.from} -> #{event.to}" }
}

#...

fsm.event1
fsm.event1
fsm.event2
fsm.event2
# should transition through states state1, state2, state3, state4 and state5

This raise questions about which callbacks should fire. I think the event trace should be:

received event1
received event1
received event2
event2 state1 -> state2
received event2
event2 state2 -> state3
received event1
event1 state3 -> state4
received event1
event1 state4 -> state5
piotrmurach commented 6 years ago

Due to complexity and need for storing events in queues before processing, I will skip this feature. In the past storing events asynchronously caused a lot of issues including memory leaks for the majority of users of this library.