This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-01-02
Channels
- # beginners (29)
- # boot (65)
- # cider (12)
- # cljs-dev (8)
- # cljsjs (31)
- # clojars (5)
- # clojure (147)
- # clojure-austin (47)
- # clojure-berlin (1)
- # clojure-brasil (7)
- # clojure-russia (5)
- # clojure-spec (18)
- # clojure-uk (18)
- # clojurescript (113)
- # css (2)
- # cursive (7)
- # datascript (5)
- # datomic (2)
- # dirac (4)
- # events (3)
- # funcool (143)
- # hoplon (287)
- # jobs (2)
- # off-topic (4)
- # om (10)
- # om-next (5)
- # onyx (18)
- # protorepl (1)
- # re-frame (93)
- # reagent (34)
- # rum (41)
- # test-check (51)
- # untangled (15)
- # yada (18)
in re-frame, my app has a single source of truth; and the gui is a function of the db if we take this a step further, my collaborative app has one global source of truth (the aws db), and each client has a projection of this global truth (based on user permissions) then, all of 'collaboration / server requests" is about (1) sending motificatikons on changing this global db [subject to permissions] and (2) getting updates from the db [also subject to permissions] is there a toolchain for setting this up with re-frame? so it handels not only client side, but client + server + distributed ?
Nothing publicly available that I'm aware of. You'd need a reactive database (one that can tell you when it has changed). You'd need to handle *latency compensation* (when the user does action X, how long before the effect of that action is reflected in the GUI). Etc. perhaps these links will help: https://yogthos.net/posts/2016-11-05-LuminusPostgresNotifications.html https://github.com/Day8/re-frame/blob/master/docs/MentalModelOmnibus.md#full-stack
@mikethompson : I'm willing to "optimistically" do stuff on the client side, and in case of "merge conflicts", push it back to the user (like git commit conflicts)
Yeah, and its hard to do properly :-)
We've had some experience with rethinkdb
And you'll need to think it through VERY carefully
will look into comander pattern / datalog all the way down, I ctually already have a poor man's eav / datalog impl going on
@mikethompson : what if I made the following simplification: everything is either (1) only one person can write to it or (2) append-only [like slack/irc channels]; there should be no 'merge conflicts' in this case
If you want background on the "latency compensation" side of things, google for terms like "write fencing" etc.
it seems very weird that (1) on the client side, I have this beautiful data sturcutre; then to colalborate with another client, I have to shove it to the server, shove it to some db, then send it back to the server, then send it to the client, where the db is often not datomic and doesn't match well with the clikent data structure
Yeah, I promise it is almost certainly more complicated than what you realise. At least that was my experince, and I was already expecting it to be hard. Consider: you have a "subscription for a certain query" and then your user updates one of the items, but then someone else also changes another item (not the one that your user changed), and then the change that your user made gets rejected on the server (but not the change made by someone else). So your "optimistic change" has to be undone, BUT not the one successfully made by the other party.
@qqq the difference is this: on the client side you don't have shared mutatable state (the root of all evil). Whereas that's EXACTLY what a shared database is.
That's why within the client it is all "easy". Introduce shared mutable state AND distributed state and, oh boy, you just increased the complexity through the roof.
1. I don't disagree it's hard. 2. Git seems to somehow allow people to "work locally then merge globally" 3. Can we decompose the server problem into 3 parts: (1) data format (storing clojure data in the database), (2) latency, and (3) merge conflicts? Or does this split not make sense?
There's something called CRDTs also right? Where everything I can force into CRDTs won't have merge conflicts, and for the other things, I have to be very careful with.
Just to be clear: the problem is not too hard if you don't do latency compensation.
The latency compensation is what makes it hard: because you are suddenly dealing with distributed state.
Remember the old quote: the two hard things in CS are naming things and cache invalidation. The "cache invalidation" bit should really be "keeping distributed state consistent"
The moment you bite off "latency compensation" you are actually biting off "keeping distributed state consistent"
That certainly works
"the only thing worse than deterministic bugs are non-deterministic bugs" <-- CRDT debugging fun
Maybe Martin Kleppman? https://martin.kleppmann.com/2016/08/13/json-crdt.html
While I'm aware of CRDT, my knowledge is shallow
This may also be interesting wrt CRDTs: http://replikativ.io/
https://arxiv.org/abs/1410.2803 <-- supposedly the paper Phoenix Presence is based on
There's a bunch of good talks on YouTube for crdt's
I went down the same thought path as you @qqq but it's not trivial.
that says: here are the standard algorithms; here are how they work; here is their limitations
Sure, search google scholar for crdt
I think inra has a review paper
@danielcompton: having gone thorugh the pass, what's your current view on CRDTs, and do you use them?
That's a good starting point I think
I think they're incredible and need to be adopted further
But there is a bunch of low level stuff that is cutting edge research, eg garbage collection
In theory it's awesome, in practice, you'd have to do a lot of your own plumbing and deeply understand the research to get something reliable
Because if you messed it up, debugging it would probably be really hard
Another big problem is ehat you do on the server side. How do you do permissions?
How do you share state?
Does everything have to live in memory on one server, or do you cluster the state across multiple backend servers
Yeah, I feel like for CRDTs, if I can't rewrite the proofs, I'm not ready to implement it yet.
Sure, then how do you translate a relational db to something on client side?
How do you optimistically update on client side and make sure that the same logic runs on the server?
Sure, i know that :) as others have said, when the rubber meets the road it's a bit more complicated than that. But if you come up with something that works with reframe I'll be keen to see it
Is there an example of how to use cursors with reg-sub type 2?
I'm looking at the examples here https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/subs.cljs
The first example simply assess the db. That's effectively a cursor.
The two function version (input-signals-fn then computation-fn) doesn't seem to allow cursor like data access. Neither take db as an arg.
Perhaps the recommended solution is to register a :path sub.
@olivergeorge I'm seemingly the self appointed president of the anti cursor movement. Please see the "Finally" point under "Guiding Philosophy" in https://github.com/Day8/re-frame/blob/master/docs/MentalModelOmnibus.md#guiding-philosophy
Are you perhaps a refugee from OM? :-)
Kidding aside, I think what you are asking is .... should you create a create a generalised level 2 reg-sub
which is given a path
and which extracts out the part of app-db
at that path. In effect, you want a generalised READ ONLY cursor for an arbitrary path?
If so, I'd urge against it. I know it seems attractive. But it means the view (where the subscription is made) has to provide the path which means it has to "know" about the structure of app-db
.
We'd prefer the subscription to be "declarative". It should simply state what it requireds, and not where to get it.
That way, when the inevitable restructuing of app-db
happens later, you don't have to scoot around all the views finding references to paths and altering them.
Hi Mike. Thanks. Yes, I'm only interested in read only. I agree paths are unstructured.
So lots of "hardcoded path" subs make sense.
Happy new year
Yeah, so you will likely create a bunch of reg-sub
s which are very, very similar except for the path they contain. And you will have to actively resist the urge to "refactor" them. This is not a place where refactoring out the common pattern (accessing a path within app-db
) will be useful.
So this issue has come up enough times that I've added it to the docs: https://github.com/Day8/re-frame/blob/master/docs/SubscriptionsCleanup.md#a-final-faq
Now I can point people to something :-)