Event refactoring
[aquarium] / src / main / scala / gr / grnet / aquarium / store / LocalFSEventStore.scala
index 2986ac8..06dbaa8 100644 (file)
 package gr.grnet.aquarium.store
 
 import gr.grnet.aquarium.Configurator
-import com.ckkloverdos.maybe.Maybe
-import gr.grnet.aquarium.util.date.MutableDateCalc
 import java.io.{FileOutputStream, File}
-import gr.grnet.aquarium.logic.events.{UserEvent, ResourceEvent}
+import gr.grnet.aquarium.util.{Loggable, stringOfStackTrace}
+import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
+import gr.grnet.aquarium.event.model.im.IMEventModel
+import gr.grnet.aquarium.event.model.resource.ResourceEventModel
 
 /**
  * This is used whenever the property `events.store.folder` is setup in aquarium configuration.
  *
- * The public methods guarantee they will not propagate any failure.
- *
  * @author Christos KK Loverdos <loverdos@gmail.com>
  */
 
-object LocalFSEventStore {
-  private[this] def writeToFile(file: File, data: Array[Byte]): Unit = {
+object LocalFSEventStore extends Loggable {
+  private[this] final val NewLine  = "\n".getBytes("UTF-8")
+  private[this] final val NewLine2 = NewLine ++ NewLine
+
+  private[this] def writeToFile(file: File, data: Array[Byte], appendString: Option[String] = None): Unit = {
     val out = new FileOutputStream(file)
     out.write(data)
+    appendString match {
+      case Some(s) ⇒
+        out.write(NewLine2)
+        out.write(s.getBytes("UTF-8"))
+      case None ⇒
+    }
     out.flush()
     out.close()
+
+    logger.debug("Wrote to file {}", file.getCanonicalPath)
+  }
+
+  private[this] def createResourceEventsFolder(root: File): File = {
+    val folder = new File(root, "rc")
+    folder.mkdirs()
+    folder
+  }
+
+  private[this] def createIMEventsFolder(root: File): File = {
+    val folder = new File(root, "im")
+    folder.mkdirs()
+    folder
+  }
+
+  private[this] def writeJson(tag: String,
+                              folder: File,
+                              jsonPayload: Array[Byte],
+                              occurredString: String,
+                              extraName: Option[String],
+                              isParsed: Boolean,
+                              appendString: Option[String]): Unit = {
+    val file = new File(
+      folder,
+      "%s-%s%s.%s.json".format(
+        tag,
+        occurredString,
+        extraName match {
+          case Some(s) ⇒ "-" + s
+          case None    ⇒ ""
+        },
+        if(isParsed) "p" else "u"
+      ))
+
+    writeToFile(file, jsonPayload, appendString)
+  }
+
+  def storeUnparsedResourceEvent(mc: Configurator, initialPayload: Array[Byte], exception: Throwable): Unit = {
+    for(root <- mc.eventsStoreFolder) {
+      val occurredMDC = new MutableDateCalc(TimeHelpers.nowMillis())
+      val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
+      val rcEventsFolder = createResourceEventsFolder(root)
+      val trace = stringOfStackTrace(exception)
+
+      writeJson("rc", rcEventsFolder, initialPayload, occurredString, None, false, Some(trace))
+    }
   }
 
-  private[this] def writeToFile(file: File, data: String): Unit = {
-    writeToFile(file, data.getBytes("UTF-8"))
+  def storeResourceEvent(mc: Configurator, event: ResourceEventModel, initialPayload: Array[Byte]): Unit = {
+    require(event ne null, "Resource event must be not null")
+
+    for(root <- mc.eventsStoreFolder) {
+      val occurredMDC = new MutableDateCalc(event.occurredMillis)
+      val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
+      val rcEventsFolder = createResourceEventsFolder(root)
+
+      // Store parsed file
+      writeJson(
+        "rc",
+        rcEventsFolder,
+        initialPayload,
+        occurredString,
+        Some("[%s]-[%s]-[%s]-[%s]".format(
+          event.id,
+          event.userID,
+          event.resource,
+          event.instanceID)),
+        true,
+        None
+      )
+    }
   }
 
-  def storeResourceEvent(mc: Configurator, event: ResourceEvent, initialPayload: Array[Byte]): Maybe[Unit] = Maybe {
-    if(mc.hasEventsStoreFolder) {
-      val occurredString = new MutableDateCalc(event.occurredMillis).toYYYYMMDDHHMMSS
-      val root = mc.eventsStoreFolder
-      val rcEvents = new File(root, "rcevents")
-      val parsed = event ne null
-
-      // We save two files. One containing the initial payload and one containing the transformed object.
-      val initialPayloadFile = new File(rcEvents, "rc-%s.raw%s".format(occurredString, if(!parsed) "x" else ""))
-      Maybe { writeToFile(initialPayloadFile, initialPayload) }
-
-      if(parsed) {
-        val parsedJsonFile = new File(
-          rcEvents,
-          "rc-%s-[%s]-[%s]-[%s]-[%s].json".format(
-            occurredString,
-            event.id,
-            event.userId,
-            event.resource,
-            event.instanceId))
-
-        Maybe { writeToFile(parsedJsonFile, event.toJson) }
-      }
+  def storeUnparsedIMEvent(mc: Configurator, initialPayload: Array[Byte], exception: Throwable): Unit = {
+    for(root <- mc.eventsStoreFolder) {
+      val occurredMDC = new MutableDateCalc(TimeHelpers.nowMillis())
+      val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
+      val imEventsFolder = createIMEventsFolder(root)
+      val trace = stringOfStackTrace(exception)
+
+      writeJson("im", imEventsFolder, initialPayload, occurredString, None, false, Some(trace))
     }
   }
 
-  def storeUserEvent(mc: Configurator, event: UserEvent, initialPayload: Array[Byte]): Maybe[Unit] = Maybe {
-    if(mc.hasEventsStoreFolder) {
-      val occurredString = new MutableDateCalc(event.occurredMillis).toYYYYMMDDHHMMSS
-      val root = mc.eventsStoreFolder
-      val imEvents = new File(root, "imevents")
-      val parsed = event ne null
-
-     // We save two files. One containing the initial payload and one containing the transformed object.
-      val initialPayloadFile = new File(imEvents, "im-%s.raw%s".format(occurredString, if(!parsed) "x" else ""))
-      Maybe { writeToFile(initialPayloadFile, initialPayload) }
-
-      if(parsed) {
-        val parsedJsonFile = new File(imEvents, "im-%s-[%s]-[%s].json".format(occurredString, event.id, event.userID))
-        Maybe { writeToFile(parsedJsonFile, event.toJson) }
-      }
+  def storeIMEvent(mc: Configurator, event: IMEventModel, initialPayload: Array[Byte]): Unit = {
+    require(event ne null, "IM event must be not null")
+    for(root <- mc.eventsStoreFolder) {
+      val occurredMDC = new MutableDateCalc(event.occurredMillis)
+      val occurredString = occurredMDC.toFilename_YYYYMMDDHHMMSSSSS
+      val imEventsFolder = createIMEventsFolder(root)
+
+      writeJson(
+        "im",
+        imEventsFolder,
+        initialPayload,
+        occurredString,
+        Some("[%s]-[%s]".format(event.id, event.userID)),
+        true,
+        None
+      )
     }
   }
 }