There's a circular dependency between a machine and a scheduler.
transition is passed a machine, so in case the transition leads to delayed events, the machine has to carry the scheduler. But the scheduler needs to refer to the machine in its dispatch function. And in turn, that machine has to have a scheduler, so that the delayed events can schedule further delayed events.
Because of this dependency, it's tricky to construct machines that need schedulers. The work around is to create some sort of mutable reference to a machine. See for example, here, here, and here. This works, but isn't idiomatic Clojure.
One fix would be for the machine to pass itself to the delayed/schedule function (and on to the dispatch function):
;; delay.cljc
(defprotocol IScheduler
(schedule [this machine state event delay])
;; ^-- new
(unschedule [this machine state event]))
;; ^-- new
;; impl.cljc (edited for brevity)
(defn- execute-internal-action
[{:as fsm :keys [scheduler]} state transition-event internal-action]
,,,
(cond
(= action :fsm/schedule-event)
(fsm.d/schedule scheduler fsm state event event-delay)
;; ^-- new
(= action :fsm/unschedule-event)
(fsm.d/unschedule scheduler fsm state event)))
;; ^-- new
With this relationship, you could assoc a scheduler onto a machine, and not have to go through any further steps to ensure that the scheduler had access to the machine.
There's a circular dependency between a machine and a scheduler.
transition
is passed a machine, so in case the transition leads to delayed events, the machine has to carry the scheduler. But the scheduler needs to refer to the machine in its dispatch function. And in turn, that machine has to have a scheduler, so that the delayed events can schedule further delayed events.Because of this dependency, it's tricky to construct machines that need schedulers. The work around is to create some sort of mutable reference to a machine. See for example, here, here, and here. This works, but isn't idiomatic Clojure.
One fix would be for the machine to pass itself to the
delayed/schedule
function (and on to the dispatch function):With this relationship, you could assoc a scheduler onto a machine, and not have to go through any further steps to ensure that the scheduler had access to the machine.