incubator-esme-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vdic...@apache.org
Subject svn commit: r802595 - in /incubator/esme/trunk/server/src/main: scala/bootstrap/liftweb/ scala/org/apache/esme/actor/ scala/org/apache/esme/snippet/ webapp/style/ webapp/templates-hidden/
Date Sun, 09 Aug 2009 20:52:17 GMT
Author: vdichev
Date: Sun Aug  9 20:52:17 2009
New Revision: 802595

URL: http://svn.apache.org/viewvc?rev=802595&view=rev
Log:
ESME-81 Snippet for popular resent messages.

Added:
    incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/PopStatsActor.scala 
 (with props)
Modified:
    incubator/esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala
    incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/UserActor.scala
    incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala
    incubator/esme/trunk/server/src/main/webapp/style/b-content.css
    incubator/esme/trunk/server/src/main/webapp/templates-hidden/message.html

Modified: incubator/esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala?rev=802595&r1=802594&r2=802595&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala (original)
+++ incubator/esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala Sun Aug  9 20:52:17
2009
@@ -27,6 +27,8 @@
 import net.liftweb.sitemap._
 import net.liftweb.sitemap.Loc._
 import Helpers._
+import TimeHelpers.intToTimeSpanBuilder
+import TimeHelpers.timeSpanToLong
 import net.liftweb.mapper.{DB, ConnectionManager, Schemifier, DefaultConnectionIdentifier,
ConnectionIdentifier}
 import java.sql.{Connection, DriverManager}
 import org.apache.esme._
@@ -144,6 +146,8 @@
     SchedulerActor.touch
     MessagePullActor.touch
     ScalaInterpreter.touch
+    
+    PopStatsActor ! PopStatsActor.StartStats(ResendStat, 1 week, 1 hour)
 
     Action.findAll(By(Action.disabled, false), By(Action.removed, false)).foreach {
       _.startActors

Added: incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/PopStatsActor.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/PopStatsActor.scala?rev=802595&view=auto
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/PopStatsActor.scala (added)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/PopStatsActor.scala Sun
Aug  9 20:52:17 2009
@@ -0,0 +1,133 @@
+package org.apache.esme.actor
+
+/**
+ * Copyright 2008-2009 WorldWide Conferencing, LLC
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import scala.actors.Actor
+import scala.actors.TIMEOUT
+import scala.actors.Actor._
+import org.apache.esme.actor.Distributor.AddMessageToMailbox
+import org.apache.esme.model._
+import net.liftweb.http.ActorWatcher
+import net.liftweb.util.{Full,Empty,TimeHelpers}
+
+class PopStatsActor(val period: Long, val refreshInterval: Long) extends Actor {
+
+  import PopStatsActor._
+
+  var queue: List[StatEvent] = List()
+  var stats: Map[Long,Int] = Map()
+  var refreshActor: Actor = _
+  
+  def act {
+    loop {
+      react {
+        case StartUp =>
+          refreshActor = actor {
+            loop {
+              self.reactWithin(refreshInterval) {
+                case TIMEOUT => this ! Expire
+                case ByeBye => self.exit()
+              }
+            }
+          }
+        case ByeBye =>
+          refreshActor ! ByeBye  
+          self.exit()
+        case Hit(id) =>
+          queue += StatEvent(id, now)
+          stats += (id -> (stats.getOrElse(id,0) + 1))
+        case Top(n) =>
+          val topList = stats.toList.sort{ (t1, t2) =>
+            val ((_,freq1),(_,freq2)) = (t1, t2)
+            freq2 < freq1
+          }.take(n)
+          reply(topList)
+        case Expire => {
+          queue = queue.dropWhile{ event =>
+            val expired_? = event.when < now
+            if (expired_?) stats -= event.id
+            expired_?
+          }.toList
+        }
+      }
+    }
+  }
+  
+  case class StatEvent(id: Long, when: Long)
+}
+
+object PopStatsActor extends Actor {
+
+  // immutable maps of maps doesn't work well
+  import scala.collection.mutable.Map
+  
+  val actors: Map[StatParam,Map[Long,PopStatsActor]] = Map()
+  
+  def now = System.currentTimeMillis
+  def act = loop {
+    react {
+      case StartStats(what, period, refresh) =>
+        if (!actors.contains(what))
+          actors(what) = Map()
+        val stat = actors(what)
+        if(!stat.contains(period)) {
+          val statActor = new PopStatsActor(period, refresh)
+          stat(period) = statActor
+          statActor.start
+          statActor ! StartUp
+        }
+          
+      case StopStats(what, period) => // TODO: not used
+      case TopStats(what, n, period) =>
+        (for (stat <- actors.get(what);
+             availableActor <- stat.get(period)) yield availableActor) match {
+               case Some(statActor) => statActor forward Top(n)
+               case _ => reply(Nil)
+             }
+      case IncrStats(what, hitItem) =>
+        for (stat <- actors.get(what);
+             statActor <- stat.values)
+          statActor ! Hit(hitItem)
+    }
+  }
+  
+  start
+
+  // do nothing
+  def touch {
+  }
+
+  case object StartUp
+  case object ByeBye
+  case class Top(n: Int)
+  case class Hit(id: Long)
+  case object Expire
+  
+  case class StartStats(what: StatParam, period: Long, refresh: Long)
+  case class StopStats(what: StatParam, period: Long)
+  case class TopStats(what: StatParam, n: Byte, period: Long)
+  case class IncrStats(what: StatParam, hitItem: Long)
+}
+
+sealed trait StatParam
+case object ResendStat extends StatParam
+case object LinkClickedStat extends StatParam

Propchange: incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/PopStatsActor.scala
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/UserActor.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/UserActor.scala?rev=802595&r1=802594&r2=802595&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/UserActor.scala (original)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/actor/UserActor.scala Sun Aug
 9 20:52:17 2009
@@ -192,11 +192,13 @@
       case AllowPool(poolId) => pools += poolId
       
       case Resend(msgId) =>
-        for (msg <- Message.find(msgId);
-             id <- followers)
-               Distributor !
-               Distributor.AddMessageToMailbox(id, msg, ResendReason(userId))
-
+        for (msg <- Message.find(msgId)) {
+          if (!msg.pool.defined_?)
+            PopStatsActor ! PopStatsActor.IncrStats(ResendStat, msgId)
+          for (id <- followers)
+            Distributor !
+            Distributor.AddMessageToMailbox(id, msg, ResendReason(userId))
+        }
     }
   }
 

Modified: incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala?rev=802595&r1=802594&r2=802595&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala (original)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala Sun
Aug  9 20:52:17 2009
@@ -32,6 +32,8 @@
 import JE._
 import util._
 import Helpers._
+import TimeHelpers.intToTimeSpanBuilder
+import TimeHelpers.timeSpanToLong
 
 import scala.xml.{NodeSeq, Text, Node}
 
@@ -87,7 +89,8 @@
       "loginForm" -> loginForm _,
       "loggedIn" -> loggedInFilter _,
       "accessPools" -> accessPools _,
-      "resendScript" -> resendScript _)
+      "resendScript" -> resendScript _,
+      "popular" -> popular _)
 
   def loggedInFilter(in: NodeSeq): NodeSeq = {
     val lookFor = if (User.loggedIn_?) "in" else "out"
@@ -165,4 +168,33 @@
     }
   </xml:group>
   
+  def popular(in: NodeSeq): NodeSeq = 
+  <xml:group>
+    {PopStatsActor !? PopStatsActor.TopStats(ResendStat, 5, 1 week) match {
+        case l: List[Tuple2[Long,Int]] =>
+          <table>
+            <thead>
+              <tr> <th>Resent</th> <th>Message</th> </tr>
+            </thead>
+            <tbody>
+            {
+              val msgMap = Message.findMessages(l.map(_._1))
+              l.map{ stat =>
+                val (msgId, freq) = stat
+                (for (m <- msgMap.get(msgId)) yield {
+                  <tr>
+                    <td>{freq}</td>
+                    <td>{m.author.obj.map(_.nickname.is).openOr("")}:
+                        {m.digestedXHTML}
+                        <!--{new java.util.Date(m.when.toLong).toString}--></td>
+                  </tr>
+                }).getOrElse(<br/>)
+              }
+            }
+            </tbody>
+          </table>
+        case _ => <br/>
+      }
+    }
+  </xml:group>
 }

Modified: incubator/esme/trunk/server/src/main/webapp/style/b-content.css
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/webapp/style/b-content.css?rev=802595&r1=802594&r2=802595&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/main/webapp/style/b-content.css (original)
+++ incubator/esme/trunk/server/src/main/webapp/style/b-content.css Sun Aug  9 20:52:17 2009
@@ -1,5 +1,5 @@
 /* Content page (begin) */ /**/
-.b-cloud {
+.b-cloud, .b-stats {
   margin-top: 30px;
   /* background: #233e5e; /* url(../images/sh-r.png) repeat-y 100% 0; */
   text-align: center;
@@ -8,7 +8,7 @@
   border: 1px solid black;
 }
 
-#tag-para, #word-para {
+#tag-para, #word-para, #stats-para {
   font-size: 1.7em;
   text-decoration: underline;
   font-style: italic;

Modified: incubator/esme/trunk/server/src/main/webapp/templates-hidden/message.html
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/webapp/templates-hidden/message.html?rev=802595&r1=802594&r2=802595&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/main/webapp/templates-hidden/message.html (original)
+++ incubator/esme/trunk/server/src/main/webapp/templates-hidden/message.html Sun Aug  9 20:52:17
2009
@@ -308,6 +308,11 @@
                 <div class="b-cloud">
                   <lift:comet type="TagCloud"/>
                 </div>
+                
+                <div class="b-stats">
+                  <p id="stats-para">Popular messages</p>
+                  <lift:UserSnip.popular/>
+                </div>
 
                 <lift:ignore>
                   <div class="bugs">



Mime
View raw message