Fork me on GitHub
#fulcro
<
2020-05-19
>
tony.kay01:05:30

serializability. Inspect, support viewer, etc. In general if you use code in mutations or in the db you’re likely to run into problems. Computed is another story, actually. That has to do with targeted refresh.

tony.kay01:05:47

All that said, if you want to shove code into the db, it will mostly work

tony.kay01:05:31

mutations are symbols for a reason, though, and you can always put a symbol and data into the db, and then construct a mutation call from that…and that is perfectly fine in all of those other cases, and if you think about the overall structure of Fulcro: operations happen via mutations, so when you have an operation to “store”, shouldn’t you be storing the call, not the implementation of the call?

JAtkins01:05:03

Ok, cool. I was wondering why, esp since I just made a big change to my app to include them 🙂

Robin Jakobsson09:05:27

I remember there being some kind of article or gist which showed HTML5-routing in Fulcro, but I can’t seem to find it. EDIT: Found it! https://chrisodonnell.dev/posts/giftlist/routing/

👍 4
Jakub Holý (HolyJak)14:05:23

the RAD demo also has built in html5 routing

👍 4
zilti14:05:26

Seems like I am stuck at this now... "Parser Error: Mutation not found {:mutation com.example.model.account/check-session}". I am using the most up-to-date fulcro-rad-demo codebase as base, and there is no mention of com.example in my codebase.

Jakub Holý (HolyJak)14:05:48

I am quite sure that RAD demo has that namespace?!!

zilti15:05:46

It has, but I replaced that name completely. Which means something outside of the fulcro-rad-demo repository probably has that hardcoded

Jakub Holý (HolyJak)15:05:29

When is that error thrown? As a result of a call from the frontend, I assume? What data is sent in that call?

zilti15:05:42

On the initial loading of the frontend

zilti15:05:49

20-05-19 15:02:24 linux-idle ERROR [com.fulcrologic.rad.pathom:73] - Parser Error: Mutation not found {:mutation com.example.model.account/check-session}
                                                                                                        java.lang.Thread.run                            Thread.java:  834
                                                                      org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run             EnhancedQueueExecutor.java: 1449
                                                                org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask             EnhancedQueueExecutor.java: 1558
                                                                             org.jboss.threads.EnhancedQueueExecutor.safeRun             EnhancedQueueExecutor.java: 2019
                                                                      org.jboss.threads.ContextClassLoaderSavingRunnable.run  ContextClassLoaderSavingRunnable.java:   35
                                                                                 io.undertow.server.HttpServerExchange$1.run                HttpServerExchange.java:  830
                                                                            io.undertow.server.Connectors.executeRootHandler                        Connectors.java:  370
                                                           io.undertow.server.session.SessionAttachmentHandler.handleRequest          SessionAttachmentHandler.java:   68
                                    org.projectodd.wunderboss.web.undertow.async.websocket.UndertowWebsocket$2.handleRequest                 UndertowWebsocket.java:  109
                                                      immutant.web.internal.undertow/create-http-handler/reify/handleRequest                           undertow.clj:  239
                                                                                           ring.middleware.gzip/wrap-gzip/fn                               gzip.clj:  100
                                                                                            ring.middleware.ssl/wrap-hsts/fn                                ssl.clj:  105
                                                                                  ring.middleware.x-headers/wrap-x-header/fn                          x_headers.clj:   22 (repeats 2 times)
                                                                           ring.middleware.not-modified/wrap-not-modified/fn                       not_modified.clj:   61
                                                                     ring.middleware.default-charset/wrap-default-charset/fn                    default_charset.clj:   31
                                                                           ring.middleware.content-type/wrap-content-type/fn                       content_type.clj:   34
                                                                  ring.middleware.resource/wrap-resource-prefer-resources/fn                           resource.clj:   25
                                                               ring.middleware.absolute-redirects/wrap-absolute-redirects/fn                 absolute_redirects.clj:   47
                                                                                     ring.middleware.cookies/wrap-cookies/fn                            cookies.clj:  214
                                                                                       ring.middleware.params/wrap-params/fn                             params.clj:   67
                                                                   ring.middleware.multipart-params/wrap-multipart-params/fn                   multipart_params.clj:  171
                                                                         ring.middleware.nested-params/wrap-nested-params/fn                      nested_params.clj:   89
                                                                       ring.middleware.keyword-params/wrap-keyword-params/fn                     keyword_params.clj:   53
                                                                                     ring.middleware.session/wrap-session/fn                            session.clj:  108
                                                                  com.sompani.components.ring-middleware/wrap-html-routes/fn                    ring_middleware.clj:   53
                                                       com.fulcrologic.fulcro.server.api-middleware/wrap-transit-response/fn                     api_middleware.clj:  167
                                                         com.fulcrologic.fulcro.server.api-middleware/wrap-transit-params/fn                     api_middleware.clj:  138
                                                                               com.fulcrologic.rad.blob/wrap-blob-service/fn                              blob.cljc:  315 (repeats 2 times)
                                                 com.fulcrologic.fulcro.networking.file-upload/wrap-mutation-file-uploads/fn                        file_upload.clj:   83
                                                                          com.sompani.components.ring-middleware/wrap-api/fn                    ring_middleware.clj:   36
                                                             com.fulcrologic.fulcro.server.api-middleware/handle-api-request                     api_middleware.clj:   69
                                                          com.fulcrologic.fulcro.server.api-middleware/handle-api-request/fn                     api_middleware.clj:   70
                                                                       com.sompani.components.ring-middleware/wrap-api/fn/fn                    ring_middleware.clj:   38
                                                                        com.fulcrologic.rad.pathom/new-parser/wrapped-parser                             pathom.clj:  160
                                                      com.wsscode.pathom.core/wrap-normalize-env/wrap-normalize-env-internal                              core.cljc:  977
                                                      com.wsscode.pathom.core/wrap-normalize-env/wrap-normalize-env-internal                              core.cljc:  979
                                                            com.wsscode.pathom.connect/connect-plugin/connect-wrap-parser/fn                           connect.cljc: 1740
                                                com.wsscode.pathom.core/wrap-parser-exception/wrap-parser-exception-internal                              core.cljc:  808
                                                                                            com.fulcrologic.rad.pathom/fn/fn                             pathom.clj:  121
com.wsscode.pathom.core/post-process-parser-plugin/transform-parser-out-plugin-external/transform-parser-out-plugin-internal                              core.cljc:  718 (repeats 2 times)
                                          com.wsscode.pathom.core/env-plugin/env-plugin-wrap-parser/env-plugin-wrap-internal                              core.cljc:  878
                                         com.wsscode.pathom.core/env-wrap-plugin/env-wrap-wrap-parser/env-wrap-wrap-internal                              core.cljc:  886 (repeats 4 times)
                                          com.wsscode.pathom.core/env-plugin/env-plugin-wrap-parser/env-plugin-wrap-internal                              core.cljc:  878
                                                                                       com.wsscode.pathom.parser/parser/self                            parser.cljc:  235
                                  com.wsscode.pathom.core/wrap-mutate-handle-exception/wrap-mutate-handle-exception-internal                              core.cljc:  783
                                                                                           com.wsscode.pathom.connect/mutate                           connect.cljc: 1522
clojure.lang.ExceptionInfo: Mutation not found
    mutation: com.example.model.account/check-session

zilti15:05:21

Fulcro Inspect is full of mentionings of com.example though

Jakub Holý (HolyJak)15:05:43

Look not at the server but client, that is initiating the call. I guess your cleanup was not so successfull. Perhaps stop shadow and rm -rf all generated .js? I guess you don't have https://github.com/fulcrologic/fulcro-rad-demo/blob/master/src/shared/com/example/ui/login_dialog.cljc#L20 and https://github.com/fulcrologic/fulcro-rad-demo/blob/master/src/shared/com/example/ui.cljc#L45 anymore?

zilti15:05:19

I can run an ag -Q com.example in the root directory of the project and get zero results

zilti15:05:13

I deleted .shadow-cljs, .cpcache and all generated javascript

zilti15:05:10

And yes, I don't have these anymore

Jakub Holý (HolyJak)15:05:34

BTW I did what you did, using the demo as a starting point and then getting rid of com.example, and I do not have the problem

zilti15:05:16

It did not help, but what did help was to tinker around with the script src in index.html. Why it managed to even get as far as it did without a valid script is beyond me...

zilti15:05:35

But thanks!

👍 4
dvingo17:05:39

Has anyone used tick(https://github.com/juxt/tick) with fulcro? I believe its use of time literals is causing all sorts of problems for fulcro inspector mainly during calls to pr-str by the inspector. I have a local version of the inspector running (chrome extension version) and whenever a map of data with tick values in it is printed I see:

dvingo17:05:07

Here's an example. If I click the copy button for the outer record, I get the max call stack error. But if I copy the habit/tasks data, there is no problem

dvingo17:05:39

this is the main problematic line https://github.com/fulcrologic/fulcro-inspect/blob/master/src/ui/fulcro/inspect/ui/transactions.cljs#L66 if i change that to a plain string like:

(let [f (first content)]
  (str (if (seq? f) (first f) f)))
then inspect at least doesn't crash

tony.kay17:05:43

Yeah, Inspect uses transit to send values across the security boundary, so any non-recognized EDN gets handled by a “default” handler. Not sure why pr-str goes into an infinite loop. that’s kind of weird.

tony.kay17:05:11

Hm…I wonder if this is an actual error, or if you’re selecting so much data that it is a recursive algorithm and blows the stack before it manages to finish. The “outer record” is the entire db.

tony.kay17:05:10

And your replacement code doesn’t try to print nearly as much, nor recursively down every path.

dvingo17:05:22

i had that thought too about it just being too much data, but it's about a screen full.. The screenshot i posted is cropped to just one property, it's not the full db

tony.kay17:05:50

interesting

dvingo17:05:14

the clj formatter for devtools also blows up with it though

tony.kay17:05:15

why is it getting into a loop I wonder…it is in the recursive algorithm, and it is running out of stack…so it is clearly going in a loop

tony.kay17:05:10

putting a breakpoint somewhere in that stack trace and triggering the error might help

tony.kay17:05:33

on line 10086 in core.cljs is where the main recursive part happens I think

dvingo17:05:39

ooh good idea - in chrome or in intellij?

tony.kay17:05:00

yeah, see which branch it keeps going down

dvingo17:05:11

gotcha, that makes sense

tony.kay17:05:17

too bad you’re not getting a source map on that

tony.kay17:05:33

would be easier to just look at the stack trace…

dvingo17:05:00

yea i get a bunch of warnings that the map files can't be loaded

tony.kay17:05:22

could be a proble with your server

tony.kay17:05:34

network tab might be saying why

dvingo18:05:25

This is the error for the source map failures: DevTools failed to load SourceMap: Could not load content for <chrome-extension://hbmcmeegjjiijojkbofeekehegcjbaib/out/cljs-runtime/fulcro.tempid.js.map>: HTTP error: status code 404, net::ERR_UNKNOWN_URL_SCHEME I'm new to all this setup so I'm a bit confused. I thought the shadow cljs webserver for fulcro inspect handles these requests. I also don't see the map files being requested the network panel of the extension's inspector

tony.kay18:05:17

oh…the source maps for inspect itself would have to be pacakged in the chrome extension 😞

tony.kay18:05:47

not sure how to fix that

dvingo18:05:17

no prob. I'm trying to trim down the problem - so i can send tick values and the network + tx tab are working..

dvingo19:05:53

Ok. I've narrowed down a repro. In my codebase I have the following transit writer:

(deftype TickHandler []
    Object
    (tag [_ v] "time/tick")
    (rep [_ v] (with-out-str (pr v)))
    (stringRep [_ v] nil))

  (def tick-transit-write-handler (TickHandler.))

  (def tick-transit-writer-handler-map
    (reduce
      (fn [m [k v]] (assoc m k v))
      {}
      (partition 2
        (interleave
          [Date DateTime Time Period Duration Instant]
          (repeat tick-transit-write-handler)))))

  (def date-writer (tr/writer :json {:handlers tick-transit-writer-handler-map}))
  (tr/write date-writer {:breaks #time/date "2020-05-19"})
when I write the above I get the string:
"[\"^ \",\"~:breaks\",[\"~#time/tick\",\"#time/date \\\"2020-05-19\\\"\"]]"
i copy that into the inspect repl for the ns fulcro.inspect.remote.transit and eval: (read "[\"^ \",\"~:breaks\",[\"~#time/tick\",\"#time/date \\\"2020-05-19\\\"\"]]") which gives me the error in the repl output:
Error handling response - class java.lang.ClassCastException: 
class clojure.lang.PersistentVector cannot be cast to class java.lang.CharSequence (clojure.lang.PersistentVector is in unnamed module of loader .PluginClassLoader @332e16cc; java.lang.CharSequence is in module java.base of loader 'bootstrap')
which shows up in devtools as:
RangeError: Maximum call stack size exceeded
    at Object.eval [as cljs$core$ILookup$_lookup$arity$2]
I'm pretty new to encoding types to transit, so I could foresee this being a problem with the writer I have. I think I'll try copying the default writer you're using and see if that fixes the problem

dvingo19:05:22

this is actually the simplest repro:

(tr/write date-writer #time/date "2020-05-19")
(f.i.r.transit/read "[\"~#time/tick\",\"#time/date \\\"2020-05-19\\\"\"]" )

dvingo19:05:13

reading this works in my app between FE and BE using this reader on the client:

(def date-reader (tr/reader :json {:handlers {"time/tick" #(cljs.reader/read-string %)}}))

Jakub Holý (HolyJak)15:05:30

Could something like this (from the time literals library) https://gist.github.com/jdf-id-au/2e91fb63ce396b722c1d6770154f1815 help?

dvingo16:05:40

i have transit codecs in my app for tick (time literals), but inspect does not

dvingo16:05:44

though, i did add them in my local dev version of spec and the pr-str bug still happens so that may actually not be the cause of the issue. esp because the DB tab works, but not network, txes, or db explore

dvingo16:05:31

but my implementation is different from this, so i'll give this a shot

dvingo17:05:47

still happening - that example just uses different tags for the time literals than what I had, so makes sense that it wouldn't work. I'll try again playing with inspect at some point

dvingo14:05:39

so, I finally found a solution for this.

fulcro.inspect.remote.transit
(defrecord TestIt [a])
(write (TestIt. 5))
=> "[\"~#unknown\",\"#fulcro.inspect.remote.transit.TestIt{:a 5}\"]"
  (read "[\"~#unknown\",\"#fulcro.inspect.remote.transit.TestIt{:a 5}\"]")
=> throws the error I've been getting
to fix it I added a default read handler:
(def read-handlers
  {"js-error" (fn [[msg data]] (ex-info msg data))
   "unknown" (fn [v] (str "UknownTransitType:" v))})
js-joda dates will show up in inspector as a string "UknownTransitType:2020-05-21" which is fine by me.

tony.kay16:05:33

oh..a default wasn’t in there? That’s an oversight

dvingo17:05:50

ok that's good to know. I wasn't sure if transit would somehow know what to do, but that makes sense now why it was breaking

dvingo00:05:14

should I open an issue for this on github?

tony.kay01:05:23

a pR would be great

dvingo18:05:18

sounds good, i'll put one together

Björn Ebbinghaus18:05:54

@tony.kay There is a css problem in the Inspect Binary. The Index-Explorer has classes prefixed with com_wsscode_pathom_viz_ui but these aren't defined anywhere.

tony.kay18:05:24

chrome or electron?

Björn Ebbinghaus18:05:55

I guess there is just a inject/style-element missing somewhere.

tony.kay18:05:28

feel free to look around. I don’t have time to mess with it at the moment

tony.kay18:05:49

I think I found it. What OS are you on?

tony.kay18:05:08

@mroerni I’m uploading a new release…try it out and see if that fixes it

tony.kay18:05:17

will be up in a moment

Björn Ebbinghaus19:05:55

I am on MacOS. It is fixed. Thanks for the quick response

dvingo20:05:53

I'm wondering if the fulcro inspector could be simplified by having it be embedded in the dom, alongside your app. similar to reframe 10x https://github.com/Day8/re-frame-10x

Björn Ebbinghaus20:05:14

Hm.. I never experienced network problems... I quite like it to have it separate. I often have the DevTools popped out of the Window. The only thing I would like to see back is the component inspector... from v2.

dvingo20:05:23

have you ever encoded custom types for transit?

dvingo20:05:45

ever seen missing ids and data in the DB view?

dvingo20:05:02

it also only works for one browser

tony.kay20:05:40

it used to be embedded in the DOM. We abandoned that because then we had a whole other host of problems (Css conflicts, etc.). I didn’t write the original inspect, or the rewrite even…to be honest I kind of prefer the “in the DOM” approach because I think it does have fewer headaches…but then now that we want electron we always have the potential “on the wire” issues…so it is kind of moot.

tony.kay20:05:02

If you want to make a 3rd version that goes in the DOM, feel free. I have no time to address it….

tony.kay20:05:16

oh, and the in-browser version also suffers from NPM madness: some of the inspect tabs use things like d3 etc…if your app uses those and there are conflict problems, then it totally hoses your development and you would just have to abandon the tooling

tony.kay20:05:32

so, I think the decision for it to be “remote” is actually the right overall choice

tony.kay20:05:28

The “in the browser” could work if you precompiled Inspect as a js file, and just included it…then you could package it up as an isolated js blob.

tony.kay20:05:45

so then it would be “remote but not remote”

dvingo23:05:22

like everything worth doing the answer is "it depends there are tradeoffs"... I'll most likely start building a collection of helpers as i need them, the network and tx tab often crash because of that max callstack error I posted.

dvingo23:05:54

i don't understand enough about the setup between tabs, but the db tab does show the types correctly: [TaggedValue: unknown, 2020-05-19]

dvingo23:05:26

but the db explorer view for example, crashes

tony.kay00:05:29

probably not hard to fix. either wrap pr-str in a try/catch, or do something else to format the special case

dvingo03:05:30

hard and easy are relative to the context you have...

dvingo04:05:44

i know what you mean, seems like is should be quick fix, but these seemingly minor fixes usually bring some surprises 🙂

dvingo20:05:12

then network encoding issues go away and the security restrictions from browsers