fulcro

Book: http://book.fulcrologic.com, Community Resources: https://fulcro-community.github.io/, RAD book at http://book.fulcrologic.com/RAD.html
2020-11-14T15:24:15.177800Z

I'm having an issue setting up server mutations and I can't figure out the cause. mutations.cljs

(defn delete-note*
  "Delete a Note and its CardList its Cards."
  [state-map note-id]
  (log/info "Deleting :note/id" note-id "and its CardList and Cards")
  (nstate/remove-entity state-map
                        [:note/id note-id]
                        #{:note/card-list :card-list/cards}))

(defmutation delete-note
  "Mutation: delete the note with `:note/id` from the note list with `:note-list`"
  [{note-id :note/id}]
  (action [{:keys [state]}] 
    (swap! state delete-note* note-id))
  (remote [env] true))
mutations.clj
(pc/defmutation delete-note [env {note-id :note/id}]
  {::pc/sym `delete-note}
  (swap! note-table dissoc note-id))
And my note-table looks like this:
(def note-table
  (atom
    {1 {:note/id 1 :note/text "foo from server"}
     2 {:note/id 2 :note/text "bar from server"}}))
When I have (remote [env] true) enabled, the :note/id in the application state after the mutation looks like this:
{2
 {:note/id 2, :note/text bar from server},
 1 nil}  ; why?!
If the (remote [env] true) line is commented out, it looks as I expect:
{2
 {:note/id 2, :note/text bar from server}}
The result from the server-side mutation looks correct:
#p[buidler.mutations/delete-note:15] (swap! note-table dissoc note-id) => {2 #:note {:id 2, :text "bar from server"}}

2020-11-15T14:00:41.182600Z

I tried all the way down to Fulcro 3.2.17 and Pathom 2.2.0 - 2.2.30 and still could not make it work properly. I'm running out of ideas here.

nivekuil 2020-11-15T14:27:27.182900Z

what is nstate/remove-entity? does that happen even if the server errors, like if the remote mutation doesn't exist? what happens if you have more notes in the state map, only the id you try to delete becomes nil?

nivekuil 2020-11-15T14:33:37.183100Z

the server return value is probably a red herring. it shouldn't do anything to client state unless explicitly merged

cjmurphy 2020-11-15T15:41:10.183300Z

Yes but from what's been said the server return is causing the problem. So there is some unintentional merging happening. 'shouldn't', yet is. But if your action did nothing you wouldn't get the problem. So the action prepares the state for a strange mutation return to cause the problem. You could put print statements in the fulcro source.

cjmurphy 2020-11-15T15:44:00.183500Z

There's a function called integrate-mutation-return-value!. Surely the culprit! Maybe just have it do nothing on your own version of the fulcro library.

cjmurphy 2020-11-15T15:44:33.183700Z

In com.fulcrologic.fulcro.mutations .

cjmurphy 2020-11-15T15:48:26.183900Z

I wouldn't be doing anything with server errors while you investigate this problem.

nivekuil 2020-11-15T16:14:38.184200Z

yeah, the swap! in that integrate mutation function only runs if there's wasn't a remote-error?, so if it has a different behavior on error then it's probably something going on there and I'd add logging to that function

2020-11-15T17:05:45.184700Z

I haven't seen any errors in the .shadow-cljs/server.stderr.log come up while doing this.

2020-11-15T17:31:57.184900Z

@cjmurphy I changed integrate-mutation-return-value! to:

(>defn integrate-mutation-return-value!
  "If there is a successful result from the remote mutation in `env` this function will merge it with app state
  (if there was a mutation join query), and will also rewrite any tempid remaps that were returned
  in all of the possible locations they might be in both app database and runtime application state (e.g. network queues).

  Typically used as part of the construction of a global default result handler for mutations.

  Returns env."
  [env]
  [::env => ::env]
  (print "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  env
  #_
I can see the x get printed when I execute the mutation from the UI, but the result is still the same lol

cjmurphy 2020-11-15T20:47:19.185200Z

I would then do the same with its caller, default-result-action! . That seems to then be everything that affects your app state.

2020-11-15T21:01:01.185400Z

I've narrowed it down to rewrite-tempids!.

2020-11-15T21:01:38.185600Z

Must be something in my code I guess. Hmm :thinking_face:

cjmurphy 2020-11-15T21:03:24.185800Z

Yes. Always been a candidate. But I never mentioned it because it is supposed to only do anything when your return map has a tempids key, which yours does not. But there is some kind of cache there - I was just looking at the code.

cjmurphy 2020-11-15T21:05:20.186Z

And the cache is kept in app state. At least you are in the world of source code again, even if still some more trial and error...

2020-11-15T21:10:56.186200Z

I did have previously returned a tempids map in that mutation, but that code has been deleted for a while.

2020-11-15T21:11:09.186400Z

It was also pretty cool to see how you can hack around on library code using shadow-cljs. Haven't done that prior to now.

cjmurphy 2020-11-15T21:46:11.186600Z

So a browser fresh (F5) would have solved the problem (by starting app state fresh)? And yes including the source code much easier these days. I've been using it more and more with RAD.

2020-11-21T01:54:05.241400Z

Nope, browser refresh doesn't solve it. Still having that same issue.

cjmurphy 2020-11-14T16:20:00.178500Z

If you return an empty map {} from your server mutation does that fix the problem?

cjmurphy 2020-11-14T16:27:05.178700Z

http://book.fulcrologic.com/#ReturnValues

2020-11-14T16:31:49.178900Z

@cjmurphy nope, returning an empty map doesn't fix it. Same result.

cjmurphy 2020-11-14T16:37:29.179100Z

So this would happen if your server mutation that did nothing and returned {} ? I want to rule out something else from the server affecting the client.

2020-11-14T16:39:16.179300Z

That's correct. I commented out the swap! form and just have it returning {} and it still happens.

cjmurphy 2020-11-14T16:43:55.179500Z

And do the same for all your server mutations perhaps? Also what about loads from the client? Gonna have to rule everything else out.

2020-11-14T16:45:33.179700Z

It's my only server mutation at this point, so that should make things simpler 🙂

2020-11-14T16:46:08.180Z

What/how should I check about client loads?

cjmurphy 2020-11-14T16:47:02.180200Z

df/load search for that. That really does affect your client state, that's what it is supposed to do.

cjmurphy 2020-11-14T16:48:05.180400Z

And then there is merge - two ways to do that.

2020-11-14T16:48:56.180600Z

From my ui the mutation is just called as such:

(div :.wide.column
          (dom/i :.ui.right.floated.icon.trash.alternate.outline
            {:onClick #(comp/transact! this [(m/delete-note {:note/id id})])}))

2020-11-14T16:49:12.180800Z

That's all there is to it, nothing else.

cjmurphy 2020-11-14T16:52:27.181Z

Is that :node/id being picked up on the server? I don't trust a mutation like that without and ~. Not that that's solving your problem. And I do know there is a way to get away with using and ~, just never used it.

cjmurphy 2020-11-14T16:53:55.181300Z

I guess it is working b/c it calls the client part of the mutation, the action part.

2020-11-14T18:00:19.181500Z

@cjmurphy yeah, the parameter is coming through to the mutation. I can log it.

2020-11-14T18:02:33.181700Z

The note-table atom even gets updated to remove the requested note, when I have the code uncommented.

cjmurphy 2020-11-14T23:52:00.182100Z

Have you tested with different versions of Fulcro? Submit a bug (especially) if everything works as expected with older versions. There is this open issue: https://github.com/fulcrologic/fulcro/issues/433. Different to yours but in the same area.

2020-11-14T23:54:37.182400Z

@cjmurphy Oh, interesting. Thanks for the link. I'm going to test that tomorrow and report if it works in another version.