fulcro

Casey 2025-02-24T14:10:19.359439Z

What's the "right" way to get a statechart's current configuration from outside the statechart given the env returned from com.fulcrologic.statecharts.simple/simple-env ? I've come up with (get-in @(get-in env [::sc/working-memory-store :storage]) [session-id ::sc/configuration]) but that seems rather clunky. (there's no fulcro involved here btw)

tony.kay 2025-02-24T17:51:27.362569Z

look in the environment ns I think

tony.kay 2025-02-24T17:53:33.486769Z

ah, but you’re right you’lll need to pull the active working memory

tony.kay 2025-02-24T17:53:47.391689Z

(if you’re not in the context of a statechart expression)

tony.kay 2025-02-24T17:53:58.137459Z

you can use the protocols for that part (insead of the direct get-in)

Casey 2025-02-24T17:54:14.949779Z

I tried that, specifically the current-configuration function, but yea, what you said.

Casey 2025-02-24T17:55:00.921479Z

Ah ok, I'll take a look there.

tony.kay 2025-02-24T17:56:16.811809Z

So, I am not remembering specifically, and it could be a hole in the API

tony.kay 2025-02-24T17:57:35.298419Z

Also look here, which isn’t meant to be “public” https://github.com/fulcrologic/statecharts/blob/main/src/main/com/fulcrologic/statecharts/algorithms/v20150901_impl.cljc#L746

tony.kay 2025-02-24T17:59:26.576589Z

I’ll look in a bit. have a meeting right now

tony.kay 2025-02-25T02:39:41.972259Z

So, I should have documented this in https://fulcrologic.github.io/statecharts/#_working_memory_and_identity

tony.kay 2025-02-25T02:40:31.180239Z

What you’re looking for is

(let [{::sc/keys [configuration]}  (sp/get-working-memory working-memory-store env session-id)]

tony.kay 2025-02-25T02:40:58.978349Z

where the working memory store itself is usually stored in the env as well. (pull it out to use as an arg).

tony.kay 2025-02-25T02:42:34.694349Z

The environment ns is meant to be using with live envs in expressions in the chart, whereas outside of the chart you’re basically just working with the overall “setup” (env is unfortunately used to refer to both the configuration environment AND the runtime session processing environment). I should clarify this in the docs if I haven’t

tony.kay 2025-02-25T02:49:44.976879Z

Just to give some more clarity about another complication: Here’s the Malli schema of the configuration env:

(>def ::sc/env [:map {:closed false}
                ::sc/data-model
                ::sc/event-queue
                ::sc/statechart-registry                    ; how to look up machine definitions
                ::sc/execution-model
                ;; These are only needed if you are supporting self-running systems with a self-running event queue
                ;; or invocations.
                [::sc/working-memory-store {:optional true}] ; session-id -> persistence of wmem
                [::sc/processor {:optional true}]           ; The statechart algorithms
                [::sc/invocation-processors {:optional true}]]) ; Invocation support
note that the working memory store is OPTIONAL. The processing implementation is a pure function old-statechart-state -> F(event) -> new-statechart-state. Running it in the “simple env” sets it up so you have an event queue and working memory store to make your life easier, but someone else might just want implement things around the storage/progress of states differently. So, providing functions that assume there is going to be a working memory store and event queue for “running the world” is not the only way to do it. That said, I really should figure out where to put some support functions that assume you’re going to to the common/easy thing I use it the way I’ve made for you.

tony.kay 2025-02-25T02:50:21.652989Z

like a ns called standard-processing-model or something perhaps not so wordy?

tony.kay 2025-02-25T02:55:16.346779Z

At my primary business I have server-side long-running statecharts for things like subscription management. In those I use a working memory store that serializes the working memory of a chart to an SQL table using nippy, and my event queue is also implemented as an SQL table, where there are many threads on many nodes that look for events that are “ready to fire”, and those event processing threads coordinate to prevent processing the same event twice. Getting the current configuration still works as I described above, though, since my SQL event queue and SQL memory store both implement the protocols.

👀 1
tony.kay 2025-02-25T03:37:13.245689Z

ok, so I added a runtime ns. Released in 1.2.14. Includes helpers for making a processing env, getting the current config, and getting session data.

michaelwhitford 2025-02-25T03:56:42.610969Z

Thank you for this, made the shutdown hook I am using much simpler to pull a websocket out of the statechart-local data to close it properly.

tony.kay 2025-02-25T04:02:59.132489Z

Just released 1.2.15…added a send! helper as well. Happy to add more. Really my intention was for people just to use the protocols for the most part, but these are nicer.

michaelwhitford 2025-02-25T04:03:38.546499Z

I'm curious why in the session-data function you did not use when-let? You have a let then a when. Just wondering if there is a reason to seperate them.

tony.kay 2025-02-25T04:06:55.937839Z

because there is a destructuring

tony.kay 2025-02-25T04:07:08.412539Z

Am I right on that?

tony.kay 2025-02-25T04:07:11.962899Z

I’m sleepy

tony.kay 2025-02-25T04:08:09.606139Z

(when-let [{:keys [x]} {:y 3}]
  (println "Foo"))
prints foo

tony.kay 2025-02-25T04:08:29.088219Z

I’m not checking if there is a MAP on the right, but if there’s a key in the map

tony.kay 2025-02-25T04:09:05.517959Z

(macroexpand-1 '(when-let [{:keys [x]} {:y 3}]
                  (println "Foo")))
=> (clojure.core/let [temp__5804__auto__ {:y 3}] 
     (clojure.core/when temp__5804__auto__ 
       (clojure.core/let [{:keys [x]} temp__5804__auto__] (println "Foo"))))

tony.kay 2025-02-25T04:09:22.833459Z

gotta be careful with those destructurings 😄

michaelwhitford 2025-02-25T04:10:06.216959Z

There is no destructure there

(let [penv (processing-env env session-id)]
     (when penv
       (sp/get-at data-model penv data-path)))

tony.kay 2025-02-25T04:10:13.038739Z

oh that one 😄

tony.kay 2025-02-25T04:10:23.538639Z

I think I originally had a destructuring and refactored it 😛

michaelwhitford 2025-02-25T04:10:47.258379Z

Anyways I was just curious, it's working great and thank you for the new namespace I am already refactoring some sends to make them simpler than my current usage.

tony.kay 2025-02-25T04:10:48.453659Z

(I wrote that one first, and the refactored it when I wrote processing-env as a helper)

tony.kay 2025-02-25T04:11:03.888759Z

like I said…sleepy

tony.kay 2025-02-25T04:11:12.942089Z

been up since 3am

tony.kay 2025-02-25T04:11:27.922809Z

and it’s 8pm. so past my bedtime

tony.kay 2025-02-25T04:12:30.728519Z

refactored and pushed 🙂 Thanks for the code review!