I'm trying to implement a carmine worker in a constantly running process.
When launching the following app with lein run myclass.foo, it just starts the worker and stops it right away.
(def my-worker
(car-mq/worker queue-server "my-queue"
{:handler (fn [{:keys [message attempt]}]
(println "Received" message)
{:status :success})
:auto-start false}))
(defn -main []
(car-mq/start my-worker))
My goal is something like that
Launch the foo listener
foo listener runs in foreground and prints everything that gets posted to the queue
Ctrl-c / quit will close the listener
Running it with lein foo was the wrong approach. I edited the entire question to conform with the 'solution' I found.
The main problem was, that I was using lein run myclass.foo to run it. lein trampoline run myclass.foo launches the app's JVM and gets rid of leiningen's, with seems to be exactly what I need. When using trampoline instead of run, the app doesn't exit right away.
Step 2, to close the connection on ctrl-c is a simple shutdown hook
(.addShutdownHook (Runtime/getRuntime) (Thread. #(car-mq/stop my-worker)))
Related
I'm trying to use lwjgl with clojure for game developement.
My first step is trying to display something on an OpenGL screenfrom the REPL. After launching the repl with lein repl this is what I have done so far:
(import org.lwjgl.opengl GL11 Display DisplayMode
(Display/setDisplayMode (DisplayMode. 800 600))
(Display/create) ; This shows a black 800x600 window as expected
(GL11/glClearColor 1.0 0.0 0.0 1.0)
(GL11/glClear (bit-or GL11/GL_COLOR_BUFFER_BIT GL11/GL_DEPTH_BUFFER_BIT))
(Display/update)
Note that this works, if done quick enough. But after a while (even if I just wait) I start getting errors about the current OpenGL context not being bound to the current thread.
(Display/update)
IllegalStateException No context is current org.lwjgl.opengl.LinuxContextImplementation.swapBuffers (LinuxContextImplementation.java:72)
(GL11/glClear ...)
RuntimeException No OpenGL context found in the current thread. org.lwjgl.opengl.GLContext.getCapabilities (GLContext.java:124)
But maybe the most intriguing of the errors happens when I try to call Display/destroy
(Display/destroy)
IllegalStateException From thread Thread[nREPL-worker-4,5,main]: Thread[nREPL-worker-0,5,] already has the context current org.lwjgl.opengl.ContextGL.checkAccess (ContextGL.java:184)
It all looks as if the repl randomly spawned another thread after some time of inactivity. As I've been able to read, LWJGL only lets you make OpenGL calls from the thread from where it originally was created, so I bet this is causing those errors.
But how could the REPL be randomly switching threads? And especially if I'm not doing anything, just waiting.
It's a known issue already reported against nREPL project (and discussed on Clojure Google Group). It seems that nREPL uses thread pool which terminates idle threads (probably according to keepalive setting).
Until it's fixed you can use a workaround for this (a bit awkward, I admit):
(import '(java.util.concurrent Executors))
(def opengl-executor (Executors/newSingleThreadExecutor))
(defmacro with-executor [executor & body]
`(.submit ~executor (fn [] ~#body)))
(on-executor opengl-executor
(println (.getId (Thread/currentThread))))
By using your own executor, all code wrapped in on-executor will be executed in its thread. newSingleThreadExecutor creates one single thread which according to doc will replace it only when the current one fails due to exception. When you try to execute the last expression with long delays, the printed thread ID should remain the same.
Remember that you should shutdown the executor when stopping your application.
(def queue-agent (agent (clojure.lang.PersistentQueue/EMPTY)))
(send queue-agent conj "some data for the queue")
(println "test output")
If I run this code, after a couple (!) of seconds the console will output test output and then nothing happens (program is not terminating). I've just checked against a couple of sources that all said the send function is asynchronous and should return immediately to the calling thread. So what's wrong with this? Why is it not returning? Is there something wrong with me? Or with my environment?
So you have two issues: long startup time, and the program does not exit.
Startup: Clojure does not do any tree shaking. When you run a Clojure program, you load and bootstrap the compiler, and initialize namespaces, on every run. A couple of seconds sounds about right for a bare bones Clojure program.
Hanging: If you use the agent thread pool, you must run shutdown-agents if you want the program to exit. The vm simply doesn't know it is safe to shut them down.
The scenario I try to resolve is a s follows, I have a testing program that makes a web to a web endpoint on a system.
This test program has a jetty web server running on which it expects a callback from the external system that completes a successful test cycle. In case that the callback is not received during an specific time range (timeout), the test fails.
To achieve this, I want the test runner to wait on an "event" that the jetty handler will set upon callback.
I thought about using java's CyclicBarrier but I wonder if there is an idiomatic way in clojure to solve this.
Thanks
You can use promise you asked about recently :) Something like this:
(def completion (promise))
; In test runner.
; Wait 5 seconds then fail.
(let [result (deref completion 5000 :fail)]
(if (= result :success)
(println "Great!")
(println "Failed :(")))
; In jetty on callback
(deliver completion :success)
In straight Clojure, using an agent that tracks outstanding callbacks would make sense, though in practice I would recommend using Aleph, which is a library for asynchronous web programming that makes even driven handlers rather easy. It produces ring handlers, which sounds like it would fit nicely with your existing code.
I have a simple single threaded Clojure program that creates a temp file for swapping data. When the program exits normally this file is deleted, however when the program is exited via Ctrl+C, Ctrl+D, or Ctrl+Z that bit of code never executes. I need it to execute regardles sof how the program exits. I know that I need to catch that signal (I've done this before in other languages), but I can't seem to figure out how to do it in Clojure.
I don't know if Clojure has wrapped method for that purpose. In java, you can use Runtime.addShutdownHook()
Registers a new virtual-machine shutdown hook.
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
Update
Here is a simple demo
(.addShutdownHook (Runtime/getRuntime) (Thread. (fn [] (println "Shutting down..."))))
user=> ;; Ctrl-C
Shutting down...
Have a look at the deleteOnExit method in the java.io.File:
(import '(java.io File))
(doto (File/createTempFile "foo" nil nil) (.deleteOnExit))
I am trying to use sh from clojure.java.shell. In the REPL, it works fine but from a script, it gets stuck.
(ns tutorial.shell
(:use clojure.java.shell))
(println (:out (sh "ls" )))
What should I fix?
The problem is that sh uses futures and Clojure programs which use futures or agents hang around a bit before quitting when they have nothing more to do due to how some internal machinery works.
To get around this, add
(shutdown-agents)
at the end of your script, which terminates that piece of machinery. (So it does more than the name promises in that futures are also affected.)
Note that this cannot be undone and therefore should not be used at the REPL.