I am fairly new to Clojure, and new to the JVM, so I do not know how to 
diagnose a dying app.

I have a very simple app that tries to keep track (in memory) of who is 
logged in. I'll show the code below. I compiled this app and uploaded it to 
my server and launched it like this:

who-is-logged-in-1.0.1-standalone.jar 40000 </dev/null >/dev/null 2>&1 &

This ran for a day or two, and then it died. I restarted it, and it ran 
another day or 2, and then it died. I just restarted it so you might be 
able to see its output here:

http://www.tailormadeanswers.com:40000/

What you see is from some Javascript, which works when people log into a 
site like this: 

http://www.wpquestions.com/

On that site, the Javascript sends an Ajax ping every 10 seconds. The 
Clojure app remembers everyone who has sent a ping during the last 15 
seconds. I don't think this has ever been more than 30 people, so I doubt 
that I am at risk of exhausting the memory. If the app is running, you can 
see some usage stats here:

http://www.tailormadeanswers.com:40000/show-resources

I have not yet added any security to the app, so there is a chance that 
someone is shutting it down with spam. (I just got this app up last week, 
and was planning to add security checks this week). 

I do not know much about programming for the JVM, so I am curious, how do I 
diagnose this? I could add some logging, but what should I log? What should 
I be looking for? 

My project.clj looks like this:

(defproject who-is-logged-in "1.0.1"
  :description "When users arrive at a site like wpquestions.com, and then 
log in, the Javascript on that site should do 2 things: ping this software 
to let us know that user has logged in, and also ping this software to get 
some info about who else is logged in. The Javascript on the site should be 
able to take the data this software sends and turn it into a meaningful 
list of logged in users. Version: 1.0.1: since the output needs to be 
consumed by Javascript as JSON, I'm making some changes in the way the 
registry outputs."
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [net.cgrand/moustache "1.1.0"]
                 [ring "1.1.5"]
                 [ring/ring-jetty-adapter "1.1.5"]
                 [org.clojure/data.json "0.2.0"]]
  :main who-is-logged-in.core
  :jvm-opts ["-Xmx4000m"])


And the core.clj looks like this:

(ns who-is-logged-in.core
  (:gen-class)
  (:import (java.util Date))
  (:require clojure.string clojure.java.io who-is-logged-in.memory_display
            [clojure.data.json :as json])
  (:use   [net.cgrand.moustache :only [app delegate]]
          [ring.util.response]
          [ring.middleware.params]
          [ring.adapter.jetty :only [run-jetty]]))

(def registry (atom {}))

(defn add-to-logged-in-registry [this-users-params]
  "We assume some user is looking at a site such as wpquestions.com and the 
Javascript on that site is sending an Ajax request to this app, every 10 
seconds, with a map of information about the user, which we need to store 
in the registry."
  (let [right-now (. (Date.) getTime)
        new-user-entry (conj this-users-params { "updated" right-now })]
    (if-not (nil? (get new-user-entry "username"))
      (swap! registry assoc (get new-user-entry "username") 
new-user-entry))))

(defn is-current? [this-users-map]
  "If we have not received an Ajax request from a user during the last 15 
seconds then we can assume they have left the site. We need to remove them 
from registry."
    (let [most-recent-ping (get this-users-map "updated")
          allowed-cutoff (- (. (Date.) getTime) 15000)]
      (if (> most-recent-ping allowed-cutoff)
        true
        false)))

(defn remove-old-registrants []
  "The registry should only show people who have pinged this app during the 
last 15 seconds. We rebuild the registry with only those users whose maps 
return true from is-current?"
  (def updated-registry {})
  (swap! registry (fn [map-of-all-user-maps]
                    (into {}
                          (doall
                           (for [[username-as-key each-user-map] 
map-of-all-user-maps :when (is-current? each-user-map)]
                             (conj updated-registry {(get each-user-map 
"username") each-user-map})))))))

(defn current-users [request]
  "The default action of this app. Add new users to the registry, and 
delete the ones that are more than 15 seconds old"
  (let [this-users-params (:params request)]
    (add-to-logged-in-registry this-users-params)
    (remove-old-registrants)
    (response (apply str (json/write-str @registry)))))










-- 
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

Reply via email to