Fork me on GitHub
#clojurescript
<
2020-06-27
>
benny02:06:45

not sure of a better place to ask this, but any ideas why my sente client won’t connect?

(defn start-client! []
  (let [client (sente/make-channel-socket-client!
                "/ws"
                {:host "10.0.2.2"
                 :port 8888})]

    (def chsk       (:chsk client))
    (def ch-chsk    (:ch-recv client))
    (def chsk-send! (:send-fn client))
    (def chsk-state (:state client))))

phronmophobic03:06:55

what kind of error are you getting?

benny03:06:53

client.core> @chsk-state
{:type :auto, :open? false, :ever-opened? false, :csrf-token {:host "192.168.1.51", :port 8888}, :last-ws-error {:udt 1593226359007, :ev #object[Event [object Object]]}, :last-close {:udt 1593226359008, :reason :downgrading-ws-to-ajax}, :last-ws-close {:udt 1593226359082, :ev #object[Event [object Object]], :clean? nil, :code nil, :reason nil}}

benny03:06:23

client.core> (start-client!)
#object[cljs.core.Atom {:val {:type :auto, :open? false, :ever-opened? false, :csrf-token {:host "192.168.1.51", :port 8888}}}]

benny03:06:50

as you can see i’m trying different IPs as my runtime is in an emulator

benny03:06:15

based on the network traffic, it looks like my url is being constructed all weird, in the inspector, its trying to connect with ws:///ws?client-id={guid}&csrf-token=….

benny03:06:41

shouldn’t it be ws:///10.0.2.2:8888?client...

phronmophobic03:06:38

what kind of emulator? android?

phronmophobic03:06:19

it should be ...

phronmophobic03:06:47

where are you seeing it show ws:///ws?client-id={guid}&csrf-token=…. ?

benny03:06:54

in the emulator

benny03:06:07

to answer your question, it’s an android emulator

phronmophobic03:06:14

where in the emulator?

benny03:06:30

it has a built in inspector

benny03:06:16

i changed it now and it’s actually sending requests

benny03:06:38

switched to this

(let [client (sente/make-channel-socket-client!
                "10.0.2.2:8888/ws"
                {:host "10.0.2.2"
                 :port 8888})]

benny03:06:50

but it’s still not connecting

phronmophobic03:06:50

i'm assuming that if you do nc 127.0.0.1 8888 on your computer (not in the emulator), it connects to something?

phronmophobic03:06:48

do you get any exceptions?

benny03:06:15

no exceptions

benny03:06:40

nc 127.0.0.1 8888 hangs

phronmophobic03:06:08

it's just connecting and waiting

phronmophobic03:06:22

which means there's at least a server listening on that port

phronmophobic03:06:57

it's weird that there's no exceptions

phronmophobic03:06:32

if you run nc -l 8889 and then try to connect on port 8889, does anything show up in the terminal running nc -l 8889?

benny03:06:40

i guess i’m not sure where to find the exception even honestly

phronmophobic03:06:07

oh, so there might be an exception, but just being ignored somewhere

benny03:06:29

when i run start client it returns me the atom as expected

benny03:06:47

the atom has information in it which seems to relate to an exception but i can’t get it out

benny03:06:56

{:type :auto, :open? false, :ever-opened? false, :csrf-token {:type :ws, :host "10.0.2.2", :port 8888}, :last-ws-error {:udt 1593228475869, :ev #object[Event [object Object]]}, :last-close {:udt 1593228475869, :reason :downgrading-ws-to-ajax}, :last-ws-close {:udt 1593228476043, :ev #object[Event [object Object]], :clean? nil, :code nil, :reason nil}, :udt-next-reconnect 1593228498545}

benny03:06:18

I would think I could do (get-in @chsk-state [:last-ws-error :ev])

benny03:06:38

but that just returns an object and i can’t use js->clj on it

benny03:06:24

it definitely keeps trying to connect, i threw in debugging on the server and the requests are coming through, but nothing is happening

benny03:06:32

maybe it’s the server side not doing something right?

phronmophobic03:06:45

yea, if you're seeing the requests coming through

benny03:06:22

(let [chsk-server (sente/make-channel-socket-server! (get-sch-adapter) {})

      {:keys [ch-recv send-fn connected-uids
              ajax-post-fn ajax-get-or-ws-handshake-fn]} chsk-server]

  ;; (def ring-ajax-post                ajax-post-fn)
  (def ring-ajax-get-or-ws-handshake ajax-get-or-ws-handshake-fn)
  (def ch-chsk                       ch-recv) ; ChannelSocket's receive channel
  (def chsk-send!                    send-fn) ; ChannelSocket's send API fn
  (def connected-uids                connected-uids)) ; Watchable, read-only atom

(defmulti msg-handler :id)

(defmethod msg-handler :test [event]
  (prn event))

(defmethod msg-handler :notification/register-device-token [{:keys [uid ?data] :as event}]
  (prn "Received device token register request: " event))

(defn wrap-msg-handler
  [event]
  (try
    (msg-handler event)
    (catch Exception e
      (timbre/error e))))

(defonce router_ (atom nil))
(defn stop-router! [] (when-let [stop-fn @router_] (stop-fn)))
(defn start-router! []
  (stop-router!)
  (reset! router_
          (sente/start-server-chsk-router!
           ch-chsk
           wrap-msg-handler)))

benny03:06:42

that’s my ws server

phronmophobic03:06:33

you might be able to use:

(defn obj->clj [x]
  (reduce (fn [r k] (assoc r k (gobject/get x k)))
          {}
          (js-keys x)))
to convert the event to a clj map

phronmophobic03:06:05

nothing seems off about the server, but I can't see that it's sending a message back to the client at any point

benny03:06:24

yeah it doesn’t seem to be sending a response

benny03:06:30

it’s getting it, and at the right path too

benny03:06:43

i’ve never seen gobject before, where do i find that

phronmophobic03:06:29

oops, you'll need to require [goog.object :as gobject] to use that

👍 3
phronmophobic03:06:20

for some reason, js->clj will only convert js objects that return true for (identical? (type x) js/Object)

benny03:06:56

> {“message” “Expected HTTP 101 response but was ‘403 Forbidden’“, “eventPhase” 0, “cancelable” false, “currentTarget” nil, “BUBBLING_PHASE” 3, “composed” false, “cancelBubble” false, “isTrusted” false, “returnValue” true, “CAPTURING_PHASE” 1, “AT_TARGET” 2, “initEvent” #object[initEvent], “preventDefault” #object[preventDefault], “timeStamp” 1593228475869, “NONE” 0, “stopPropagation” #object[stopPropagation], “bubbles” false, “type” “error”, “stopImmediatePropagation” #object[stopImmediatePropagation], “target” #object[WebSocket [object Object]], “srcElement” #object[WebSocket [object Object]], “defaultPrevented” false, “composedPath” #object[composedPath]}

phronmophobic03:06:37

I did not expect that

benny03:06:13

lol me neither, i don’t have any authentication but it leads me into my handlers

phronmophobic03:06:03

hmmm, there's csrf token in the log you showed earlier. I wonder if the fact that the hostname is originally 10.0.2.2 and there's the emulator doing the NAT stuff is causing issues

benny03:06:00

now we’re getting somewhere, it was definitely me…

(GET "/ws" [req] (ws/ring-ajax-get-or-ws-handshake req))
was
(GET "/ws" [req] ws/ring-ajax-get-or-ws-handshake)

benny03:06:27

i was looking in the wrong places 🙂

benny03:06:46

thank you for helping unwrap that object, that was the key!

phronmophobic03:06:54

that's always where the bug hide!

benny03:06:20

thank you again! i’m on a roll now!

sheepy 3
William Steinberg03:06:30

Am looking for a guide to help me get started with ClojureScript and rapidly be productive. Will pay for the service. Need only a couple of hours of help. Anyone interested? <mailto:[email protected]|[email protected]> Need to see an example where JavaScript code calls a ClojureScript function, and a ClojureScript function calls a JavaScript library/file.

jaide08:06:07

Do you write specs for your reagent view functions?

David Pham09:06:29

I think my most frequent bug is when JS interop becomes nil. I would use spec to check if the first element is not nil and if it is the interop :> check that the second element is not nil. Does it make sense? I am struggling to test views as well, I like the kamera solution but never had time to dig in into it.

Tim09:06:41

Hello guys! Has somebody updated to Big Sur? I have a problem with shadow-cljs after update:

shadow-cljs - running: lein run -m shadow.cljs.cli --npm watch app
Syntax error (UnsatisfiedLinkError) compiling at (/private/var/folders/0x/d5945v_9115481gx0v74y87r0000gn/T/form-init6521250380523574093.clj:1:125).
Unable to load library 'Carbon': dlopen(libCarbon.dylib, 9): image not found

Tim06:06:26

Hey @thheller! I’ve dived a little deeper here and found an interesting thing. It seems that in new macOS the Carbon.framework is broken (or most likely deleted). Its been deprecated for a while and now /System/Library/Frameworks/Carbon.framework is only 18 megabytes instead of 138mb which it was before. So, all the libraries using it are broken on Big Sur. Including shadow-cljs, figwheel-main and everything that depends on https://github.com/gjoseph/BarbaryWatchService

thheller07:06:55

ah doh. I'll remove that then I guess.

thheller07:06:27

you can try setting :fs-watch {:hawk false} in shadow-cljs.edn. maybe it loads then? hawk should only be loaded conditionally anyways and is only used on macos

👍 3
Tim07:06:57

Oh, you’ve saved my day! Thank you very much, it worked 🙂

thheller09:06:39

@tim269 probably a java error. try reinstalling java?

Tim09:06:44

@thheller I’ll try that, thanks

William Steinberg13:06:10

How to configure project.clj to include /path/to/undo-manager.js, and then how to access creating an instance of UndoManager and then calling hasUndo() method from ClojureScript.

thheller14:06:13

otherwise working with JS files in CLJS is a bit clunky

benny15:06:11

still working on my sente client, the two sides can connect, and the server receives messages from the client if sent any, but when i try to send messages to the client, messages don’t show up unless messages have been sent before my router is started. any messages sent after my router starts never print. any ideas?

(defn event-msg-handler
  "Wraps `-event-msg-handler` with logging, error catching, etc."
  [{:as ev-msg :keys [id ?data event]}]
  (prn "here")
  (prn ev-msg))

(defonce router_ (atom nil))
(defn stop-router! [] (when-let [stop-fn @router_] (stop-fn)))
(defn start-router! []
  (stop-router!)
  (reset! router_
          (sente/start-client-chsk-router!
           ch-chsk event-msg-handler)))

benny17:06:45

ultimately it seems like my async channel is not getting flushed somewhere or the channel is shutting down, i can’t tell. when i send my message server side via (chsk-send! "abc" [:notification/device-registered "abc"] {:flush? true}) and I’m not hooked up to the channel yet client-side, once i do spin up the sente router, it spits it and any other messages queued up out, but any additional messages are lost

phronmophobic17:06:42

is the router a server side thing or a client side thing?

benny18:06:13

I have one both sides but the client is the one that doesn't receive the event

benny18:06:20

the server router does

phronmophobic18:06:16

how are you seeing the messages before your router is started?

benny18:06:30

I'm running the above send from the server repl

phronmophobic18:06:42

> it spits it and any other messages queued up out, but any additional messages are lost what is "it"? are you seeing any messages on the client, or just sometimes?

benny19:06:42

sorry, my repl

phronmophobic19:06:01

how is the repl printing the messages?

benny20:06:16

that’s the top half of the block in the op

phronmophobic20:06:50

i don't see any issues

phronmophobic20:06:20

what's the client environment like?

phronmophobic20:06:32

is it on android within a browser?

phronmophobic20:06:39

or within an android app running javascript?

phronmophobic20:06:14

if possible, I would try running the javascript on your local computer in Chrome or Firefox since they have pretty good inspectors

phronmophobic20:06:26

that can give you more information about what's happening with the websocket connection itself

benny20:06:08

what’s the quickest way to spin up a browser-based repl?

benny20:06:19

it is android via rn

phronmophobic20:06:20

I haven't used a cljs repl in a while, so I'm not sure

phronmophobic20:06:31

prn will print to the browser console though

phronmophobic20:06:18

and both chrome and firefox has inspectors that show websocket connections which includes their state and the messages that have been sent/received

benny20:06:04

prn is printing to my repl though

phronmophobic20:06:19

from the browser? then it seems like you're all set

benny21:06:42

no, that’s what i mean by “it spitting out”, it works and prints to my repl, but only when i build up a queue then connect from the client

benny21:06:11

if i connect from the client, then send a message from the server, the message never shows up client side

benny04:06:07

tried it again in a browser-based repl and got the same results

benny04:06:20

i only see messages when i start the router

phronmophobic04:06:55

what do you see in the inspector?

phronmophobic04:06:09

are the messages arriving? does the connection get closed?

benny06:06:28

looks like it could be as simple as I don't know my way around aaync well enough yet. it seems like the call to send is usually inside a go block but I tried my own attempt by literally just running the same send command inside a go from the server repl but it still didn't come through

benny06:06:16

it doesn't appear the messages are arriving

benny06:06:06

if you could help me write what a call using a go block from the repl would look like, I'm stumped!

phronmophobic06:06:43

code inside a go block will just get executed in a green thread

phronmophobic06:06:24

i'm not sure if send has a return value, but you should be able to run it outside of a go block without issue

benny14:06:11

you can see more clearly the behavior of what’s happening here in the browser. the server starts talking immediately doing a handshake, and a few pings, but when i start the client router, nothing else is received from the server. it’s the same story for as long as the client’s router is up.

benny02:06:11

figured it out….it was the version of async…the sente version is seemingly incompatible with newer versions of async

phronmophobic05:06:31

that's a pretty tough bug. glad you figured out a solution!

benny13:06:14

thanks for the support @U7RJTCH6J!

gekkostate21:06:44

Hi all! I was wondering if someone has implemented a mime-type check? Before the user uploads something to my S3 server, I would like to check if the file is valid or not. I was thinking about porting https://stackoverflow.com/a/29672957/681159 to cljs but was wondering if there’s another way. Thanks for your time!

Tim06:06:26

Hey @thheller! I’ve dived a little deeper here and found an interesting thing. It seems that in new macOS the Carbon.framework is broken (or most likely deleted). Its been deprecated for a while and now /System/Library/Frameworks/Carbon.framework is only 18 megabytes instead of 138mb which it was before. So, all the libraries using it are broken on Big Sur. Including shadow-cljs, figwheel-main and everything that depends on https://github.com/gjoseph/BarbaryWatchService