clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
Nazral 2021-02-23T04:34:05.055800Z

Is it safe to have a watcher send a message to the agent it is watching ?

2021-02-23T04:36:32.056800Z

It is as safe as recursion, you need a base case to avoid an infinite loop

1👍
Jeongsoo Lee 2021-02-23T05:09:35.057300Z

Whoa, this is so nice. Thanks for sharing!!

2021-02-23T05:15:31.058400Z

What people try to do with that sort of think is often not safe though

2021-02-23T05:17:15.060700Z

The action your watcher sends will get interleaved with other actions being concurrently sent

2021-02-23T05:17:32.061200Z

So you can easily make a race condition

Nazral 2021-02-23T05:41:19.061300Z

It's my worry. I have a bunch of futures that all send to the agent to append to a list. When the watcher detects that the list is longer than a certain size, I want it to process that list and reset the agent to the empty list

Nazral 2021-02-23T05:43:33.061400Z

If I am not mistaken, the messages received by the agent are handled sequentially, so there shouldn't be any race condition in this scenario, right? Can there be loss of data though?

Nazral 2021-02-23T05:46:12.061500Z

Would a better approach be to just drop the part of the vector contained in the agent that I used rather than resetting the agent?

2021-02-23T17:52:24.084800Z

this sounds like a better fit for a queue, with writers giving it items, and a single reader that builds up a buffer and periodically processes the whole buffer

2021-02-23T17:52:35.085Z

unless the senders need to see the pending buffer

Nazral 2021-02-24T06:52:45.113900Z

It is what I ended up doing, you are right it is a much better (and simpler) solution

jumar 2021-02-23T07:13:42.061900Z

The iteration function looks useful. Here's my attempt to use it fetch repositories with installed github app: https://github.com/jumarko/clojure-experiments/blob/master/src/clojure_experiments/collections.clj#L434-L449

(let [my-installation-token "generate-jwt-and-get-installation-access-token-from-that"
          api (fn fetch-page [page-url]
                (log/debug "Fetch all installation repositories - page: " page-url)
                (let [response (http/get page-url {:accept "application/vnd.github.v3+json"
                                                   :headers {"Authorization" (str "Bearer " my-installation-token)}
                                                   :as :json
                                                   :query-params {:per_page "100"}})]
                  (log/debug "Fetch all installation repositories - page FINISHED: " page-url)
                  response))
          api-reducible (iteration api
                                   :kf #(get-in % [:links :next :href])
                                   :vf #(-> % :body :repositories)
                                   :initk "<https://api.github.com/installation/repositories>")]
      ;; flatten the pages
      (into [] cat api-reducible))

javahippie 2021-02-23T08:28:37.066Z

I was wondering about the best approach for logging in a library I am building. I already saw this great post: https://lambdaisland.com/blog/2020-06-12-logging-in-clojure-making-sense-of-the-mess For libraries, my thoughts are that clojure.tools.logging would be the best approach, as consumers of the library could change the clojure.tools.logging.factory flag to decide if the library should log to slf4j, apache commons, log4j, log4j2 or java.util.logging, so I won’t force them to pull some bridge-libraries into their deps. What are your thoughts on this?

mpenet 2021-02-23T08:41:13.066600Z

it's one of those things were I personally prefer just relying on raw logback

mpenet 2021-02-23T08:41:20.066900Z

+ tools logging

mpenet 2021-02-23T08:41:45.067400Z

sure it's an xml file to deal with, but at least there's no indirection and it's quite straightforward

dharrigan 2021-02-23T08:44:33.067900Z

Yeah, I like clojure tools logging too

dharrigan 2021-02-23T08:44:35.068100Z

simple to use

1👍
mpenet 2021-02-23T08:46:08.068600Z

the only reason to use a third party lib would be if you want compat clj/cljs I would guess

mpenet 2021-02-23T08:46:30.069300Z

but I am not expert on cljs so I don't know the details

javahippie 2021-02-23T08:46:39.069500Z

Good point, but it won’t be targeted at cljs

javahippie 2021-02-23T08:48:43.071200Z

Regarding logback: I wouldn’t ship it with the library, as it is a logging backend, I believe

javahippie 2021-02-23T09:02:49.071900Z

Thanks!

Helins 2021-02-23T09:06:13.073900Z

I get an illegal reflective access warning when setting access on the private address field in java.nio.Buffer (java 11). Usually it goes away with type hinting but here, no matter what I hint, it doesn't.

(def ^:no-doc ^java.lang.reflect.Field -field-address

  (doto (.getDeclaredField Buffer
                           "address")
    (.setAccessible true)))
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by helins.binf.native$fn__1426 to field java.nio.Buffer.address

Helins 2021-02-24T15:35:58.132600Z

Well in a way, you are right. In another way... come on, let's make everything public and let people hack in peace 😛

1🙃
vemv 2021-02-23T10:00:38.074600Z

You are doing explicit reflection (`.getDeclaredField`) and getting a warning accordingly

2021-02-23T12:44:18.075700Z

When you’re proxying a class with clojure proxy is it possible to typehint protected methods on this?

2021-02-23T12:45:41.076500Z

I’ve wrapped (let [^MyProxyClass this this ret (.protectedMethod this) ,,,) over it and it still warns

Jamie Rumbelow 2021-02-23T13:04:02.078500Z

Has anybody ever used something like redis as a substrate for a core.async channel? I'd like to be able to use the same semantics as channels across multiple processes / machines

alexmiller 2021-02-23T13:10:21.079100Z

backpressure is a hard thing to implement over the network

Helins 2021-02-23T13:51:42.079200Z

Is it forbidden in Java now? From what I read, people still do that and nobody seem to complain. I thought I might be doing something wrong or maybe for some reasons it could be somehow Clojure related (didn't quite follow how Clojure blends with modules).

vemv 2021-02-23T14:14:16.079400Z

People tend to try supressing warnings without trying to understand those first :) I don't have the authoritative source, but it's quite clear that newer JDKs want to enforce the Java privacy mechanism, forbidding things like setAccessible. Surely other reflection APIs will remain perfectly fine to use

Jamie Rumbelow 2021-02-23T14:45:04.079900Z

yes... I was afraid there'd be some theoretical reason why not!

Jamie Rumbelow 2021-02-23T14:45:06.080100Z

thanks 🙂

2021-02-23T16:36:08.083700Z

tcp includes backpressure, but it can be non-obvious, gets weird when you aren't communicating directly, and lots of apis do a bad job of exposing it

2021-02-23T16:37:37.084200Z

https://github.com/hiredman/roundabout/blob/master/src/com/manigfeald/roundabout.cljc is an example of how you can communicate back pressure

Helins 2021-02-23T17:24:23.084500Z

Yes but since accessing private fields is so common in plenty of big Java libs... Are they really going to fully remove picking at private fields?!

2021-02-23T17:52:24.084800Z

this sounds like a better fit for a queue, with writers giving it items, and a single reader that builds up a buffer and periodically processes the whole buffer

2021-02-23T17:52:35.085Z

unless the senders need to see the pending buffer

telekid 2021-02-23T18:24:27.085200Z

this makes some intuitive sense, but I’d love to understand why more formally – do you know of any good reads on the topic?

vemv 2021-02-23T19:24:16.085400Z

I'm not really qualified to do an assessment on that, but personally it SGTM. Privacy is there for a reason and can be solved in alternative ways (e.g. forking a dependency)

roklenarcic 2021-02-23T19:51:28.085600Z

A server using async connector can theoretically handle a million connections, not read from them and slowly process them, stalling clients that are waiting for results, which is backpressure.

roklenarcic 2021-02-23T19:58:12.087900Z

Has anyone tried to implement a sandboxed Clojure interpreter? I’ve looked at SCI and it’s a nice interpreter, but I’m afraid of two things: • infinitely long execution (I can solve this by timing the execution and calling Thread/stop on the executing thread from a controller thread) • infinite memory allocation (I haven’t found a way to prevent this)

alexmiller 2021-02-23T20:00:09.089Z

Java security is built into the jvm and can do a lot of things. there is clojail as well, which puts some additional clojure restrictions over that

borkdude 2021-02-23T20:00:46.089900Z

I have used clojail to run snippets from clojuredocs to verify specs in speculative, using this updated fork: https://github.com/borkdude/clojail (been a while)

ghadi 2021-02-23T20:01:24.091Z

can also sandbox at an outer layer using something like Firecracker, the VM technology that AWS uses for Lambdas

ghadi 2021-02-23T20:01:39.091200Z

depending on the use-case

borkdude 2021-02-23T20:02:03.091600Z

you can also run a dedicated JVM for the sandboxes and set -Xmx maybe?

ghadi 2021-02-23T20:02:38.091900Z

...what is the use-case?

ghadi 2021-02-23T20:04:30.093400Z

supporting user-submitted scripts in a multitenant runtime (a la Jenkins extensions)? implementing something like an interactive tutorial site (a la http://repl.it or 4clojure)? ?

roklenarcic 2021-02-23T20:05:26.094300Z

basically in a mini-game I’d like to have players submit their own routines in clojure which would operate in a very closed world

roklenarcic 2021-02-23T20:05:52.094800Z

unfortunately it’s very easy to nuke the server by saying (last (range 10000000000))

borkdude 2021-02-23T20:07:42.095900Z

@roklenarcic this is something I have thought about for a while in sci and I haven't been able to come up with a satisfactory solution - it should be solved at a deeper level, like you say, e.g. use a timeout with Thread#stop or even an lower level

jumar 2021-02-23T20:21:31.098200Z

The best approach is usually run those as standalone processes. For Clojure this might mean a non-trivial overhead of course, especially in terms of memory usage and also the execution time (maybe GraalVM could help with this) it depends on how much resources do you want to give them and the latency you can tolerate. Here's a related question: https://stackoverflow.com/questions/6599985/is-there-a-way-to-put-maximum-memory-usage-limit-on-each-thread-in-java#:~:text=To%20place%20a%20limit%20on,memory%20each%20thread%20is%20using.

borkdude 2021-02-23T20:33:15.099200Z

If you go that road, maybe setting it up as a CGI-ish solution works. I bet they have solved similar problems there.

borkdude 2021-02-23T20:33:42.099300Z

https://github.com/eccentric-j/clj-cgi-example

dpsutton 2021-02-23T20:35:30.100300Z

just randomly, would it be possible to use clojure's asm to create classes that defeat what clojail is attempting to do?

borkdude 2021-02-23T20:40:09.100600Z

@dpsutton I guess you can try that out in 4clojure

2021-02-23T21:16:14.102400Z

It would be surprising if clojail could not be compromised in some way. I don’t think it was submitted to any kind of sustained attack effort by experts before

devn 2021-03-02T01:25:41.399600Z

well, aside from a lot of us in IRC trying to break it all the time for years, I agree 😄

borkdude 2021-02-23T21:24:12.103100Z

This is why I like offering such solutions in browsers. If people mess up, it's their problem ;)

sova-soars-the-sora 2021-02-23T23:37:15.103800Z

If I were to make a Peer-to-peer application in Clojure, is the state-of-the-art the java interop with pastry?

lukasz 2021-02-23T23:45:11.103900Z

jGroups perhaps? http://www.jgroups.org - was pretty pleasant to use via the interop

1🐝1🎉