Store the last update timestamp per resource and instance id
authorGeorgios Gousios <gousiosg@gmail.com>
Tue, 10 Jan 2012 16:17:13 +0000 (18:17 +0200)
committerGeorgios Gousios <gousiosg@gmail.com>
Tue, 10 Jan 2012 16:17:52 +0000 (18:17 +0200)
This code has some errors with JSON serialization

src/main/scala/gr/grnet/aquarium/user/UserDataSnapshot.scala
src/main/scala/gr/grnet/aquarium/user/actor/UserActor.scala
src/test/scala/gr/grnet/aquarium/user/UserActorTest.scala

index 93d478e..9fa35e5 100644 (file)
@@ -39,6 +39,7 @@ package user
 import logic.accounting.dsl.{DSLResource, DSLAgreement}
 import collection.mutable
 import logic.events.WalletEntry
+import util.json.JsonSupport
 
 
 /**
@@ -65,18 +66,24 @@ case class OwnedGroupsSnapshot(data: List[String], snapshotTime: Long) extends U
 case class GroupMembershipsSnapshot(data: List[String], snapshotTime: Long) extends UserDataSnapshot[List[String]]
 
 /**
- * Maintains the current state of resources owned by the user. In order to have a
- * uniform representation of the resource state for all resource types
- * (complex or simple) the following convention applies:
+ * Maintains the current state of resources owned by the user.
+ * The encoding of the stored Map is as follows:
+ *
+ * key:   ResourceInstanceId(DSLResource.name, instance-id)
+ * value: ResourceStateSnapshot(current-resource-value, last-update-timestamp)
+ *
+ * In order to have a uniform representation of the resource state for all
+ * resource types (complex or simple) the following convention applies:
+ *
+ *  - If the resource is complex, the key is stored as ResourceInstanceId(DSLResource.name, instance-id)
+ *  - If the resource is simple,  the key is stored as ResourceInstanceId(DSLResource.name, 1)
  *
- *  * If the resource is complex, then `data.get(AResource)` returns a Map of
- *  `("instance-id" -> current_resource_value)`, as expected.
- *  * If the resource is simple, then `data.get(AResource)` returns
- *   `("1" -> current_resource_value)`. This means that simple resources are
- *   always stored with key 1 as `instance-id`.
  */
-case class OwnedResourcesSnapshot(data: Map[DSLResource, Map[String, Float]], snapshotTime: Long)
-  extends UserDataSnapshot[Map[DSLResource, Map[String, Float]]]
+case class ResourceInstanceId(name: String, instanceId: String)
+case class ResourceStateSnapshot(value: Float, lastUpdate: Long)
+case class OwnedResourcesSnapshot(data: Map[ResourceInstanceId, ResourceStateSnapshot], snapshotTime: Long)
+  extends UserDataSnapshot[Map[ResourceInstanceId, ResourceStateSnapshot]]
+
 
 /**
  * A generic exception thrown when errors occur in dealing with user data snapshots
index 1254b27..111a8e6 100644 (file)
@@ -381,14 +381,15 @@ class UserActor extends AquariumActor with Loggable with Accounting {
             val oldOwnedResources = _userState.ownedResources
             // Find or create the new resource instance map
             val oldOwnedResourcesData = oldOwnedResources.data
-            val oldRCInstanceMap = oldOwnedResourcesData.get(resource) match {
-              case Some(resourceMap) ⇒ resourceMap
-              case None              ⇒ Map[String, Float]()
+            val key = ResourceInstanceId(resource.name, instanceId)
+            val oldRCInstance = oldOwnedResourcesData.get(key) match {
+              case Some(resourceState) ⇒ resourceState
+              case None                ⇒ ResourceStateSnapshot(0, 0)
             }
-            // Update the new value in the resource instance map
-            val newRCInstanceMap: Map[String, Float] = oldRCInstanceMap.updated(instanceId, ev.value)
+            // Update the new value in the resource state
+            val newRCInstanceMap = oldRCInstance.copy(value = ev.value, lastUpdate = ev.occurredMillis)
 
-            val newOwnedResourcesData = oldOwnedResourcesData.updated(resource, newRCInstanceMap)
+            val newOwnedResourcesData = oldOwnedResourcesData.updated(key, newRCInstanceMap)
 
             // A. First state diff: the modified resource value
             val StateChangeMillis = TimeHelpers.nowMillis
@@ -403,7 +404,7 @@ class UserActor extends AquariumActor with Loggable with Accounting {
                 // TODO: the snapshot time should be per instanceId?
                 // TODO: Related events
                 val walletEntriesM = chargeEvent(ev, agreement, ev.value,
-                  new Date(oldOwnedResources.snapshotTime),
+                  new Date(oldRCInstance.lastUpdate),
                   findRelatedEntries(resource, ev.getInstanceId(policy)))
                 walletEntriesM match {
                   case Just(walletEntries) ⇒
index 1302368..ea19413 100644 (file)
@@ -3,6 +3,8 @@ package gr.grnet.aquarium.user
 import gr.grnet.aquarium.logic.test.DSLTest
 import gr.grnet.aquarium.logic.accounting.Policy
 import org.junit.Test
+import gr.grnet.aquarium.util.json.JsonSupport
+import gr.grnet.aquarium.logic.accounting.dsl.DSLResource
 
 /**
  * 
@@ -24,7 +26,8 @@ class UserActorTest extends DSLTest {
       PaymentOrdersSnapshot(Nil, now),
       OwnedGroupsSnapshot(Nil, now),
       GroupMembershipsSnapshot(Nil, now),
-      OwnedResourcesSnapshot(Map(("foo", "1") -> (0F, 0L)), now)
+      OwnedResourcesSnapshot(Map(ResourceInstanceId("foo", "1") ->
+        ResourceStateSnapshot(0F, 0L)), now)
     )
 
     println(state.toJson)