Is there any documentation about ::txn/submission-queue
, ::txn/active-queue
, and ::txn/send-queues
? The source code in the txn namespace is a bit hard to follow
There’s a general diagram here: https://github.com/fulcrologic/fulcro/blob/develop/src/main/com/fulcrologic/fulcro/algorithms/tx-processing-readme.adoc
If you check out the source and use deps to make that what you’re using for your code, then you can decorate the tx processing code with calls to https://github.com/fulcrologic/fulcro/blob/develop/src/main/com/fulcrologic/fulcro/algorithms/tx_processing_debug.cljc tx-status, which will dump whats in the various queues.
(`tap>` is your better friend here, these days)
This section of the book mentions what all is going on in there: https://book.fulcrologic.com/#_the_transaction_processing_system
1🙏A while ago I was playing around with having the tx layer combine transactions into one network call. I left some cursory notes from my code dive here: https://github.com/dvingo/fulcro/blob/f0df8f8cf144e5c544af5a038cf6f5fca8b406b2/src/main/com/fulcrologic/fulcro/algorithms/tx-processing-readme.adoc#dans-notes or view the text bc I wasn't careful with formatting (the section "Dan's notes") : https://raw.githubusercontent.com/dvingo/fulcro/f0df8f8cf144e5c544af5a038cf6f5fca8b406b2/src/main/com/fulcrologic/fulcro/algorithms/tx-processing-readme.adoc (warning, very rough - typos etc, was meant for me to organize my thoughts 🙂 )
1🤘Ok, I found the answer. I'm writing it down for my own future reference.
First, be clear that a transaction could have multiple elements (i.e., first-level children of the ast, each correspond to a defmutation), and an element can have multiple remotes, and finally, two different elements can (and likely) have the same remote.
When processing the ::send-queue
, Fulcro combines sends from multiple elements when they have the same remote. This means that we need to demultiplex the combined remote response.
Fulcro does the demultiplexing in the txn/combine-sends
function, where it says
(doseq [{::keys [ast result-handler]} to-send]
(let [new-body (if (map? body)
(select-keys body (top-keys ast))
body)
result (assoc combined-result :body new-body)]
...
(result-handler result)))
There you see that if the body is not a map, each element's (i.e. defmutation's) result-action
will receive a whole copy of the body. However, if the body is a map, each element's result-action
will receive only a subset of the whole body, containing only the keys that it queried for (the first-level children's keys).1❤️And global-error-action
is invoked at the default result-action
(i.e., m/default-result-action!
) where it says:
(-> env
(update-errors-on-ui-component! ::mutation-error)
(rewrite-tempids!)
(integrate-mutation-return-value!)
(trigger-global-error-action!)
(dispatch-ok-error-actions!))
And this result-action
is the result-handler
referred in the txn/combine-sends
.@tony.kay I feel even though this way of multiplexing makes sense (it gives a valid pathom query that can be directly fed into a Pathom parser), it doesn't fit Fulcro exactly. For example, you mentioned yourself that "nodes with the same ID" cannot be handled at the moment. Maybe the multiplexing/demultiplexing can be handled using a Fulcro-specific protocol?
The issue, at its core, is this:
[(f) (g) (h)]
, where those three mutations all have different remotes. Each of them has a result section which is going to be triggered from a separate network response. If those mutations all went to the same remote, then you can do some combining. The general problem is much harder than the common one.
So it isn’t multiplexing…each mutation has a singular existence, and can even talk to multiple remotes. Each network request needs a separate tracking node.
The combining logic that is currently present can only recombine nodes from a single transaction that all share the same desired remote.
In terms of the code you’re referncing, it is distributing result to mutations. The map in question will be keyed by dispatch symbol {'f result-map 'g result-map …}
, and the top-keys of the AST of [(f)]
will be 'f
so, it is possible there is some kind of bug in the transaction logic, but I kind of doubt it…you may have changed the shape of the result from the server in an incorrect way due to it being an error
Returning an error from the server that should be targeted at a mutation requires that you return a map keyed by the mutation name, which is the exact shape normal mutations return.
i.e. The result of the mutation is nothing if it failed…you should not expect its result to be anything at all, which is why you get the entire env, which I think has other keys on it around the result so you can see the raw result.