Okay, I am an idiot. I had the "directory watch" setup to watch the directory where the uberjar was built, so of course it was triggered thousands of time while the uberjar was built, since I guess every new byte added to the uberjar triggers the change event.
So I set my app to listen on the final directory, where the final uberjar is moved, just once, when the uberjar is complete, and now the app behaves the way I was expecting it to. On Sunday, August 9, 2015 at 1:13:56 PM UTC-4, Lawrence Krubner wrote: > > > Let's assume for a moment that, for some strange reason, the "directory > watching" strategy won't work here. Does anyone have any other suggestions? > I am thinking there must be a simple way to setup Jenkins and Supervisord > to run these apps, but what I'm doing keeps getting more and more complex, > which is typically a warning sign that I'm on the wrong track. > > > > > On Saturday, August 8, 2015 at 5:24:28 PM UTC-4, Lawrence Krubner wrote: >> >> I feel stupid, but I have not been able to track this down. >> >> The background is that I have Jenkins running on the server, and when >> triggered it pulls code from Github, compiles it, and then moves the final >> uberjar to the directory where I keep all the uberjars that run on this >> server. Then I have an app that should kill all currently running >> instances. Then Supervisord should step in and restart the instances, using >> the new uberjars for the new instances. >> >> All of this works, but I have been doing one bit by hand: "kill all >> currently running instances". I log in as root and run a script that kills >> the old instances. But just today I wrote a quick Clojure app to automate >> this for me (the whole app is 50 lines of code, so this is a very small >> app). >> >> To trigger the main action, I thought the app should set a watcher on the >> final directory where Jenkins moves the uberjars to. When Jenkins moves a >> new uberjar to the directory, the watch would be triggered and then it >> could run the "kill all currently running instances" script. However, I >> assumed that the ""kill all currently running instances"" script would be >> triggered once each time the uberjar was updated, but instead it seems to >> be triggered infinitely. Does a JVM app, or a Clojure app, change the dir >> its in, on launch? Or is the problem in my own code? I'm using Chris >> Zheng's excellent Hara library for the Watch. This is the main function of >> my app, which is called on startup: >> >> (defn establish-watchers [] >> "The config contains a hashmap which has a 'watchers' key, which >> contains a vector that holds hashmaps with 2 keys, one pointing to the >> directory that should be watched and the other pointing to the command that >> should be run when the watch is triggered." >> (let [config (read-string (slurp "/etc/fiit.edn")) >> watchers (:watchers config)] >> (doseq [w watchers] >> (common-watch/add (clojure.java.io/file (:dir-to-watch w)) (keyword >> (:dir-to-watch w)) >> (fn [f k _ [cmd file]] >> (pprint/pprint (:out (sh/sh (:action-to-do w))))) >> {:types #{:create :modify} >> :recursive false >> :async false})))) >> >> So if I log in as root and start the app like this: >> >> /usr/bin/java -jar /home/jenkins/fiit/fiit-1-standalone.jar >> >> Then at the terminal I see this, which I expect: >> >> [/home/jenkins/sarr] >> [/home/jenkins/food_for_all] >> >> Those are the 2 directories that it is watching. >> >> Then if I trigger Jenkins for the sarr app, Jenkins will pull the sarr >> code from Github, rebuild the sarr uberjar, and move the uberjar to >> /home/jenkins/sarr. >> >> All of that works just great. And then my app sees there has been a >> change in /home/jenkins/sarr, and so it calls the command to kill all >> existing instances of the sarr app. However, instead of doing this once, it >> starts doing so an infinite number of times. At the terminal I see: >> >> (sarr is a Java app, not a Clojure app) >> >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \nroot 25593 0.0 0.1 5813460 19452 ? >> Sl 20:28 0:00 /usr/bin/java -cp /home/jenkins/sarr/sarr.jar >> com.candle.sarr.Main\nroot 25595 0.0 0.1 5813460 19564 ? Sl >> 20:28 0:00 /usr/bin/java -cp /home/jenkins/sarr/sarr.jar >> com.candle.sarr.Main\n25593\n25595\n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n25694\n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \nroot 26239 0.0 0.1 5813460 19452 ? >> Sl 20:28 0:00 /usr/bin/java -cp /home/jenkins/sarr/sarr.jar >> com.candle.sarr.Main\n26239\n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \nroot 26319 0.0 0.1 5811252 15484 ? >> Sl 20:28 0:00 /usr/bin/java -cp /home/jenkins/sarr/sarr.jar >> com.candle.sarr.Main\n26319\n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> "We will kill these processes: \n" >> >> >> I have Supervisord set to run 3 instances of the sarr app, so you can see >> at first it it is killing these PIDs: >> >> 25593 >> 25595 >> 25694 >> >> Supervisord restarts these almost instantly, so you can see these >> processes are launched and instantly killed, all on the same line of >> output: >> >> "We will kill these processes: \nroot 26239 0.0 0.1 5813460 19452 ? >> Sl 20:28 0:00 /usr/bin/java -cp /home/jenkins/sarr/sarr.jar >> com.candle.sarr.Main\n26239\n" >> >> "We will kill these processes: \nroot 26319 0.0 0.1 5811252 15484 ? >> Sl 20:28 0:00 /usr/bin/java -cp /home/jenkins/sarr/sarr.jar >> com.candle.sarr.Main\n26319\n" >> >> This goes on for as long as I allow it (it takes Supervisord a long time >> to quit, because when I am developing new software, I set startretries=500, >> in Supervisord, exactly so I can experiment like this). >> >> I looked here to try to figure out what was going on: >> >> >> https://github.com/zcaudate/hara/blob/55b4eda688a4e616f03bf3740419a69b5c5dd658/src/hara/io/watch.clj >> >> As near as I can tell, the main action happens here: >> >> (defn run-watcher [watcher] >> (let [^java.nio.file.WatchKey wkey >> (.take ^java.nio.file.WatchService (:service watcher))] >> (doseq [^java.nio.file.WatchEvent event (.pollEvents wkey) >> :when (not= (.kind event) >> StandardWatchEventKinds/OVERFLOW)] >> (let [kind (.kind event) >> ^java.nio.file.Path path (.watchable wkey) >> ^java.nio.file.Path context (.context event) >> ^java.nio.file.Path res-path (.resolve path context) >> ^java.io.File file (.toFile res-path)] >> (if (and (= kind StandardWatchEventKinds/ENTRY_CREATE) >> (.isDirectory file) >> (-> watcher :options :recursive)) >> (register-sub-directory watcher (.getPath file))) >> (if (.isFile file) >> (process-event watcher kind file)))) >> (.reset wkey) >> (recur watcher))) >> >> >> Again, maybe I am being stupid, but it looks to me like the callback is >> called once per event triggered on that directory. So why would the >> callback seem to be called an infinite number of times? Does starting or >> stopping the app trigger a change in the directory (thus triggering the >> callback again)? >> >> >> >> >> >> >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.