This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-09-23
Channels
- # announcements (2)
- # architecture (16)
- # babashka (26)
- # beginners (106)
- # calva (173)
- # chlorine-clover (19)
- # cider (36)
- # cljdoc (4)
- # clojure (113)
- # clojure-berlin (3)
- # clojure-czech (3)
- # clojure-dev (5)
- # clojure-europe (37)
- # clojure-france (3)
- # clojure-hamburg (12)
- # clojure-italy (4)
- # clojure-nl (2)
- # clojure-uk (22)
- # clojurescript (38)
- # cryogen (10)
- # cursive (30)
- # data-science (7)
- # datascript (1)
- # datomic (13)
- # deps-new (7)
- # depstar (13)
- # duct (3)
- # events (2)
- # exercism (3)
- # fulcro (31)
- # graalvm (56)
- # graphql (1)
- # helix (5)
- # java (12)
- # jobs-discuss (19)
- # kaocha (13)
- # luminus (1)
- # lumo (4)
- # malli (5)
- # off-topic (17)
- # parinfer (1)
- # pathom (1)
- # pedestal (7)
- # rdf (10)
- # re-frame (1)
- # remote-jobs (7)
- # rum (6)
- # shadow-cljs (4)
- # tools-deps (41)
- # uncomplicate (3)
- # vim (14)
what is the best practice to keep a thread running inside a with-open
block
You'd have to wait for it to complete inside the with-open
block.
Otherwise, the resource the thread is using could be closed before it was done.
I'm aware of that, the question was more on which mechanism to use for the waiting
i'm spawning 2 threads inside the with-open
future
+ deref
?
There are lots of ways to do it. Hard to say what's best without knowing a bit more about exactly what you're doing.
i'm opening a stream, reading from it into a buffer on one thread, and the other is locked waiting for a signal to start processing from the buffer
future
/`deref` is a simple but fairly uncontrolled way to do it. Using Java threads directly or an executor or... all sorts of possibilities depending on how much control you wanted over this.
control in terms of?
these threads should be running in the background
with no interaction other than the data they're receiving and processing
(defn watch-collection [collection-name signal]
(println (str "Waiting for changes in " collection-name))
(with-open [watch-cursor (.watch (get-collection collection-name))]
(let [buffered-channel (async/chan (async/sliding-buffer 100))]
(map deref [(future (-> watch-cursor
.iterator
iterator-seq
(map #(async/>! buffered-channel %))))
(future (do (async/<! signal)
(loop []
(when-let [change (async/<! buffered-channel)]
(println change)
(recur)))))]))))
map
is lazy so that is not safe.
need a dorun after
Safer to use run!
there since you want the side-effects.
ah yes
(run! defer [...])
other than that
would something like the above work?
ah right
i'm calling (go (watch-collection
should the go
go inside the function body?
or use another mechanism
Consider letting the caller of this function supply a channel onto which changes are published
(I always cringe a bit when I see beginners trying to use core.async
👀 -- it is really not easy to learn/use and there are so many ways to shoot yourself in the foot with it...)
It's always felt like one of those "Here Be Dragons!" things in Clojure to me...
@ghadi but both the pushing and pulling from the channel are happening inside this function
@ghadi i'm opening a stream, reading from it into a buffer on one thread, and the other is locked waiting for a signal to start processing from the buffer
and I need to keep the threads alive inside the with-open
block
@seancorfield well I'm not one to shy away from a new challenge 🙂 that's why I came to clojure
@ghadi my current attempt
(defn watch-collection [collection-name signal]
(println "Start watching" collection-name)
(with-open [watch-cursor (.watch (get-collection collection-name))]
(let [buffered-channel (async/chan (async/sliding-buffer 1000))] ;buffer size might need tweaking
(run! #(async/<!! %) [(async/thread
(->> watch-cursor
.iterator
iterator-seq
(run! #(async/>!! buffered-channel %))))
(async/thread
(async/<!! signal)
(println (str "Waiting for changes in " collection-name))
(loop []
(when-let [change (async/<!! buffered-channel)]
(println collection-name change)
(recur))))]))))
I need help, For example, if my sequence is '((if a b)(if a c), and i want to find "if" and then "b" and want to return true because i found "b" with a "if", would i use some or filter?
(filter #(and (sequential? %) (= (first %) 'if) (= (second %) expr)) kb)
For example with this code, how would i change (second %) so it looks for the third index of a sequence?What do you mean by "third index of a sequence"?
Sequences are not indexed.
(if a b), i want to look at b
Instead of (second %)
you want (nth % 2)
Or (second (rest %))
would also work
I was doing (nth 2 %) the whole time
my bad
a lot of the functions that manipulate colls take them as the last arg
@ntrut you need to get used to doing things like (doc nth)
@joao.galrito No, sequence functions take the sequence as the last argument. Collection functions take the collection as the first argument.
oh ok
I still mix the two a bit
Most of the time, if the first argument is a collection, the function will have some specific guarantees about performance and/or return type.
If the last argument is a sequence, and you pass a collection, it will be coerced to a sequence first. For example (map inc [1 2 3])
will call seq
on the vector and then process it as a sequence.
(filter #(and (sequential? %) (= (first %) 'if) (= (second (rest %) ) 'b)) '(if a b))
returning nil, any ideas why?@seancorfield thanks for the help btw
i owe you guys
Because you're passing an expression instead of a list of expressions (again 🙂 )
filter
expecs ( (if a b) )
remember @ntrut?
it's calling sequential?
on 'if, then 'a, then 'b
Oh i see my mistake now
@ntrut Some suggested viewing for you https://www.youtube.com/watch?v=Qx0-pViyIDU and https://www.youtube.com/watch?v=FihU5JxmnBg -- two talks on debugging techniques by Stuart Halloway of Cognitect. I think you'll find they'll help you figure out some of the problems you are running into.
(you might also want to track down Stu's "REPL-Driven Development" talk as well)
Hi all. Any recommendations for simple websockets client and server implementations in clojure on the jvm for both client and server? Nothing fancy, no need for fallbacks etc. Needed as a way of linking two servers to exchange information where firewalls block other types of socket and bidirectional flow would be better than polling.
never used it, just saw it yesterday somewhere
not sure if that's what you need
Thanks I have looked at it but as I’m not an expert in this, on first inspection it has more functionality than I think I need. Of course, in its favour, it does seem to be the top hit on search - and is maintained, and the API looks good!
in the README there's also a couple other alternatives he recommends
Thanks. I’ve seen a variety of options including sente, direct http-kit usage - although the examples / docs use now deprecated methods, immutant, aleph, and I’ve looked at wrapping java libraries directly (e.g. Java-WebSocket) which actually I think was just added to sente for the java client bit. Up until then, it looks as if the main tooling was cljs for client and clj for server, because of the browser focus, but websockets now being used more and falling back to AJAX (as per sente) and starting connection using HTTP POST isn’t necessary for my use case. Hence just asking for advice. Thank you
Hi Mark,
I am very new to clojure, so this is not coming from any experience in production. But I am in the same boat as you. My experiments suggest that reitit
ring
and http-kit
can make for a fairly easy setup.
Thanks. I have an aleph client and server talking nicely to one another - but there’s a lot of new stuff/patterns to learn for me to fully understand how it’s working! My comparison is a golang based library : http://nhooyr.io/websocket
See https://aleph.io/examples/literate.html#aleph.examples.websocket But you can use sente as both a clj client and server as well.
Is there an any
type in lacinia that I can use while defining the schema?
when using Cursive, do I only get method name resolution if I import the corresponding classes?
Are there any simple examples of using reitit
, ring
and http-kit
where some routes are regular routes and a websocket route?
Not sure if you'll find an exact match, but the reitit repository provides plenty of examples: https://github.com/metosin/reitit/tree/master/examples
May be I am not seeing properly. But none of them are with websockets. Is reitit capable of routing websocket requests? Thank you.
haven't seen a public example, but we have been using reitit + ws since day1. Just mount a ws-endpoint into a route like you would do with any other routing lib, like compojure. Sente has examples of this
Thank you @U055NJ5CC. Can you please see the ws route below. I understand that the route is not set up to handle websocket connections. Also when I visit using the url using a regular browser window, I know it will fails. But I expect the httpkit/websocket?
to work as described on page
Would that now print out`false`. But instead I get an error saying: java.lang.IllegalArgumentException: No implementation of method: :websocket? of protocol: #'org.httpkit.server/Channel found for class: clojure.lang.PersistentHashMap
.
I am very new to clojure. Just trying to figure out what to use for webapps. Thank you.
My code:
(ns sampleapp
(:require
[reitit.ring :as ring]
[ring.middleware.params :as params]
[ring.middleware.multipart-params :as multparams]
[org.httpkit.server :as httpkit]
; [ring.adapter.jetty :as jetty]
; [ring.adapter.jetty9 :as jetty]
)
(:gen-class))
(defn wrap [handler val]
(fn [request]
(let [currval (get request :val [])]
(handler (assoc request :val (conj currval val))))))
(defn jerryhandler [req]
(println (str "Wrapped value: " (:val req)))
{:status 200
:headers {"Content-type" "text/plain"}
:body (str "Hello Jerry!!\nI got values " (:val req))})
(defn busterhandler [req]
(println (str "Parameters: " (:params req)))
{:status 200
:headers {"Content-type" "text/plain"}
:body "Hello Buster!!"})
(defn fileupload [req]
(println (str "File info: " (get-in req [:params "file"])))
(let [fileobj (get-in req [:params "file" :tempfile])
pathtofile (.getAbsolutePath fileobj)
contents (slurp fileobj)]
(println contents)
(println pathtofile)
{:status 200
:headers {"Content-type" "text/plain"}
:body "File uploaded..."})
)
(defn wshandler [req]
(println (httpkit/websocket? req))
{:status 200 :headers {"Content-type" "text/plain" :body "Not valid ws request..."}})
(def router
(ring/router
[["/hellojerry" {:get {:middleware [[wrap 1] [wrap 2]] :handler jerryhandler}}]
["/hellobuster" {:get (params/wrap-params busterhandler)}]
["/fileupload" {:post (multparams/wrap-multipart-params fileupload)}]
["/ws" wshandler]]
))
(def app
(ring/ring-handler
router
(constantly {:status 404 :body "Not found!"}))
)
(defn -main
[& args]
(httpkit/run-server app {:port 3000})
; (jetty/run-jetty app {:port 3000 :h2? true}))
)
I believe you need to pull out the channel linked to the request to get web-sockets with http-kit. There seems to be an example here: https://http-kit.github.io/server.html#channel
Thank you @U055NJ5CC. I believe the linked approach is deprecated. However, the example given here: https://http-kit.github.io/http-kit/org.httpkit.server.html#var-as-channel, works well. It appears that my mistake was using (httpkit/websocket?
, when, in fact, I was supposed to be using just (`:websocket?` ).
Does https://github.com/ptaoussanis/sente require using it for both server and client, or can you use it only on the server with standard Javascript websocket on the client? Thank you.
there are examples for connecting other types of infrastructure https://github.com/theasp/sente-nodejs-example
if you wanted a non-clojure or non-clojurescript participant, you'd have to conform to the message passing. It looks like they do have some emulation on web sockets to make up for web sockets short comings, so that may be a little tricky
What is a way that i can check if there is two "nots" in my sequence like this '(not (not b)), so therefore, if there is two "not" like this example.
(not(not a)) would be true
(not a) would be false
I would define a predicate that returned true if an expression was (not X)
and then you can do (and (has-not? expr) (has-not? (second expr)))
if you make has-not?
robust (check for sequential expr and then check first item is 'not
)
clojure collections are not falsey. in another dynamic language i might test for the presence or absence of a given value of an unknown type with if
. is there a conventional way to do this in clojure? so far i have (or (nil? x) (and (seqable? x) (empty? x)))
I think you can just do
(if (empty? x) ...)
that throws on integers
i'm reminded of the little schemer where the first question you always ask is atom?
...
indeed. what are you trying to do?
i'm writing a general purpose "is this var value missing?" predicate for use with values of an unknown type
maybe i shouldn't be doing that...
i could do additional work to bring through the type, i suppose
trying to define a universal "missing?" predicate always reminds of https://bugs.python.org/issue13936
ok, maybe i should rework such that i'm starting with a map where absence is represented by a missing key
that would be more clojuristic
basically, it's highly context dependent and it might be ok if you're defining the context, but it's trouble if you're defining the context for someone else and may be confusing for others to have to figure out what your definition of "missing" is
I much prefer clojure's approach compared to something like javascript:
> All values are truthy unless they are defined as https://developer.mozilla.org/en-US/docs/Glossary/Falsy (i.e., except for false
, 0
, -0
, `0n`, ""
, null
, undefined
, and NaN
).
🤢
should i use (seq x)
instead of (empty? x)
?