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.

Reply via email to