Skip to content
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

Allow cancelling of :delay #19

Open
brjann opened this issue Mar 5, 2024 · 2 comments
Open

Allow cancelling of :delay #19

brjann opened this issue Mar 5, 2024 · 2 comments

Comments

@brjann
Copy link

brjann commented Mar 5, 2024

The :after keyword can be used to specify a delayed transition, and allows a function that returns a dynamic delay. Would it make sense to cancel the delay if the :delay function returns nil?

LIke this (example from the docs)

(defn calculate-backoff
  "Exponential backoff, with a upper limit of 15 seconds. Stops retrying after 15 attemtps"
  [state & _]
 (when (> 15 (:retries state))
    (-> (js/Math.pow 2 (:retries state))
        (* 1000)
        (min 15000))))

(defn update-retries [state & _]
  (update state :retries inc))

;; Part of the machine definition
{:states
 {:connecting   {:entry try-connect
                 :on    {:success-connect :connected}}
  :disconnected {:entry (assign update-retries)
                 :after [{:delay calculate-backoff :target :connecting}]}
  :connected    {:on {:connection-closed :disconnected}}}}```
@lucywang000
Copy link
Owner

technically we can do that, but from a higher level i think it's better to modify the statecharts instead to distinguish "disconnected but retrying" and "disconnected and retry exhausted" states, e.g. by modifying disconnected as a compound state:

:disconnected  
{:initial :retrying
 :states {:retrying {:entry (assign update-retries)
                     :after [{:delay calculate-backoff :target :connecting}]}
          :retry-exhausted {}

and when transition to disconnected state, the machine should jump to retry-exhausted state by checking the :retries key using some guard

@brjann
Copy link
Author

brjann commented Apr 8, 2024

Thank you @lucywang000 for replying and sorry for the delay in responding.

My example was a bit contrived, I just wanted to base it on the existing example in the docs.

My real use case is a general FSM definition that runs several FSM instances. Some of them regularly reload their data whereas others don't. Each FSM instance's :context has a key that tells whether it's a reloading FSM or not. So the FSM definition has a :delay function that checks this key. If no reload should happen, my idea was that it should return nil. Now I instead return 0 and a :guard follows that cancels the transition if no reload should happen. Which is fine, but the possibility to cancel the :delay already in the function would be nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants