Fork me on GitHub

I’ve seen that load! has an option post-action that is not the in documentation of the book. What’s the use case for that? Adding form state to the loaded entity? Or should I stick to post-mutation for that?


post-action is a simplified way, you can use that instead of post-mutation


if you already have a mutation that does what you need, stick to post-mutation, otherwise you can use post-action

Jakub Holý (HolyJak)14:04:48

Also, many details are not in the book - remember to always check the docstring. This one is documented in load!'s


but I imagine that post-action does not get recorded in the tx logs, so if you replay just mutations, you don’t get the same state


yes, post-action is a shortcut to writing a mutation…it is a way to provide a handler that runs as-if it were an ok action in a mutation, without having to actually write a mutation.


The architecture doesn’t have many parts to it in 3. Result-action gets called on every network result. For loads, the internal-mutation in the data-fetch ns is the actual definition of what is running to accomplish a load, so you can easily just look at that. Mutations in general have an optimistic section (action), remote(s), and a result-action. The default-result-action can be set, but the default for that is also defined in the mutations ns. Things like ok-action and such are just implementation details of result-action, as are load targeting, etc.

Jakub Holý (HolyJak)07:04:14

If you replay the mutation, you run the mutation again including all parts of it - action, remote, post-action....


depends on how you’re replaying it…could be an “event stream” you’ve recorded (say at the server) (CQRS-style processing),

Jakub Holý (HolyJak)15:04:07

How does error handling work in RAD? If I get a DB error, I want to show an error message but currently I am just getting nildata back. From the log I see that com.fulcrologic.rad.pathom/process-error has been called so I expected to see

{::errors {:message msg
               :data    data}}
somewhere in the response but instead I just get {:my-ns/my-top-key nil} How to get the error info? Thank you!

🙏 4

I haven’t gotten to refining that yet. It is the standard Fulcro stuff described in the book. You define what responses are errors, etc. The state machines for the things in RAD currently don’t deal with a lot of unhappy path stuff.

Jakub Holý (HolyJak)07:04:44

The thing is that the error does not reach the client (as seen from the Network tab), it disappears somewhere during Pathom's processing. I can try to find out where...

Chris O’Donnell11:04:56

@U0522TWDA This has worked well for me for handling mutation errors. Hasn't been thoroughly tested; might need a bit of tweaking to work with load errors as well. (Also, this is vanilla fulcro 3, not RAD.) Planning on getting clear on the details and writing a blog post on error handling soon.


So, you can use status code like that, since the default error definition in Fulcro considers that a problem, but consider this: You may have errors that are peppered around that you’d like targeted to specific mutations (or components that read): Co-locating the errors on the response is actually desirable. Say you has a security error on some sub-graph of the query…you could just elide that and keep the parser error at that point in the tree, and then components could actually query for the error keys. Same with mutations: an error can be just a return value that ok-action processes, but what I commonly do is redefine the remote-error definition at the applciation level and return true if the result of the mutation contains a special nsed key. This allows you to return normally from a mutation (so other parsing continues) and direct the error to a specific mutation in the sequence. The default of 500 status code just catches the things you “missed” that bled out as exceptions.

Chris O’Donnell16:04:19

@U0CKQ19AQ Thanks for the suggestions! I hadn't considered querying for errors in components; it's a nice idea. I'm not sure I understand your suggestion about mutations. It sounds like you're suggesting individually marking mutations as failed, which sounds great. However, I'm only familiar with the :remote-error? predicate, which to my knowledge marks errors at the response granularity. Could you elaborate on how that would work?


@U0DUNNKT2 When results are processed at the mutations/default-result-action Fulcro’s tx processing has split any tx into component parts, and uses remote-error? on each one. Thus, a tx like [(f) (g) (h)] can call error action on each one individually. (mutations.cljc line 116)


thus remote-error? will be handed a result that can be narrowed to that mutation

Chris O’Donnell22:04:00

That makes sense. Thanks for clarifying.

Jakub Holý (HolyJak)07:04:42

Answer to my question: The error is present in the response but not shown in Inspect > Query because it is an additional, top-level key which the query has not asked for. Sadly, the Network tab does not show it either (I had to go to the native network tab and transit-decode the response to the /api call). So there is

{:data/i-asked-for nil, :com.wsscode.pathom.core/errors {[::data/i-asked-for] #:com.fulcrologic.rad.pathom{:errors {:message "No DataSource in env!", :data {:db-pools nil}}}}}


Yeah, I need to add a global-eql-transform in the demo…easy to forget until you try the unhappy paths 🙂

Jakub Holý (HolyJak)15:04:24

You can rely on my to find quite a few :)

Jakub Holý (HolyJak)15:04:36

Q2: Is it still true that RAD reports/forms must be under a top-level router or can they be under a nested router?


the latest versions are more tolerant of nesting. I expanded the routing of Fulcro so you could find current paths, etc. Not heavily tested though.

👍 4
Jakub Holý (HolyJak)17:04:11

BTW I've switched to the new RAD routing, it is neat! I noticed that my integer params are weirdly encoded so I guess I will try to have them all as strings.


@U0522TWDA I’m using transit encoding for params so that types are auto-preserved. I know that makes them less “manually usable”, but that is not one of my goals. I want the URL to just work, and encoding things like date to strings, then having to install coercion functions, then having to make all that crap pluggable…exhausting.


end users don’t edit URLs…they copy and paste them

👍 8
Jakub Holý (HolyJak)07:04:37

thank you for the explanation! That makes perfect sense.


For server-side-rendering, what would be the advantage of running the app headlessly vs. using build-initial-state (assuming missing hooks/tests got written)?


I'm just coming up to speed on this, so I could be wrong. But my understanding is that running headlessly produces completely rendered html that, in theory, wouldn't require javascript. So the content would be readily available to clients that don't support javascript, like curl, and could be immediately piped to other programs. SEO would be improved too. build-initial-state embeds the response to the query the client would make as base64 encoded javascript. So javascript and additional rendering is required on the client.


Ah, yes that is the use-case I'm after actually. Thanks!

👍 4

The documentation says headless mode is "incomplete." I'd be interested to hear your experience with it


Right, I'm assuming I'll have to implement at least some of the missing hooks it mentions

Jakub Holý (HolyJak)07:04:42

Answer to my question: The error is present in the response but not shown in Inspect > Query because it is an additional, top-level key which the query has not asked for. Sadly, the Network tab does not show it either (I had to go to the native network tab and transit-decode the response to the /api call). So there is

{:data/i-asked-for nil, :com.wsscode.pathom.core/errors {[::data/i-asked-for] #:com.fulcrologic.rad.pathom{:errors {:message "No DataSource in env!", :data {:db-pools nil}}}}}