Managing and finding variables in Clojure REPL - clojure

I was looking at https://github.com/juxt/dirwatch library. The example from the front page is:
(require '[juxt.dirwatch :refer (watch-dir)])
(watch-dir println (clojure.java.io/file "/tmp"))
That works fine. Let's say the above is executed in REPL:
user=> (watch-dir println (clojure.java.io/file "/tmp"))
#<Agent#16824c93: #<LinuxWatchService sun.nio.fs.LinuxWatchService#17ece9ac>>
Now, I have an agent that will print events when I modify files in /tmp:
{:file #<File /tmp/1>, :count 1, :action :modify}
so all is fine.
I know I can reference the agent by using previous expression references (*1, *2 and *3). However, I don't know how to, without restarting the REPL itself:
Unbind an implicit var created like this - i.e. how to remove the binding completely, so that agent gets GCed and stops working
Access it in case I lost it in cases where I did not bind it, such as the above. If I'm not mistaken, in REPL only the last three results are available (*3 is, but *4 and further are not), at least per http://clojure.org/repl_and_main
Any suggestions?

Did you take a look at the code? The documentation to watch-dir has this: "The watcher returned by this function is a resource which
should be closed with close-watcher."
Looking at the code, it watch-dir uses send-off, which "Dispatch a potentially blocking action to an agent. Returns the agent immediately.". In other words, to address your first question, there is no implicit var created. If you want to get rid of the agent, you should bind the returned agent to some var and call close-watcher on it afterwards.
To address the second question, take a look at the canonical documentation for agents. Specifically, you can call shutdown-agents, which will shut-down the thread pool (potentially killing other agents as well).

Related

Why does this re-frame command only work when the browser is on a specific local host address? Shouldn't it be just an interface to the the database?

I have been using Clojure, ClojureScript, lein, shadow-cljs, Emacs, and CIDER to work on a Clojure/ClojureScript dynamic web app project.
Usually, I build the project executing command cider-jack-in-cljs in Emacs, choosing shadow-cljs, then shadow for REPL type, and, finally, app for building option.
It works fine. I can watch changes on the UI on localhost:3005.
There is something weird though that I do not understand (take into consideration that I am new to the Clojure stack).
On the REPL I can do:
cljs.user> #(re-frame.core/subscribe [:the-selections])
{:firm "cb08795f-378b-4eb0-9404-ad83b83a8474",
:active-client "Random-client",
:active-atb "c6193c35-bf91-4711-8523-d905bd7f0a03"}
The keywords inserted by me and retrieved by the REPL are related to the project.
My doubt is about the fact that this only works if the browser is in a specific page (address). Authentication here is not relevant.
On http://localhost:3005/link/random-numbers-asidadbsadkfbajhksdbf9283492374, it works:
cljs.user> #(re-frame.core/subscribe [:the-selections])
{:firm "cb08795f-378b-4eb0-9404-ad83b83a8474",
:active-client "Random-client",
:active-atb "c6193c35-bf91-4711-8523-d905bd7f0a03"}
But, if change the address bar on the Chrome browser to another valid path being properly rendered by the browser: http://localhost:3005/another-path.
And if try the same command, surprisingly the REPL retrieves nil:
cljs.user> #(re-frame.core/subscribe [:the-selections])
nil
Even after authentication and even if the browser address is inside the home page, the command above does not work. It only works after the address is on a specific page.
In addition, based on #ThomasHeller's comment, it seems to be relevant to post how :the-selections is defined. I am not sure this is the root of the definition, but it is my best bet:
(rf/reg-sub
:the-selections
;; Only returns something if all :firm, :active-client, and
;; :active-atb are present. :raw-selections defined in
;; selections.cljs omits validation if (rarely) needed. selections
;; are only stored locally in re-frame's app-db, not in firebase,
;; like :the-client and :the-atb. Minor selections components which
;; are not part of the validation are :active-account and :active-je
(fn [_q _d]
(rf/subscribe [:raw-selections]))
(fn [selections _q]
(tc-selections/valid-selections selections)))
This behavior intrigues me. Isn't a re-frame.core/subscribe an interface to the database?
According to re-frame's documentation:
When a View Function uses a subscription, like this (subscribe [:something :needed]), the sub-graph of nodes needed to service that subscription is created. The necessary sub-graph will "grow backwards" from the View Function all the way to app-db.
If so, why should the address bar on the browser matter after proper build and authentication?
This is impossible to answer without knowing how :the-selections is defined.
However, a guess would be that the value is provided by the "router". It basically takes the URL and puts some data related to it into the app-db. In case of URIs starting with /link it may be creating the necessary data, while others don't.

Clojure - core.async vary-meta

I have seen code like this in ClojureScript repeatedly :
(apply async/put! port (vary-meta val assoc :key *val*) args)
I don't understand the repeated use of vary-meta along with async/put!, why is it needed ?
Seen for instance in CircleCI frontend code and ninjudd/eventual.
Basically they are using core.async as an async event system, and they are annotating the values they use for events with an id in the meta data.
In the case of the CircleCI architecture, one of the things they are using this for is to update the state of an input control when the result of whatever action it controlled completes (or errors or whatever).
You can see how this works by checking out the forms namespace. The uuid instances are created on line 49 in wrap-managed-button-handler. And you can find examples of the event handling code that calls release-button! in the frontend.controls namespace.
When the event handlers handle an event, they bind frontend.async/*uuid* to the uuid associated with the event value so that the relevant multimethod can access it. You can see this in frontend.core.
p.s. I tried to include more links but I don't have enough reputation with stackoverflow.

clojure future vs delay

I have been reading through Programming in Clojure and found thing text
(defn get-document [id]
; ... do some work to retrieve the identified document's metadata ... {:url "http://www.mozilla.org/about/manifesto.en.html"
:title "The Mozilla Manifesto"
:mime "text/html"
:content (delay (slurp "http://www.mozilla.org/about/manifesto.en.html"))})
if callers are likely to always require that data, the change of replacing future over delay can prove to be a significant improvement in throughput.
I didn't got this part completely, can someone please explain a bit.
Simple answer future is background execution of body, delay is on-demand execution of body. Example: if you have list of 100 delay-ed code, and trying to loop through it - code will block while evaluating each list item (e.g. doing HTTP request) and first iteration will be slow. Same with future-d code - it'll evaluate all content in background thread(s) and results will be available instantly in your loop.
Rule of thumb - if there is good chance that some or most of content will not be needed at all - use delay, otherwise use future.
https://clojuredocs.org/clojure.core/delay
https://clojuredocs.org/clojure.core/future
future creates a Future and schedules it for execution immediately, therefore calling
(get-document "id")
will cause a future to be created which fetches the document immediately and then caches the result in the future.
In contrast, delay creates a lazy operation which will not be executed until dereferenced. In this case, calling
(get-document "id")
will not cause the document to be fetched. This will only happen when dereferencing e.g.
(let [{:keys [content]} (get-document "id")]
(println #content))

Clojure - connections at compile time

I have a rabbitMQ connection that seems to be started at compile time (when I type lein compile) and then blocks the building of my project. Here are more details on the problem. Let us say this is the clojure file bla_test.clj
(import (com.rabbitmq.client ConnectionFactory Connection Channel QueueingConsumer))
;; And then we have to translate the equivalent java hello world program using
;; Clojure's excellent interop.
;; It feels very strange writing this sort of ceremony-oriented imperative code
;; in Clojure:
;; Make a connection factory on the local host
(def connection-factory
(doto (ConnectionFactory.)
(.setHost "localhost")))
;; and get it to make you a connection
(def connection (.newConnection connection-factory))
;; get that to make you a channel
(def channel (. connection createChannel))
;;HERE I WOULD LIKE TO USE THE SAME CONNECTION AND THE SAME CHANNEL INSTANCE AS OFTEN AS
;; I LIKE
(dotimes [ i 10 ]
(. channel basicPublish "" "hello" nil (. (format "Hello World! (%d)" i) getBytes)))
The clojure file above is part of a bigger clojure program that I build using lein. My problem is that when I compile with "lein compile", a connection is done because of the line (def connection (.newConnection connection-factory)) and then the compilation is stopped! How can I avoid this? Is there a way to compile without building connection? How can I manage to use the same instance of channel over several calls coming from external components?
Any help would be appreciated.
Regards,
Horace
The Clojure compiler must evaluate all top-level forms, because it can be required to run arbitrary code when expanding calls to macros.
The usual solution to issues like the one you describe is to define a top-level Var holding an object of a dereferenceable type, for example an atom or a promise, and have an initialization function provide the value at runtime. (You could also use a delay and specify the value inline; this is less flexible, since it makes it more difficult to use a different value for testing etc.)

How should carmine's wcar macro be used?

I'm confused by how calls with carmine should be done. I found the wcar macro described in carmine's docs:
(defmacro wcar [& body] `(car/with-conn pool spec-server1 ~#body))
Do I really have to call wcar every time I want to talk to redis in addition to the redis command? Or can I just call it once at the beginning? If so how?
This is what some code with tavisrudd's redis library looked like (from my toy url shortener project's testsuite):
(deftest test_shorten_doesnt_exist_create_new_next
(redis/with-server test-server
(redis/set "url_counter" 51)
(shorten test-url)
(is (= "1g" (redis/get (str "urls|" test-url))))
(is (= test-url (redis/get "shorts|1g")))))
And now I can only get it working with carmine by writing it like this:
(deftest test_shorten_doesnt_exist_create_new_next
(wcar (car/set "url_counter" 51))
(shorten test-url)
(is (= "1g" (wcar (car/get (str "urls|" test-url)))))
(is (= test-url (wcar (car/get "shorts|1g")))))
So what's the right way of using it and what underlying concept am I not getting?
Dan's explanation is correct.
Carmine uses response pipelining by default, whereas redis-clojure requires you to ask for pipelining when you want it (using the pipeline macro).
The main reason you'd want pipelining is for performance. Redis is so fast that the bottleneck in using it is often the time it takes for the request+response to travel over the network.
Clojure destructuring provides a convenient way of dealing with the pipelined response, but it does require writing your code differently to redis-clojure. The way I'd write your example is something like this (I'm assuming your shorten fn has side effects and needs to be called before the GETs):
(deftest test_shorten_doesnt_exist_create_new_next
(wcar (car/set "url_counter" 51))
(shorten test-url)
(let [[response1 response2] (wcar (car/get (str "urls|" test-url))
(car/get "shorts|1g"))]
(is (= "1g" response1))
(is (= test-url response2))))
So we're sending the first (SET) request to Redis and waiting for the reply (I'm not certain if that's actually necessary here). We then send the next two (GET) requests at once, allow Redis to queue the responses, then receive them all back at once as a vector that we'll destructure.
At first this may seem like unnecessary extra effort because it requires you to be explicit about when to receive queued responses, but it brings a lot of benefits including performance, clarity, and composable commands.
I'd check out Touchstone on GitHub if you're looking for an example of what I'd consider idiomatic Carmine use (just search for the wcar calls). (Sorry, SO is preventing me from including another link).
Otherwise just pop me an email (or file a GitHub issue) if you have any other questions.
Don't worry, you're using it the correct way already.
The Redis request functions (such as the get and set that you're using above) are all routed through another function send-request! that relies on a dynamically bound *context* to provide the connection. Attempting to call any of these Redis commands without that context will fail with a "no context" error. The with-conn macro (used in wcar) sets that context and provides the connection.
The wcar macro is then just a thin wrapper around with-conn making the assumption that you will be using the same connection details for all Redis requests.
So far this is all very similar to how Tavis Rudd's redis-clojure works.
So, the question now is why does Carmine need multiple wcar's when Redis-Clojure only required a single with-server?
And the answer is, it doesn't. Apart from sometimes, when it does. Carmine's with-conn uses Redis's "Pipelining" to send multiple requests with the same connection and then package the responses together in a vector. The example from the README shows this in action.
(wcar (car/ping)
(car/set "foo" "bar")
(car/get "foo"))
=> ["PONG" "OK" "bar"]
Here you will see that ping, set and get are only concerned with sending the request, leaving the receiving of response up to wcar. This precludes asserts (or any result access) from inside of wcar and leads to the separation of requests and multiple wcar calls that you have.