Fork me on GitHub
#fulcro
<
2018-12-29
>
eric.shao04:12:43

@mdhaney Wow,Thank you for your reply.I can’t figure out why my :started-callback can’t load things from the server.How do you debug the client server communication problem?Thanks.😊

eric.shao04:12:55

console.error: "[18.362s]  [fulcro.client.network] Transit decode failed! SyntaxError:Unexpected token u in JSON at position 0"

eric.shao04:12:16

Really hope to see your demo projects or project template.

tony.kay04:12:49

@eric.shao what are you sending back and forth? That is a transit failure. Perhaps you sent some data that transit can encode in JVM, but not decode in cljs?

eric.shao08:12:24

@tony.kay I think it is in cljs,not even touch the server. 1. The df/load code in RN client side is identical to the Web client side .And the web’s reaction is right. 2: The problem is in df/load(there is a console.log) but before the http request was even sent. Because in the react native debug console’s network tab there is not a new XHR and the console.log in server’s defquery is not invoked. I’ll try again from scratch.

eric.shao16:12:03

1. Still the same Transit decode error. 2. The :ident begin to show problem [ 3.697s] [fulcro.client.primitives] component main.state-machine-ws.ui.components/PersonList’s ident ([:person-list/by-id nil]) has a nil second element. This warning can be safely ignored if that is intended. [ 3.703s] [fulcro.client.primitives] component main.state-machine-ws.ui.components/Person’s ident ([:person/by-id nil]) has a nil second element. This warning can be safely ignored if that is intended. 3. Without REPL and FulcroInspector it’s hard to http://program.It reminds me how much work tony has put to make our work easy with FulcroWeb. Thank you Mr. tony.kay. 4. Mr @mdhaney , please share your experience in code and articles.😊

hmaurer19:12:15

Hi! I have a “library” for my Fulcro project in the main directory, i.e. src/main/my_project/core/lib.cljc. I would like to test it using devcards, so I created a file src/cards/my_project/core/lib.cljs (mirroring the main tree). I thought I would be apple to access methods define in my lib.cljc file but it looks like it’s not getting compiled as part of shadow-cljs watch cards. How can I remedy this?

hmaurer19:12:18

I solved the problem by renaming my cards namespace to lib_cards, after which I could import the core/lib.cljc namespace and take it from there. I would rather have both share the same namespace though, so my question still stands 🙂

hmaurer19:12:45

problem solved no #shadow-cljs

mdhaney20:12:00

@eric.shao your problem might be shadow-cljs. When I started this project and looked into shadow-cljs, they were in limbo with RN support (there were some older attempts that kinda worked, but then broke with newer releases). The Expo lein template worked out of the box, but it doesn’t support Fulcro and only supported Expo 26, which is about 10 months old now. What I did was start with the Expo template and Om.next, then swapped out Fulcro for Om and upgraded the Expo version to 30, which is the last release on RN 55 (versions 56 and 57 had a lot of tooling changes, and last I checked re-natal wasn’t even supporting them yet). This has worked quite well. I get a working REPL, which has proved invaluable. Fulcro inspect isn’t working - it’s not detecting the Fulcro app when I run the app remotely on Chrome. It seems to me this might be fixable, but I haven’t had the cycles to dig into it. To avoid the externs issue, I’m using cljs-oops and so far that has worked well. I’ll pull out the core client code and upload a project tonight. Converting the Expo template to use Fulcro and upgrade Expo was pretty straightforward, but IIRC there were a couple of gotchas during the process.

tony.kay20:12:11

Fulcro 2.7.0 released. This includes a breaking change in websockets (the API for sente changed due to a security hole (which we had a workaround for)). It also fixes a bug in SSR state encode/decode. Thanks @lennart.buit.

👍 13
hmaurer20:12:36

@tony.kay I am about to start a new fulcro project. Would you recommend the websocket transport or the HTTP transport? My only real requirement is that order of mutations is preserved (i.e. the transport doesnt submit a mutation to the server until it has received a confirmation by the server that the previous mutation has been processed)

tony.kay20:12:46

@hmaurer both are fine. If you submit a tx as a unit to a single remote, then the sequence of calls in that tx will be preserved, but it will be transmitted all at once. So, the behavior on the server is up to you. If the mutations are queued in separate event invocations, then Fulcro, by default, serializes requests

tony.kay20:12:59

I.e. [(f)] [(g)] is possibly different in processing from [(f) (g)], but is up to your implementation on the server. There are 2 possible scenarios for the 1st.

tony.kay20:12:19

If 2 txes are submitted on the same user event, then they are combined, and are equivalent to the second form

hmaurer20:12:29

Okay, so both would be fine? My use-case would be the later (separate mutations). Roughly speaking I am building an exercise application, where the state of exercises are dictated by a sequence of events. The user (student) does an action on the frontend which moidfies the state of the exercise. I want to apply it optimistically on the frontend (to show new state without lag) and also transmit the event to the backend to persist the student’s current exercise state

tony.kay20:12:44

unless they share mutation name. [(f) (f)] is always split into 2

hmaurer20:12:03

The reason why it needs serialisation is that a student might perform multiple actions quickly in a row, in which case we would want the server state to be the same as the client’s state

hmaurer20:12:10

exercise state I mean

tony.kay20:12:27

yep…that is one very important thing that was designed in from the beginning

hmaurer20:12:15

Great 🙂 And what is the default behaviour in case of failure on the server side? (also, is the default behaviour to apply the mutation optimistically on the frontend?)

tony.kay20:12:53

See pessimistic mutation support in Fulcro Incubator

tony.kay20:12:06

The book goes through all of this, but the end result it you probably want that

tony.kay20:12:19

it allows for optimistic UI update and easy failure handling

tony.kay20:12:48

The optimistic update is not rolled back for you, if that is what you’re asking.

tony.kay20:12:14

Just too many possible desired behaviors (you might want to retry instead)

tony.kay20:12:24

so there is no automation around error handling

hmaurer20:12:41

Yep, I was basically asking: if A -> B -> C are applied optimistically on the frontend (where A, B, C are mutations), and the server queue fails on B, what happens?

hmaurer20:12:50

but if the answer is in the book I won’t bother you further

tony.kay20:12:59

the answer is “that depends”

tony.kay20:12:25

Start by reading the stuff on ptransact! in the book, then look at the pessimistic mutation docs in incubator

tony.kay20:12:50

is a good starting point

hmaurer20:12:32

and (late) merry christmas 🙂

tony.kay20:12:32

Thanks, happy holidays to you as well 🙂

hmaurer20:12:57

I’ll definitely read that; in my case I don’t want to hard fail if a mutation fails. The idea is to “sync” a client state (exercise state) with a server state. So I want to let the student keep going in the exercise, and perhaps if syncing really fails (i.e. 3 retries fail) then give a warning that the connexion might be broken and that his progress will be lost

hmaurer20:12:36

or syncing might fail because the auth token expired, in which case I would just want to refresh it and retry

tony.kay20:12:37

Hm…the docs on incubator are a little weird on that. You can use normal Fulcro ptransact! with those now…it mentions transact functions in incubator, which are not necessary.

hmaurer20:12:42

those are the only two scenarios I can think of

tony.kay21:12:39

So, you might even consider implementing retry at the network layer. The built-in Fulcro remote isn’t that complicated (use the source), and that kind of recovery would probably be best handled at that layer.

tony.kay21:12:21

Websocket support has a basic version of that (auto-retry), BUT it requires your mutations be idempotent (as your own implementation would need to as well, since you can’t know on a failure what the server saw)

hmaurer21:12:26

does that suggestion apply regardless of whether the transport is http or websocket? or is one easier than the other ?

hmaurer21:12:39

ah, you tackled that point faster than I wrote my question 😛

hmaurer21:12:04

I guess I can make mutations idempotent by tagging them with an ID and check that on the backend

hmaurer21:12:11

in my case that’s an acceptable solution

hmaurer21:12:19

it won’t have noticeable performance impact

tony.kay21:12:21

Auto-retry could be added to the built in normal one as well, but most of my projects use websockets, so it got the attn on that.

hmaurer21:12:48

so I guess using websocket is also a better idea if I want to get the most out of you, should any issue arise 😛

tony.kay21:12:57

not necessarily 🙂 The code works “well enough” for me that I’ve not had to look at the network layer in some time. I wouldn’t say I’m any better at dealing with issues on either.

tony.kay21:12:17

I looked further at the docs. It think the incubator stuff is actually all ok…the comment on “composition” https://github.com/fulcrologic/fulcro-incubator#composition is what I was trying to get at/remember.

tony.kay21:12:28

so it is probable you sshould just trust the docs 🙂

tony.kay21:12:25

Yeah…the docs are right

tony.kay21:12:44

But I think they might mislead you slightly unless you know this: Separate invocations will not have a blocking behavior (e.g. 2 calls to ptransact will never be combined of block each other)…so, it requires a bit more care…but auto-retry at the network layer sounds like a better call. YOu can also get network status notifications from websockets (though they are sometimes delayed a lot by browser implementation).

tony.kay21:12:21

E.g. (pm/ptransact! this [(f) (g)]) may delay the invocation of g until f completes full stack…but if the user submits a new tx (h), then that one won’t* necessarily be blocked by the completion of the (yet incomplete) g. You could see f, h, g. The order that is guaranteed is that g comes after f. period.

hmaurer21:12:43

Sorry, just to clarify: (prim/ptransact! this '[(a) (b)]) will run (a) and (b) serially, but you said that mutations are also queued by remote, right? and serially applied

tony.kay21:12:36

so if h got queued while f was running, then it may run before g

tony.kay21:12:12

The queue of g doesn’t even happen until f completes

hmaurer21:12:13

ah, so both f and g don’t get queued at once, then h queued after that?

hmaurer21:12:51

and if I wanted to run those 3 actions serially?

hmaurer21:12:58

f, g then h

hmaurer21:12:14

(but I don’t want to add h to the same ptransact call)

tony.kay21:12:24

have to be in same tx, or in 3 diff ones

tony.kay21:12:43

the former uses the pessimistic support, the latter relies on the queue

tony.kay21:12:49

but the latter does not let you short-circuit

hmaurer21:12:53

so

(pm/ptransact! this [(f)])
(pm/ptransact! this [(g)])
then later
(pm/ptransact! this [(h)])
?

tony.kay21:12:41

those will go in order, BUT all of the optimistic will run immediately

tony.kay21:12:48

the network queue is just about remotes

tony.kay21:12:10

optimistic is always immediate unless using ptransact and a single tx

hmaurer21:12:22

whereas with (pm/ptransact! this [(f) (g)]) it would optimistically run f, wait for completion, and if successful optimistically run g and wait for comlpetion?

tony.kay21:12:27

in which case full-stack has to complete before next runs optimistically

hmaurer21:12:44

Thanks for pointing that out; it would definitely have confused me if I stumbled on it

hmaurer21:12:10

is there one queue per remote btw?

tony.kay21:12:12

The main point of ptransact is to be able to hold off on optimistic updates until a remote has completed.

tony.kay21:12:18

one queue per, yes

tony.kay21:12:39

ptransact works across them

tony.kay21:12:01

BUT, do not turn off serial operation on the remote (which is an option). That will break it (it bypasses the queue)