This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-12
Channels
- # aleph (1)
- # aws (2)
- # babashka (44)
- # beginners (178)
- # biff (12)
- # calva (22)
- # chlorine-clover (60)
- # cider (1)
- # clj-kondo (9)
- # cljdoc (6)
- # cljs-dev (37)
- # cljss (2)
- # clojure (43)
- # clojure-europe (3)
- # clojure-finland (23)
- # clojure-italy (1)
- # clojure-nl (4)
- # clojure-norway (3)
- # clojure-spec (56)
- # clojure-uk (148)
- # clojuredesign-podcast (1)
- # clojurescript (11)
- # conjure (5)
- # core-async (22)
- # cursive (9)
- # datascript (5)
- # datomic (4)
- # duct (8)
- # emotion-cljs (2)
- # figwheel-main (15)
- # fulcro (53)
- # graalvm (68)
- # helix (2)
- # jackdaw (1)
- # kaocha (9)
- # lambdaisland (1)
- # malli (10)
- # meander (2)
- # news-and-articles (1)
- # observability (12)
- # off-topic (17)
- # pathom (1)
- # pedestal (25)
- # practicalli (1)
- # protojure (4)
- # re-frame (2)
- # reagent (57)
- # reitit (1)
- # releases (2)
- # shadow-cljs (69)
- # specter (6)
- # tools-deps (10)
- # vim (16)
- # vscode (4)
- # yada (3)
The book says
> When you pass tempids as a parameter to a mutation, that value will be captured and not rewritten. Thus your ok-action
and result-action
env
will contain a :tempid→realid
map that can be used to translate those values.
But how else am I supposed to pass the data to the mutation?
there is a map, in env
that goes from the tempid you passed, to the real id that was returned from the server
The book describes that Fulcro will rewrite the tempids of the data sent to the mutation, unless the data is handed to the mutation using an argument
ok, so first, the book could be out of date: tempid rewriting happens against state and transaction queues. So, the only tempids that cannot be rewritten are those that are captured in runtime closures
but the book is telling you that it is handing you the remapping “map”…so you can fix these runtime closures yourself, if need be
Well I wanted to chain two mutations in a transaction (to see what would happen) and I expected it to re-write the tempid before running the second mutation, but it didn't. So I wondered what I'd have to do in such a case to have it happen automatically, or if I am misunderstanding something here.
(defmutation f [params]
(ok-action [{:keys [tempid->realid]}]
(let [fixed-params (reduce-kv (fn [p k v] (assoc p k (if (tempid? v) (tempid->realid v v) v)) {} params)]
(comp/transact ... [(new-mutation fixed-params)])))
Mutations are multimethods. They get dispatched exactly once. The sections of the mutations become lambdas in a map in the runtime that are generated during that initial dispatch.
I don’t remember, off the top of my head, why I don’t rewrite the tempids in params, but if that is the way it is working and written in the book, then there was probably some limitation on functional closure that was too hard to work around. Do you understand the solution?
there’s a helper function somewhere that can use that map on an arbitrary data structure so you don’t have to write the reduce yourself
Yes, I do understand this solution, this one was clear. I was wondering about the Warning, because I don't get in which case the automatic replacement actually does happen. Just made me curious, that's all
the auto-replacement happens against the entire app database, and everything in all transaction queues (including pending things in network queues)
so, if there was a mutation you’d queued with a tempid that was waiting in line behind a mutation that rewrote IDs, it would actually resolve it in the network params of that one
So I tried it with a
(comp/transact! this [(mutation-a (fs/dirty-fields props false {:new-entity? true}))
(mutation-b (fs/dirty-fields props false {:new-entity? true}))])
And I expected the tempids to be replaced by the time the data arrives on the server for mutation-b
but they were notso perhaps this is the source of the confusion: I cannot rewrite data in functional closures. The things in the queues are not closures…they’re literal data. So all that can be rewritten
I assumed first a would be sent to the server, then when the result got back it would rewrite the tempids and then send b to the server
two mutations to the same server in the same txn are an attempt, by you, to execute an atomic grouping…you have to enforce that yourself on the server, but Fulcro is allowing you to express that desire
The default txn processing will guarantee that a single submission will only be split if more than one server is involved, but that groupings to those servers will be maximal (i.e. everything that should go to a given server will go as a unit)
It is meant for exactly that…you’re just assuming Fulcro can do some magic in the middle of your atomic processing on the server, which it cannot
you’ll have to carry along your rewrites in your parsing env on the server if you want that ability
but it is completely pessimistic…not even the optimistic of b would run until a is done
Currently the tx processing will not combine unrelated transations…so running two invocations of transact!
should get the behavior you expected.
"Currently the tx processing will not combine unrelated transations" is that an implementation detail, or something that is by design? (Would make sense if it is by design)
The tx processing is pluggable. The default implementation attempts to do things in a way that will “make sense” given the distributed systems environemtn of an SPA.
for example, reads and writes that are submitted while you hold the js thread (i.e. you call load load load transact transact) will be reordered so that the writes go first. Loads and transacts might come from arbitrary code composition, and one way to cleanly reason about such composition is for these combinations to assume you don’t want “stale reads”…that is to say, if a single code path (possibly composed of black box calls) asked to both change and read things, then you probably don’t want to do the reads before those submitted changes have taken effect.
txn vector as a “hint” for an atomic unit is another useful guarantee as is sequential network operation (which you can opt out of via parallel option)