This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-09
Channels
- # announcements (4)
- # beginners (71)
- # boot (258)
- # braid-chat (7)
- # business (3)
- # cider (5)
- # cljs-dev (5)
- # cljsrn (64)
- # clojure (154)
- # clojure-canada (1)
- # clojure-poland (112)
- # clojure-russia (290)
- # clojurebridge (1)
- # clojurescript (60)
- # community-development (1)
- # core-async (25)
- # cursive (9)
- # data-science (1)
- # datomic (40)
- # editors (14)
- # events (2)
- # hoplon (2)
- # jobs (3)
- # ldnclj (51)
- # lein-figwheel (2)
- # luminus (1)
- # off-topic (5)
- # om (57)
- # onyx (29)
- # overtone (1)
- # parinfer (52)
- # portland-or (1)
- # proton (17)
- # quil (2)
- # re-frame (77)
- # reagent (1)
- # ring-swagger (20)
- # spacemacs (1)
- # test-check (4)
- # testing (13)
- # yada (1)
not sure if this is the right place to ask this, but I was hoping someone might have some words of wisdom regarding best practice for getting visibility into some state being computed inside a go block
Specifically, I have some process running in a go block that responds to commands (think play, pause, stop, etc.). I recur the state each iteration in my go loop, which works great inside the go block, however I'd like to expose that state to others outside the go block (as a read-only type view)
I thought of just calling reset! on an atom before I recur each time, but I don't really like the idea of each go block have a reference to some atom that could be modified elsewhere. I suppose I can simply reset! it and just treat the reset! as an update to the "view" on the status.
I should also mention I'm encapsulating all this in a component (stuartsierra/component). I can therefore do something like pass in an atom at the start of the component lifecycle. The actually go-loop is set as an entry on the component record and kicked off in the component start. In essence, I want to do something like (get-component-status my-running-component)
the actual status is in the state map I mentioned earlier and includes things like a state of running/stopped/paused, friendly names, ids, and things like that. Anyway, I'm not sure what's the preferred approach for giving other pieces of code visibility into this state outside of writing to an external system like a database or log, or just exposing an atom on the component that others can read.
You could expose something that implements clojure.lang.IDeref
@hugesandwich: you could use an atom and have a function which closes over the atom and returns it's value be the only exposed way of getting at the value
go
blocks, by design, do not expose their state to outside observers. But you can program your go
block to publish its state (such as a progress counter) in any number of ways: modify an Atom, put messages on another channel, write to a log.
I experimented with a sliding out chan with a pub for snapshots but I don't like it
Probably the best solution though since really when you do something equivalent to querying a "process" status, you're really just asking for a snapshot at that point in time anyway and it may have changed by the time you receive the data
I'm not sure if anyone has an opinion on a preferred solution. I'm aware of all the techniques mentioned so far, just looking for pros and cons or something I haven't thought of maybe
Knowing what your observer(s) are looking to do with that state might clarify things
An example use case of what I'm doing - I need to show in a UI something akin to doing "ps -a" where ps is returning a series of states about various go-loops inside a component
sorry I meant components
Needing to know about every change as it happens is different that wanting to be able to view the state at an arbitrary point in time
Each component has a single process loop with an inbox and outbox to be clear. At the moment, I just publish a snapshot of my state (running, paused, muted, etc along with some other values) to a snapshot channel that is part of the component record
If for example you want to pause the go loop processing data, you can send it a "pause" command on its control channel
So my api needs some way of asking is this component's processing loop paused
internally, it's simple because it's sitting in a map
To change the state, I simply alts! on the command channel and input channel with :priority true
it works, but maybe this is a bad design as well
so if I get a command, I update the state accordingly, recur, if I get a value on the inbox, I process it and usually leave things alone regarding the state
@donaldball: Yes, you're right, which is why I thought about atom vs. channel among many other concerns. I try to avoid changing anything in the middle of a go-loop that would cause some sort of split between what the go loop is seeing and what an observer of the component sees. But if I put that information on a channel, there's no guarantee by design when it is seen, so by then things are not a real-time view even with pub/sub. With an atom I could have a watch I suppose but I really don't like each of my components hanging on to an extra atom if possible.
This may be a digression, but clojure agents are designed to combine one-at-a-time processing with visible state.
Thanks. definitely an option. In my case, I'm using myostly the same code server/client so it's simpler to avoid agents