This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-28
Channels
- # admin-announcements (2)
- # alda (5)
- # arachne (4)
- # beginners (49)
- # boot (92)
- # capetown (3)
- # cider (9)
- # cljs-dev (6)
- # cljs-edn (1)
- # cljsjs (29)
- # cljsrn (4)
- # clojure (65)
- # clojure-android (1)
- # clojure-berlin (2)
- # clojure-chicago (2)
- # clojure-gamedev (2)
- # clojure-greece (11)
- # clojure-india (1)
- # clojure-japan (1)
- # clojure-new-zealand (2)
- # clojure-quebec (2)
- # clojure-russia (49)
- # clojure-spec (73)
- # clojure-uk (38)
- # clojurescript (118)
- # clojutre (4)
- # community-development (17)
- # cursive (3)
- # data-science (1)
- # datascript (1)
- # datomic (17)
- # emacs (6)
- # euroclojure (2)
- # events (2)
- # immutant (30)
- # keechma (11)
- # leiningen (4)
- # luminus (2)
- # off-topic (19)
- # om (14)
- # onyx (28)
- # planck (9)
- # re-frame (11)
- # reagent (35)
- # ring-swagger (4)
- # schema (4)
- # slack-help (6)
- # spacemacs (2)
- # specter (11)
- # testing (4)
- # untangled (88)
- # utah-clojurians (2)
- # vim (2)
- # yada (9)
@cjmurphy: i was wondering that too, but too embarrassed to ask
I'm wondering the same thing about old vs new style
I didn't even knew there was a new one 😅
@currentoor @cjmurphy @wilkerlucio maybe referring to using the InitialAppState protocol vs. not?
@ethangracer: yeah i think so, i was on vacation for a little while and i think i missed all the discussions
oh, you’re referring to tony’s comment. I was with him when he fixed that bug, I can confirm that’s what he meant
cool, thanks!
so i realize untangled makes extensive use db->tree
but i was wondering, if i had the ability to write some of the read functions in untangled-client then could i use datascript for my persistent models?
right now, on the server i computed timing related data based on transaction times, via data-log queries but on the client i have to treat this derived data as actual model attributes
for example dashboard/created-at
You can always use anything you want. When you want to show something it needs to be in the app database. Nothing says you can't have a mutation that uses something (e.g. a datascript db) as a source of information that you put in the UI database.
I think doing it via the parser adds a complexity that you probably don't want. Nor do you want the datascript (very very slow) running queries on demand at every frame render
why not just make the memoization a step from datascript to UI db at a designated point of interest?
Untangled, in general, is not a fan of using an alternate thing as the app db, nor having your engineers augment a parser. If you want to do that, raw Om might be better.
But the approach I outline (treating the app db as a UI graph db) lets you do everything you want (it is completely general), but is more direct (easier to trace deterministic steps from point A to B)
With a parser, you switch to another paradigm altogether (transform some arbitrary data into a tree). With a clear app db everything is just a data transform on a simple graph, and the UI query walks the graph to make the tree.
So, I recommend treating your mutations as Graph DB -> mutation -> Graph DB
, your queries as Query ---(Graph DB)---> Tree
. Thus, the only black magic is completely contained in your mutations, which are always treated as a consistent kind of function.
Remote queries pull tree data into the graph db, and your post-mutation is just like any other mutation: evolve the graph
If you happen to do some alternate network IO, populate a datascript db, and want to use that in a mutation to evolve the graph: fine
yeah that sounds like a really good approach
yeah, using datascript sounds sexier initially but i can see why this is simpler
shared queries on client and server etc
what do you mean?
oh i see
The one place where it might be really nice: mimic your schema on client/server, subscribe to tx on server, push entity updates to datascript db.
in my experience the pull syntax occasionally comes up short and we have to supplement it, for example to get dashboard/last-edit-on
i use the tx time on the server
do you find yourself doing that?
The pull syntax is a convenience, and the prime advantage is tuning chattiness of results via the UI.
I think an alternative to Datascript, though, might be adding something that can subscribe to a rooted pull fragment...such that server push could re-push some pull query when anything is touched on the db that was included in the original pull result.
(rooted, say, at an ident, which in turn corresponds to a particular datomic entity)
to get the Meteor-like subscription model we were thinking about annotating datomic transactions with client mutation literals, so for example when dashboard/edit
happens on the server, the transaction also gets a field for "[(dashboard/load-by-id {:id 3})]"
then via datomic's transaction report we read this client mutation literal and broadcast it out to clients
the clients can then transact these mutations, which will trigger the appropriate (re-)reads
not as nice as pushing the datoms but seems simpler
My initial reaction is "client code injection...erm" and "code in transaction data...erm"
i see, i thought of them as data, since they are just the names of mutations and some params, the actual logic lives in the client's mutation functions
Why not have clients "subscribe" to their server by IDs of interest. Then when the tx log includes those ids you could trigger the update.
any number of servers supported, and you don't have to pass extra data through the transactor/db, which are more limited resources.
The subscription could include the "here's what you should tell me when ID n changes"
which is fine because websockets will already require you being attached to a specific server.
IDs in this case being datomic entity ids?
which is also what I was referring to in my "subscribe to a pull". When a pull runs, you can derive all IDs of entities involved
gives you a fully general and reusable subscription system tied to UI queries rooted with an ident
ok just to make sure i understand the first part, on the server i would have a set of IDs associated with each open websocket and then for any tx reports i push the updated IDs out to all the clients that are associated with those IDs
awesome!
1. On subscribe (which is client-centric): The subscription is for a query of the form :`[{ [:db/id 4] [:subquery :props] }]` of arbitrary depth. Any joins should include :db/id
in the requested attributes.
2. On the server, run the pull and recursively walk the result, and record the ids into a set
3. Places that set into a subscription record for that client
4. Return the result to the client.
A thread watching the datomic tx log, on each tx:
1. Get the set of IDs that have changed
2. Find all clients whose subscription sets have a non-zero intersection
3. Re-run those pulls (as if starting at step 2 in the first list of steps)
4. Push the result and query to the client (which can use om/merge! with that data and query to make app state change properly)
We didn't need this yet, so we never finished the implementation. More pressing things needed. The proof of concept seemed solid, though.
If it really is a leaf entity, then you're saying "keep this entity up-to-date". If there is a graph, then the pull query says "keep this graph of objects up-to-date". Additional fun realizations: Your pull query need not actually be on the UI...you could subscribe however you want. One caveat: refresh of UI on server push might require explicit re-rendering stuff. Not sure under what conditions you'd need to help.
The ident would definitely refresh components with that ident. You might have to do a no-op transact!
with follow-on reads to get related/derived stuff.
Optimizing the "find clients to refresh" could also get CPU heavy, though you could heavily index things to make that fast.
wow that was very thorough, thanks for sharing!
i'll talk to my team and see if we can do some of this
So in the above scenario is [:db/id 4] an ident? (Normally ours would look something like [:widget/by-id 4], but then the server isn't really going to know what that means)
@therabidbanana: It is trivial to use whatever you want for the keyword on the client side, and know that it really means :db/id on the server
So, subscription could just ignore the specifics of the keyword, and know that the number has db/id meaning
Yeah, that's what I was imagining we'd do, just pretend it means :db/id on the server
Cool, I think the rest makes sense, we're going to try and get a simple proof of concept going
Though unfortunately it turns out sente relies on CLJX, which we don't have in our boot builds yet, so first some yak shaving. 🙂