Fork me on GitHub
Gustavo Bertolino00:01:48

Hi guys, I'm building a react demo appl with cljs (to practice cljs) and I'm thinking about changing this very appl on the fly via a remote repl. Is that possible? For example, suppose I want to change a component to correct it and re-rendering it with my appl running in production. Is it possible to make these things via repl?

Gustavo Bertolino00:01:49

obs.: the repl I'd connect with remotely is the one fired by the start of my appl


A repl can only change the running instance. For a long running clj process this would be fine. But a cljs process is just someone’s browser. So if you repld to a particular users browser you could change it but the next load of a page would just get the originally compiled code without any changes. The same as restarting a clj process.

👀 3
👍 3
Gustavo Bertolino03:01:15

Yes, I see. I made some tests here with my appl and re-rendering its component via repl and it works but only for one particular browser's tab or window that opens my appl. And after reloading the page, the browser takes the initial compiled code. Opening other tabs/windows and calling my appl also cause the same effect. I didn't notice that in the case of setting the browser as the target means that the repl (fired during the build) will be connected to that instance/process of the browser through I eventually open my appl.

Gustavo Bertolino13:01:26

But if this appl is a Electron appl which runs in a single JS process (a node process), or even a controlled number of JS processes. So in this case, in theory, I could make changes on the fly via a remote repl to inject this change on the node process running my appl and all the clients would take this change, wouldn't they? @dpsutton

Gustavo Bertolino13:01:04

obs.: in the case of a controlled number of node processes, each one running an appl's instance, I'd enter in the repl of each instance to make the change


I am uploading a video to the server like so:


 (fn [coeffects _]
   (prn "uploading video")
   (let [video {:uri (-> coeffects :db :shot-video-uri)}
         body (js/FormData.)]
     (prn "uri is " (-> coeffects :db :shot-video-uri))
     (.append body "video" video)
     {:http-xhrio {:method :post
                   :uri (str "" "/api/upload-shot-video")
                   :body body
                   :on-success [:upload-success]
                   :on-failure [:upload-error]
                   :response-format (edn/edn-response-format)}})))
where (-> coeffects :db :shot-video-uri) is the temporary uri of the image in the ios device


the handler that I have is the following:


For saving the input stream into a file

(defn upload-shot-video [req]
  (prn "uploading video")
  (prn "video is! " (-> req :params))
  (prn "video is " (-> req :body))
  ( (-> req :body) ( "./resources/public/"))

  (r/response {:res "okay!"}))


But the size of the file is turning out to be 0 bytes, whereas I expect a size greater than 0 bytes


How to correctly send the video to the server?


did you look into the extensive info noisesmith provided about the middleware? How it takes the body and creates a temporary file for you?


@dpsutton I removed the middleware and created a copy manually/


the video is in (-> req :body). At least there’s an inputstream in there


copying that input stream to the file system as a file is giving a file of 0 bytes


add a prn statement on your request. just see what's in there. i suspect you've got more middleware going on. there might be more information


@dpsutton Here’s the request:


{:reitit.core/match #reitit.core.Match{:template "/api/upload-shot-video", :data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :result #reitit.ring.Methods{:get #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :get, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :head #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :head, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :post #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :post, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :put #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :put, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :delete #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :delete, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :connect #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :connect, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :options #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :options, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :trace #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :trace, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :patch #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :patch, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}}, :path-params {}, :path "/api/upload-shot-video"}, :reitit.core/router #object[reitit.core$lookup_router$reify__11769 0x667531a6 "[email protected]"], :aleph/request-arrived 166349045051244, :aleph/keep-alive? true, :cookies {}, :remote-addr "0:0:0:0:0:0:0:1", :params {:video ""}, :flash nil, :headers {"host" "", "user-agent" "Humboi/1 CFNetwork/1206 Darwin/20.1.0", "content-type" "multipart/form-data; boundary=BrxekIJ39.PWpQVKqWBWuBAz5KUTH7jhXk67qEssuW4LZbO4Df535XFNLmYDbDGWT73QsP", "content-length" "200", "accept" "application/edn", "accept-language" "en-us", "x-forwarded-for" "", "accept-encoding" "gzip, deflate"}, :server-port 3000, :muuntaja/request #FormatAndCharset{:format nil, :charset "utf-8", :raw-format "multipart/form-data"}, :form-params {}, :session/key nil, :query-params {}, :uri "/api/upload-shot-video", :server-name "localhost", :query-string nil, :path-params {}, :muuntaja/response #FormatAndCharset{:format "application/edn", :charset "utf-8", :raw-format "application/edn"}, :body #object[ 0x222b0412 "[email protected]"], :multipart-params {"video" ""}, :scheme :http, :request-method :post, :session {}}


The only middleware is wrap-formats


can you open up the browser network pane and make sure you're actually sending bytes across the wire?


I don’t know how to do that. How does one open a browser network pane?


@ps What browser are you using?


Ah... been many years since I used that... I'm sure it has developer tools but no memory of how to get at them...


command option I


I have been using Microsoft Edge on macOS for ages -- and cmd-opt-i is what Edge uses to open dev tools 🙂


@dpsutton You mean open the developer console here?: http://localhost:8081/debugger-ui/


Chrome has "dev tools" (as does Microsoft Edge for macOS).


Develop > Show Web Inspector. then click on the network tab


wouldn’t http://localhost:8081/debugger-ui/ open the simulator debugging and not the device? I’m recording the video on the device


which is supposed to be sent to the server after video stops recording


I have a feeling that http://localhost:8081/debugger-ui/ doesn’t open debugging for the device


no actually the debugger is working with the device


but @dpsutton what should I be looking for in the network tab?


the request that has a big video payload. look for it having some form data, try to find the size of the request, etc


identify if the video is getting to your backend and the problem is finding it in the request or if the frontend is sending it and you need to fix that first. just general debugging steps. cut the problem in half and then figure out a way to cut that remaining problem in half, etc


I don’t see any new requests in the console, whereas the server is receiving the request


if you're on the network pane and its correctly hooked up and you hit refresh you should see requests to load your js and html. i don't know what you're looking at so can't help you further


I do see the other requests


but apparently not the one with the video


and the number of requests isn’t increased either


I read this on cljs-ajax which the http-xhrio library wraps


cljs-ajax doesn’t have any other support for file uploads (although pull requests are welcome).


but in this issue the user successfully uploads the file:


This is confusing


hi everyone, probably stupid question asked million times but

(= (hash 1) (hash 1.7))
;; => true
is that expected?


Clojure has different behavior

Alex Miller (Clojure team)14:01:16

hashes are not guaranteed consistent across platforms


you can fudge that a little bit with ClojureScript

Alex Miller (Clojure team)14:01:56

and having hashes collide is certainly normal


for various reasons we do try to generate identical hashes where practical


numbers are problematic of course because JavaScript only has double


so aligning things here is not really worth the other complications


thanks for explanation :thumbsup::skin-tone-3:


A quick cljs REPL experiment shows that cljs vectors appear to be more like Clojure 1.5.1 and earlier, in that they collide often for a set of vectors like:

(def grid-keys (for [x (range 100), y (range 100)]
                        [x y]))


That was one example of the kind of hash collisions that led Clojure to change its hash function in Clojure 1.6.0


I don't know whether the performance tradeoffs for fancier hashing is the same in cljs -- just thought I'd mention the results of that experiment, since the code demonstrating the problem with older Clojure versions was easy to copy and paste.

Gustavo Bertolino15:01:52

Hi guys, could someone validate this scenario for me? I was thinking if it's correct or feasible The context is to see if it make sense my thought of accessing the JS process on which is running my cljs appl so that I can make changes in it on the fly


@andy.fingerhut we use the same hashing functions as Clojure at the bottom


so we have the post 1.6 stuff, whether we have the vector specific tweaks is another investigation


Is a CLJS ticket that at first simply collects some observations on latest CLJS version hash behavior as compared to latest Clojure version perhaps useful?

Brian Kelly18:01:34

Morning everyone - a member invited me and thought it would valuable to do a quick Post. I am hiring a few full time software engineers specifically with closure experience. Also looking for a UI Developer with Clojurescript experience. Please DM me if you are interested in hearing more. Thank you


There are special channels for that - #jobs and #remote-jobs


Make sure to read the channels' descriptions.

Brian Kelly18:01:56

Absolutely and this will be my only post in here. 2 members asked me to do it to help others in the community that may be looking for work !

👍 3

@U01K8867LH2 This is the second time you've been told not to post jobs in general channels -- and the second time I've deleted your post. If you want to post a job, do it in the appropriate channel and provide details about location/remote and any other criteria. Just saying "DM me for more details" just wastes people's time. /admin

☝️ 4