Fork me on GitHub
#fulcro
<
2018-10-16
>
tony.kay00:10:06

optimistic update failure…can use fallbacks, or mutations “returning” (e.g. have the server return the final value, like some other gql system), ptransact to check result and react…some other possibilities too ::)

hmaurer00:10:39

> The default fulcro networking does not do retries because it isn’t safe without the idempotent guarantee.

hmaurer00:10:11

@tony.kay if, as you mentioned the other day, making mutations idempotent is potentially as simple as UUID-tagging them and checking those on the server, couldn’t this be implemented in the core?

tony.kay00:10:53

could be, but how would core know you’ve made them all idempotent?

hmaurer00:10:07

> . “Can I log in with these credentials?“. Yes or no. This is a query and response, not an error handling interaction. Thus, something like login can be handled with a query (to get the answer) and post-mutation (to update the screen with a message or change the UI route). Do you have an example of this sort of “query, and based on response do a mutation”?

tony.kay00:10:09

feels like a “your problem” layer to me

hmaurer00:10:18

@tony.kay hmm, fair enough

tony.kay00:10:38

or at least a layer that you add in…not saying it couldn’t be in a library

hmaurer00:10:50

My use case wouldn’t be login but signup; check if email is already in use; if not, proceed to sign up

tony.kay00:10:11

didn’t I give you that code earlier today?

hmaurer00:10:29

(defmutation login
     "Mutation: Try logging in with the given `email` and `password`."
     [{:keys [email password]}]
     (action [{:keys [state]}]
       (swap! state set-status* :authenticating))
     (remote [{:keys [ast state]}]
       (-> ast
         (m/returning @state session/ServerSession)
         (m/with-target [::session/session])))
     (refresh [_]
       [::session/session]))
this ?

tony.kay00:10:35

The defresolver is the server code

tony.kay00:10:41

for the query

hmaurer00:10:00

oh, I missed the edit 🙂

hmaurer00:10:18

I had copied it in a gist before the edit

tony.kay00:10:23

The client does something like

(df/load reconciler ::session Session {:post-mutation `check-session})

tony.kay00:10:05

where check-session is a post mutation that looks in ::session in state to see if it is a valid user

hmaurer00:10:14

I am looking at the AST of a query:

dev:cljs.user=> (fulcro.client.primitives/query->ast [:foo])
{:type :root, :children [{:type :prop, :dispatch-key :foo, :key :foo}]}
In which cases can the :key and :dispatch-key differ?

tony.kay00:10:41

If I remember right, on idents

tony.kay00:10:52

vague and distant memories

tony.kay00:10:24

I’ve got stuff stacked on that so that I never have to think about it 🙂

hmaurer00:10:52

😄 perhaps I should phrase my question differently then: what are their respective roles?

hmaurer00:10:56

(:key and :dispatch-key)

tony.kay01:10:55

:key can be an ident, but dispatch key will only be the first element of the ident (for multimethod dispatch)

tony.kay01:10:08

on symbols and props, they are identical

tony.kay01:10:30

so a query like [{:x [:y]}] will give :x and :y as both

tony.kay01:10:06

but [{[:table 2] [:x]}] will have dispath keys :table and :x, but keys [:table 2] and :x (if I remember right)

tony.kay01:10:57

because you would never want to write a defmethod to “catch” the dispatch of an unlimited possible number of idents

tony.kay01:10:21

you’d want one, and then it could look at the ast to see the whole thing

tony.kay02:10:16

Just released a new version of Fulcro Incubator with declare-mutation…a way to get rid of quoting in transact! and the problems with mutations sometimes wanting circular refs to the UI

tony.kay02:10:23

Updated Developer’s Guide to talk about it

bananadance 4
🎉 8
tony.kay02:10:50

Thanks to @thheller for the idea and initial implementation suggestion

👏 8
tony.kay05:10:24

helps if I press the “release” button…NOW it’s on clojars

hmaurer10:10:01

@tony.kay loving the new declare-mutation 🙂

hmaurer11:10:02

Quick question on the approach to full-stack error handling. Am I correct in understanding that any form of server-side validation (check if email unique on signup, or check other invariants that can only be checked on the server) should be handled using a plain-data response from the mutation in question? i.e. have the mutation return Either ValidationFailure SuccessPayload, store that result in the global state and switch the UI based on that?

claudiu11:10:07

@hmaurer that is how I'm doing it. Exceptions go into the global exception handler, there not really for local logic.

johnny15:10:12

If I have a mutation (say "ensure-article-loaded") with a load-action, which has a post-mutation of itself. How do I make sure this is not recursively executed if for some reason it cannot be satisfied. From my research into this I would need to check if :load-request is not already added to the environment. But I feel like this might be common case and is already handled somehow?

tony.kay15:10:45

@johnny the point of the name is that your mutation should conditionally call load-action…remote-load is a noop if there are no actions queued.

tony.kay15:10:11

Fulcro cannot know what “stale” or “missing” means for your data…

tony.kay15:10:08

if you mean “executed twice”, then I would say examine your logic…if, for example, you were running this in a react lifecycle that was on a to-many component I could see how you might be worried…in that case your mutation should put something in the state that indicates each item that is loading (which will be overwritten by the load).

tony.kay15:10:14

that way you can still short-circuit

tony.kay15:10:33

but in the general case a check of “is something there” is good enough

johnny15:10:04

Yeah Iam already calling the load-action conditionally, it's just that it can return with nothing in some cases.

tony.kay15:10:22

in that case put something that will get overwritten

tony.kay15:10:34

that your component will tolerate as “nothing” or “loading”…then your post-mutation can still fix it up (if necessary)

johnny15:10:50

Ok, thanks for the clarification, appreciated!

hmaurer15:10:30

@tony.kay any specific reason why the params argument on get-query is not optional?

tony.kay16:10:18

you mean get-initial-state?

tony.kay16:10:15

it’s a protocol internally

tony.kay16:10:25

guess I could technically make the function get-initial-state not require params…just haven’t 🙂

hmaurer17:10:20

yes, get-initial-state, sorry!

tony.kay17:10:12

feel free to send a PR if you want 🙂

hmaurer18:10:39

It’s a pretty minor thing; I was just curious as to whether there was a good reason behind it, or whether it was just a “could but haven’t” kind of thing