Fork me on GitHub
#fulcro
<
2020-03-15
>
twashing16:03:14

I put this question on SO. But I think I’m missing something basic in enabling Fulcro websockets. https://stackoverflow.com/questions/60695250/howto-enable-fulcro-websockets For Fulcro Websockets, how do I i) get the client to first establish a connection to the sever. Then ii) do sever pushes?

Piotr Roterski08:03:43

I answered you https://stackoverflow.com/a/60702600/3504803 so it's easier to find for others. TL;DR: since fulcro-websockets 3.1.0 the connection is made on the first data transfer via the websocket remote

Piotr Roterski08:03:07

then you can do a push this way:

(:require [com.fulcrologic.fulcro.networking.websocket-protocols :refer [push]])

(let [client-uid (-> @(:connected-uids websockets)
                     :any
                     first)]
    (push websockets client-uid :foo-topic {:foo "bar"}))

tony.kay15:03:14

That just sends to some random connected user-id, whicih could push to multiple clients depending on your user mapping function. All of that is Sente functionality. Typically you will either have some mapping in the request (i.e. session) for mapping CIDs to UIDs. The id on a given incoming websocket request can be stored as a way to track a particular connection. See the Sente docs for more info and examples on tracking UID vs. CID. https://github.com/ptaoussanis/sente#server-side-api

👍 4
twashing02:03:06

@UHA0AQZ2M Thanks for making that answer. It helped me a lot. But I still wasn’t able to trigger an initial remote call. If you want to see the details, I put my initial Fulcro Template / Websocket attempt here: https://github.com/twashing/beatthemarket.fulcro

twashing02:03:41

@U0CKQ19AQ Thanks for the heads up. I guess I’m trying to grok how to make that initial WS connection with a remote. What’s slightly confusing to me is that there seem to be 2 ways to set up a remote

;; A
(defonce app (app/fulcro-app {:remotes {:remote (fws/fulcro-websocket-remote {})}}))

;; B
(defonce SPA (atom nil))
(reset! SPA (fc/make-fulcro-client
                {:client-did-mount (fn [beatthemarket]
                                     (df/load beatthemarket :all-users root/User))
                 :networking       {:remote (net/fulcro-http-remote
                                              {:url                "/api"
                                               :request-middleware secured-request-middleware})
                                    :websocket (fws/fulcro-websocket-remote {})}}))

twashing02:03:28

And another way to send a query / transaction to my remote

(comp/transact! SPA `[(connect-socket {})])

twashing02:03:24

I’m still combing through the Fulcro Developers Guide. And obviously I’m missing something. But I put my initial attempts here. Any hints are welcome. https://github.com/twashing/beatthemarket.fulcro

Piotr Roterski10:03:39

@U0TU2M47R I would start by logging state-callback to see if there's any info there on why the connection fails. My initial guess would be that your CSRF is not properly configured - I see you tried skipping it but for me it was actually easier to set it up instead. You can do that by just adding :csrf-token js/fulcro_network_csrf_token key to fws/fulcro-websocket-remote's arg and removing :sente-options from server's fws/make-websockets

4
Piotr Roterski11:03:56

as for different ways of setting up the remotes, I'm not sure about the difference or if both are currently supported but A) worked for me with websockets

twashing04:03:01

Thanks @UHA0AQZ2M app/fulcro-app (A), worked for me too. As did your example for server pushes. push-handler and state-callback are also working. So my init now looks like so.

(defn ^:export init []

  (reset! app (app/fulcro-app {:client-did-mount (fn [beatthemarket]
                                                   (df/load beatthemarket :all-users root/User))

                               :remotes {:remote (net/fulcro-http-remote
                                                   {:url                "/api"
                                                    :request-middleware secured-request-middleware})
                                         :websocket (fws/fulcro-websocket-remote
                                                      {:csrf-token js/fulcro_network_csrf_token
                                                       :push-handler push-handler
                                                       :state-callback state-callback})}}))
  (start)

🎉 4
cjsauer18:03:36

Amazing what I’m able to do in a weekend playing with RAD. The database adapter + save/delete middleware alone are hugely powerful abstractions. fulcro clj

👍 16
Allen Dupras19:03:40

Hello, my server is closing out occasionally. I was wondering if anybody might have some insight as to why this may happen? I will leave the error message I receive as a reply to this thread. I am using CLJ on Windows which is in an alpha state, that is the only thing I can think of that could cause an issue like this.. I would really appreciate any ideas as to why the server could cut out, or if there is any more information you think could help in understanding the problem. 🙂

Allen Dupras19:03:33

ERROR:ERROR:  Unhandled REPL handler exception processing messageUnhandled REPL handler exception processing message  {{ERROR::op:op  closeclose, , :session:session  f5419aa6-1be2-4a14-8a5e-58a69f61195e9d98912c-6f9a-4cc1-82f1-f58ec8f61920}}
 Unhandled REPL handler exception processing .SocketException: Socket closed
        at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
        at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
        at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
        at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
        at nrepl.transport$bencode$fn__19123.invoke(transport.clj:116)
        at nrepl.transport.FnTransport.send(transport.clj:41)
        at nrepl.middleware.print$send_nonstreamed.invokeStatic(print.clj:159)
        at nrepl.middleware.print$send_nonstreamed.invoke(print.clj:138)
        at nrepl.middleware.print$printing_transport$reify__19530.send(print.clj:174)
        at nrepl.middleware.caught$caught_transport$reify__19565.send(caught.clj:58)
        at nrepl.middleware.session$close_session.invokeStatic(session.clj:232)
        at nrepl.middleware.session$close_session.invoke(session.clj:228)
        at nrepl.middleware.session$session$fn__19762.invoke(session.clj:269)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at nrepl.middleware.caught$wrap_caught$fn__19574.invoke(caught.clj:97)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at nrepl.middleware.print$wrap_print$fn__19541.invoke(print.clj:234)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at shadow.cljs.devtools.server.nrepl04$start$fn__20027.invoke(nrepl04.clj:386)
        at nrepl.server$handle_STAR_.invokeStatic(server.clj:18)
        at nrepl.server$handle_STAR_.invoke(server.clj:15)
        at nrepl.server$handle$fn__19799.invoke(server.clj:27)
        at clojure.core$binding_conveyor_fn$fn__5754.invoke(core.clj:2030)
        at clojure.lang.AFn.call(AFn.java:18)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:835)
.SocketException: Socket closed
        at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
        at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
        at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
        at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
        at nrepl.transport$bencode$fn__19123.invoke(transport.clj:116)
        at nrepl.transport.FnTransport.send(transport.clj:41)
        at nrepl.middleware.print$send_nonstreamed.invokeStatic(print.clj:159)
        at nrepl.middleware.print$send_nonstreamed.invoke(print.clj:138)
        at nrepl.middleware.print$printing_transport$reify__19530.send(print.clj:174)
        at nrepl.middleware.caught$caught_transport$reify__19565.send(caught.clj:58)
        at nrepl.middleware.session$close_session.invokeStatic(session.clj:232)
        at nrepl.middleware.session$close_session.invoke(session.clj:228)
        at nrepl.middleware.session$session$fn__19762.invoke(session.clj:269)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at nrepl.middleware.caught$wrap_caught$fn__19574.invoke(caught.clj:97)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at nrepl.middleware.print$wrap_print$fn__19541.invoke(print.clj:234)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at shadow.cljs.devtools.server.nrepl04$start$fn__20027.invoke(nrepl04.clj:386)
        at nrepl.server$handle_STAR_.invokeStatic(server.clj:18)
        at nrepl.server$handle_STAR_.invoke(server.clj:15)
        at nrepl.server$handle$fn__19799.invoke(server.clj:27)
        at clojure.core$binding_conveyor_fn$fn__5754.invoke(core.clj:2030)
        at clojure.lang.AFn.call(AFn.java:18)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:835)
 {:op close, :session 5a0888a1-0f0d-465f-8718-f3da301ddf61}
.SocketException: Socket closed
        at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
        at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
        at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
        at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
        at nrepl.transport$bencode$fn__19123.invoke(transport.clj:116)
        at nrepl.transport.FnTransport.send(transport.clj:41)
        at nrepl.middleware.print$send_nonstreamed.invokeStatic(print.clj:159)
        at nrepl.middleware.print$send_nonstreamed.invoke(print.clj:138)
        at nrepl.middleware.print$printing_transport$reify__19530.send(print.clj:174)
        at nrepl.middleware.caught$caught_transport$reify__19565.send(caught.clj:58)
        at nrepl.middleware.session$close_session.invokeStatic(session.clj:232)
        at nrepl.middleware.session$close_session.invoke(session.clj:228)
        at nrepl.middleware.session$session$fn__19762.invoke(session.clj:269)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at nrepl.middleware.caught$wrap_caught$fn__19574.invoke(caught.clj:97)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at nrepl.middleware.print$wrap_print$fn__19541.invoke(print.clj:234)
        at nrepl.middleware$wrap_conj_descriptor$fn__19187.invoke(middleware.clj:16)
        at shadow.cljs.devtools.server.nrepl04$start$fn__20027.invoke(nrepl04.clj:386)
        at nrepl.server$handle_STAR_.invokeStatic(server.clj:18)
        at nrepl.server$handle_STAR_.invoke(server.clj:15)
        at nrepl.server$handle$fn__19799.invoke(server.clj:27)
        at clojure.core$binding_conveyor_fn$fn__5754.invoke(core.clj:2030)
        at clojure.lang.AFn.call(AFn.java:18)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:835)

Allen Dupras19:03:27

Here is a link to the set up for CLJ on Windows.. https://github.com/clojure/tools.deps.alpha/wiki/clj-on-Windows I did end up follwing the instructions for "Install fails due to permission errors" and ran the command, Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

bbss22:03:42

I can't really see anything that rings a bell, but you might try asking this question in #nrepl or #clojure

Allen Dupras02:03:41

Thank you for giving it a look. I'll look into asking there as well.