Cassaforte/clojure : never ending program - clojure

I try to use Cassaforte to query my cassandra db, but when i launch my code, it never end.
(defn cassandra []
(let [conn (cc/connect ["127.0.0.1", "127.0.0.2", "127.0.0.3"])
table "mytable"]
(cql/use-keyspace conn "mykeyspace")
(cql/select conn table (limit 10))))
(defn -main
"I don't do a whole lot ... yet"
[& args]
(println "Hello, World!")
(let [result (cassandra)]))
Result :
$ lein run
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Hello, World!
[the program is waiting here]
If i print the result var, it contains the rows, but same problem after.
Any idea ?

Your program is finished, you just haven't told the JVM that you explicitly want to exit at the end of main. You can do this by adding:
(System/exit 0)
to the end of your -main. Unlike a comparably small program written in just java, Clojure has started some thread pools in the background for things like agents to run on. These cause the JVM to think that some thread may still want to run and it does not immediately exit. This has been adopted as a feature by the Clojure community since then.

Related

How to reload (stop and start) an http-kit "mount state" on a -main function

With the mount library, how do I reload (stop and start) an http-kit "mount state" on a -main function?
My current code is this:
(defstate server-config :start {:port 7890 :join? false})
(defn start-server [server-config]
(when-let [server (run-server myserv-ring-handler server-config)]
(println "Server has started!")
server))
(defstate myserv-server :start (start-server server-config)
:stop (myserv-server :timeout 100))
(defn system-port [args]
(Integer/parseInt
(or (System/getenv "PORT")
(first args)
"7890")))
(defn -main [& args]
(mount/start-with-states
{#'myserv/server-config
{:start #(array-map :port (system-port args)
:join? false)}}))
So when I "lein run" everything works, but whenever I change a file, and the http-kit server is stopped, the command stops. For the moment I'm doing "while true; do lein run; done" to work, so I've thought about adding an infinite loop to the -main function, but it doesn't feel like this is the right way.
How should I do this?
I would suggest adding some metadata to your http server defstate.
From the mount readme:
In case nothing needs to be done to a running state on reload /
recompile / redef, set :on-reload to :noop:.
So try something like this:
(defstate ^{:on-reload :noop}
myserv-server
:start (start-server server-config)
:stop (my-stop-func myserv-server))
This means that when you change a file, the affected code will be reloaded, but the http server will continue to run.
I hope that I've correctly understood your question and that this is what you wanted.
Could I also suggest that if you want to get up and running quickly, then there are various templated web app projects for Leiningen. For example, the Luminus project. You can pass an +http-kit parameter to the lein new luminus myapp command and that will wire up an app correctly for you. You can then go and read the generated code and learn how it all fits together.
So I had a couple of separate problems:
I didn't understand that now I didn't need to use lein run, but instead I could just do lein repl and start the server from there. The restarting problem is avoided that way.
The other one was that I was misusing start-with-states instead of a config state.
You can see a discussion about this with the author of the library here.

Update clojure code running in a thread

Now, I need some kind of code reloading in the clojure/java mixing system.
I know tools.namespace lib can be used to refresh clj code. But when I try to reload code which is used in a thread, it is not updated.
This is the example clojure code I need to update: (just switch between upper case and lower case.)
(ns com.test.test-util)
(defn get-word [sentence]
(let [a-word (rand-nth (clojure.string/split sentence #"\s"))
;;a-word (clojure.string/upper-case a-word)
]
(println a-word)
a-word))
I used a future to start a thread and call the code above.
In main method, in my first test, I just create a future and refresh the code after a while. But it is not updated. So, I also tested to create another thread after refresh. But the code is not updated.
(defn start-job []
(future (
(println "start worker job.")
(while #job-cond
(do (get-word (rand-nth sentences))
(Thread/sleep 2000)) )
(println "return!")
)))
(defn -main []
(let [work-job (start-job)]
(println "modify clj file...")
(Thread/sleep 10000)
(swap! job-cond not)
(future-cancel work-job)
(swap! job-cond not)
(refresh)
(Thread/sleep 3000)
(let [new-work-job (start-job)]
(Thread/sleep 10000)
(swap! job-cond not)
(future-cancel new-work-job))))
Thanks.
In general you don't want code-reloading to affect runtime. Rather you should try to seek for clean ways to boot and shutdown the running application code using e. g. Stuart Sierras library component or juxt/jig by Malcolm Sparks. Then reload namespaces only when your application is not up and running (or at least not the parts of running code that depend on namespaces being reloaded).
That being said, here is why your example does not work:
start-job can not automatically refer to a reloaded version of get-word in its lifetime because the version of get-work it uses is resolved when it is compiled. So it will still use the old version.
Explicitly resolve the var of get-word using
(resolve `get-word)
and invoke the returned var as a function instead of using get-word directly in the future.
What will happen then?
After you made the changes and refresh has been invoked, -main will still refer to the old-version of start-job (so if you change that, it will not show effect in runtime). However within that get-word will be resolved as described above and the new version of get-word will be used.
Short explanation: You can't expect a running compiled function to replace itself with reloaded code on the fly (no matter whether it runs on a separate thread or not). That would (unless you are using resolve in it) be a necessity though for it to invoke reloaded functions.

clojure.tools.logging EvalReader use?

I think this is a bug in clojure/tools.logging. I have the following db.clj file. What it does is unimportant. The important part is that for safety I have disabled the *read-eval*. I invoke db/start with no problems. However, if I uncomment the #_(log/info "Failed to bootstrap") form, it throws an EvalReader not allowed error. I've tried all sorts of combinations for the log/info call. If it's outside of the try block, it's fine. Inside the try block anywhere, whether it's in the body, catch, or finally, it raises this exception. However, when I wrap a try around log/info elsewhere, it's fine.
What gives?
(ns extenium.db
(:require [clojure.tools.logging :as log]
[clojure.java.io :as io])
(:import com.thinkaurelius.titan.core.TitanGraph
com.thinkaurelius.titan.core.TitanFactory))
(def ^:private
sentinel- (Object.))
(def ^:private
db- (atom nil))
...
(defn start [^String path]
(locking sentinel-
(log/info "Starting database at path" path)
(let [exists (.exists (io/file path))
^TitanGraph db_ (TitanFactory/open path)]
(if exists
(log/info "Path" path "exists")
(log/info "Path" path "does not exist"))
(log/info "Starting database engine")
(swap! db- (constantly db_))
(log/info "Started database engine")
(if (not exists)
(try
(bootstrap-)
(catch Throwable t
#_(log/info "Failed to bootstrap")
(stop)
(.delete (io/file path))
(throw t)))))
(log/info "Started database")
true))
EDIT: Trimmed down code per #alex-taggart. bootstrap- implementation not shown. I had originally included everything because this seemed like a context-specific bug and I felt it was safer to provide as much context as possible.
EDIT: Per #chouser, added how I'm disabling *read-eval*. This is the template that is generated by lein new app.
(defn -main
"The main entry point into Extenium."
[& args]
;; Prevent arbitrary eval injection
(alter-var-root #'*read-eval* (constantly false))
;; Initialize system settings from the command line and configuration file
(init!- args)
;; Start the service
(start!-))
It's not a bug, really. The clojure.tools.logging library is just an abstraction upon other Java logging facilities. To discover which one is available, it uses eval expression. You're welcome to check for your own: here is a quick search result and a certain file where it gets used.
In your case, I believe it's not necessary to care about the global read-eval. This is an internal feature and who knows what other libraries depend on it. If you validate the user input and prevent it from being evaluated, it's fine to leave the flag as is. I would say, SQL injections and XSS are the things you should be worried about first.

Creating a Clojure future without it running

I have a basic Clojure script containing:
(def test
(future
(loop []
(println "Running")
(recur))))
However, if I execure the file with:
java -cp clojure-1.3.0.jar clojure.main test.clj
Then the screen fills with "Running". How can I change it so the future runs when I want it?
Note: I realise this will run forever, it's just an example of my problem.
A future that doesn't run immediately is just a function with no arguments.
So:
(defn test []
(println "Running")
(recur))
...Later...
(future (test))

Transform this Clojure call into a lazy sequence

I'm working with a messaging toolkit (it happens to be Spread but I don't know that the details matter). Receiving messages from this toolkit requires some boilerplate:
Create a connection to the daemon.
Join a group.
Receive one or more messages.
Leave the group.
Disconnect from the daemon.
Following some idioms that I've seen used elsewhere, I was able to cook up some working functions using Spread's Java API and Clojure's interop forms:
(defn connect-to-daemon
"Open a connection"
[daemon-spec]
(let [connection (SpreadConnection.)
{:keys [host port user]} daemon-spec]
(doto connection
(.connect (InetAddress/getByName host) port user false false))))
(defn join-group
"Join a group on a connection"
[cxn group-name]
(doto (SpreadGroup.)
(.join cxn group-name)))
(defn with-daemon*
"Execute a function with a connection to the specified daemon"
[daemon-spec func]
(let [daemon (merge *spread-daemon* daemon-spec)
cxn (connect-to-daemon daemon-spec)]
(try
(binding [*spread-daemon* (assoc daemon :connection cxn)]
(func))
(finally
(.disconnect cxn)))))
(defn with-group*
"Execute a function while joined to a group"
[group-name func]
(let [cxn (:connection *spread-daemon*)
grp (join-group cxn group-name)]
(try
(binding [*spread-group* grp]
(func))
(finally
(.leave grp)))))
(defn receive-message
"Receive a single message. If none are available, this will block indefinitely."
[]
(let [cxn (:connection *spread-daemon*)]
(.receive cxn)))
(Basically the same idiom as with-open, just that the SpreadConnection class uses disconnect instead of close. Grr. Also, I left out some macros that aren't relevant to the structural question here.)
This works well enough. I can call receive-message from inside of a structure like:
(with-daemon {:host "localhost" :port 4803}
(with-group "aGroup"
(... looping ...
(let [msg (receive-message)]
...))))
It occurs to me that receive-message would be cleaner to use if it were an infinite lazy sequence that produces messages. So, if I wanted to join a group and get messages, the calling code should look something like:
(def message-seq (messages-from {:host "localhost" :port 4803} "aGroup"))
(take 5 message-seq)
I've seen plenty of examples of lazy sequences without cleanup, that's not too hard. The catch is steps #4 and 5 from above: leaving the group and disconnecting from the daemon. How can I bind the state of the connection and group into the sequence and run the necessary cleanup code when the sequence is no longer needed?
This article describes how to do exactly that using clojure-contrib fill-queue. Regarding cleanup - the neat thing about fill-queue is that you can supply a blocking function that cleans itself up if there is an error or some condition reached. You can also hold a reference to the resource to control it externally. The sequence will just terminate. So depending on your semantic requirement you'll have to choose the strategy that fits.
Try this:
(ns your-namespace
(:use clojure.contrib.seq-utils))
(defn messages-from [daemon-spec group-name]
(let [cnx (connect-to-deamon daemon-spec))
group (connect-to-group cnx group-name)]
(fill-queue (fn [fill]
(if done?
(do
(.leave group)
(.disconnect cnx)
(throw (RuntimeException. "Finished messages"))
(fill (.receive cnx))))))
Set done? to true when you want to terminate the list. Also, any exceptions thrown in (.receive cnx) will also terminate the list.