From 02e6f5895a832091c41b46002dce94959f808210 Mon Sep 17 00:00:00 2001 From: Debasish Ghosh Date: Thu, 18 Mar 2010 10:51:22 +0530 Subject: [PATCH] added support for Redis based SortedSet persistence in Akka transactors --- .../src/main/scala/Storage.scala | 122 +++++++++ .../src/main/scala/StorageBackend.scala | 10 +- .../src/main/scala/RedisStorage.scala | 15 ++ .../src/main/scala/RedisStorageBackend.scala | 17 +- .../test/scala/RedisPersistentActorSpec.scala | 2 +- .../scala/RedisPersistentSortedSetSpec.scala | 237 ++++++++++++++++++ .../test/scala/RedisStorageBackendSpec.scala | 12 +- .../redis/redisclient/1.1/redisclient-1.1.jar | Bin 47464 -> 0 bytes .../redis/redisclient/1.1/redisclient-1.1.pom | 8 - project/build/AkkaProject.scala | 2 +- 10 files changed, 404 insertions(+), 21 deletions(-) create mode 100644 akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentSortedSetSpec.scala delete mode 100644 embedded-repo/com/redis/redisclient/1.1/redisclient-1.1.jar delete mode 100755 embedded-repo/com/redis/redisclient/1.1/redisclient-1.1.pom diff --git a/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala b/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala index f21490a1be..0f0eeac912 100644 --- a/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala +++ b/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala @@ -51,18 +51,24 @@ trait Storage { def newRef: PersistentRef[ElementType] def newQueue: PersistentQueue[ElementType] = // only implemented for redis throw new UnsupportedOperationException + def newSortedSet: PersistentSortedSet[ElementType] = // only implemented for redis + throw new UnsupportedOperationException def getMap(id: String): PersistentMap[ElementType, ElementType] def getVector(id: String): PersistentVector[ElementType] def getRef(id: String): PersistentRef[ElementType] def getQueue(id: String): PersistentQueue[ElementType] = // only implemented for redis throw new UnsupportedOperationException + def getSortedSet(id: String): PersistentSortedSet[ElementType] = // only implemented for redis + throw new UnsupportedOperationException def newMap(id: String): PersistentMap[ElementType, ElementType] def newVector(id: String): PersistentVector[ElementType] def newRef(id: String): PersistentRef[ElementType] def newQueue(id: String): PersistentQueue[ElementType] = // only implemented for redis throw new UnsupportedOperationException + def newSortedSet(id: String): PersistentSortedSet[ElementType] = // only implemented for redis + throw new UnsupportedOperationException } /** @@ -398,3 +404,119 @@ trait PersistentQueue[A] extends scala.collection.mutable.Queue[A] transaction.get.get.register(uuid, this) } } + +/** + * Implements a template for a concrete persistent transactional sorted set based storage. + *

+ * Sorting is done based on a zscore. But the computation of zscore has been kept + * outside the abstraction. + *

+ * zscore can be implemented in a variety of ways by the calling class: + *

+ * trait ZScorable {
+ *   def toZScore: Float
+ * }
+ *
+ * class Foo extends ZScorable {
+ *   //.. implemnetation
+ * }
+ * 
+ * Or we can also use views: + *
+ * class Foo {
+ *   //..
+ * }
+ * 
+ * implicit def Foo2Scorable(foo: Foo): ZScorable = new ZScorable {
+ *   def toZScore = {
+ *     //..
+ *   }
+ * }
+ * 
+ * + * and use foo.toZScore to compute the zscore and pass to the APIs. + * + * @author + */ +trait PersistentSortedSet[A] + extends Transactional + with Committable { + + protected val newElems = TransactionalState.newMap[A, Float] + protected val removedElems = TransactionalState.newVector[A] + + val storage: SortedSetStorageBackend[A] + + def commit = { + for ((element, score) <- newElems) storage.zadd(uuid, String.valueOf(score), element) + for (element <- removedElems) storage.zrem(uuid, element) + newElems.clear + removedElems.clear + } + + def +(elem: A, score: Float) = add(elem, score) + + def add(elem: A, score: Float) = { + register + newElems.put(elem, score) + } + + def -(elem: A) = remove(elem) + + def remove(elem: A) = { + register + removedElems.add(elem) + } + + private def inStorage(elem: A): Option[Float] = storage.zscore(uuid, elem) match { + case Some(s) => Some(s.toFloat) + case None => None + } + + def contains(elem: A): Boolean = { + if (newElems contains elem) true + else { + inStorage(elem) match { + case Some(f) => true + case None => false + } + } + } + + def size: Int = newElems.size + storage.zcard(uuid) - removedElems.size + + def zscore(elem: A): Float = { + if (newElems contains elem) newElems.get(elem).get + inStorage(elem) match { + case Some(f) => f + case None => + throw new Predef.NoSuchElementException(elem + " not present") + } + } + + implicit def order(x: (A, Float)) = new Ordered[(A, Float)] { + def compare(that: (A, Float)) = x._2 compare that._2 + } + + def zrange(start: Int, end: Int): List[(A, Float)] = { + // need to operate on the whole range + // get all from the underlying storage + val fromStore = storage.zrangeWithScore(uuid, 0, -1) + val ts = scala.collection.immutable.TreeSet(fromStore: _*) ++ newElems.toList + val l = ts.size + + // -1 means the last element, -2 means the second last + val s = if (start < 0) start + l else start + val e = + if (end < 0) end + l + else if (end >= l) (l - 1) + else end + // slice is open at the end, we need a closed end range + ts.elements.slice(s, e + 1).toList + } + + private def register = { + if (transaction.get.isEmpty) throw new NoTransactionInScopeException + transaction.get.get.register(uuid, this) + } +} diff --git a/akka-persistence/akka-persistence-common/src/main/scala/StorageBackend.scala b/akka-persistence/akka-persistence-common/src/main/scala/StorageBackend.scala index d909f0e4a4..ab0cfaf4d3 100644 --- a/akka-persistence/akka-persistence-common/src/main/scala/StorageBackend.scala +++ b/akka-persistence/akka-persistence-common/src/main/scala/StorageBackend.scala @@ -69,11 +69,15 @@ trait SortedSetStorageBackend[T] extends StorageBackend { // remove item from sorted set identified by name def zrem(name: String, item: T): Boolean - // cardinality of the set idnetified by name + // cardinality of the set identified by name def zcard(name: String): Int - def zscore(name: String, item: T): String + // zscore of the item from sorted set identified by name + def zscore(name: String, item: T): Option[Float] + // zrange from the sorted set identified by name def zrange(name: String, start: Int, end: Int): List[T] -} + // zrange with score from the sorted set identified by name + def zrangeWithScore(name: String, start: Int, end: Int): List[(T, Float)] +} diff --git a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorage.scala b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorage.scala index 1338a9f8d4..b8aada0572 100644 --- a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorage.scala +++ b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorage.scala @@ -15,16 +15,20 @@ object RedisStorage extends Storage { def newVector: PersistentVector[ElementType] = newVector(UUID.newUuid.toString) def newRef: PersistentRef[ElementType] = newRef(UUID.newUuid.toString) override def newQueue: PersistentQueue[ElementType] = newQueue(UUID.newUuid.toString) + override def newSortedSet: PersistentSortedSet[ElementType] = newSortedSet(UUID.newUuid.toString) def getMap(id: String): PersistentMap[ElementType, ElementType] = newMap(id) def getVector(id: String): PersistentVector[ElementType] = newVector(id) def getRef(id: String): PersistentRef[ElementType] = newRef(id) override def getQueue(id: String): PersistentQueue[ElementType] = newQueue(id) + override def getSortedSet(id: String): PersistentSortedSet[ElementType] = newSortedSet(id) def newMap(id: String): PersistentMap[ElementType, ElementType] = new RedisPersistentMap(id) def newVector(id: String): PersistentVector[ElementType] = new RedisPersistentVector(id) def newRef(id: String): PersistentRef[ElementType] = new RedisPersistentRef(id) override def newQueue(id: String): PersistentQueue[ElementType] = new RedisPersistentQueue(id) + override def newSortedSet(id: String): PersistentSortedSet[ElementType] = + new RedisPersistentSortedSet(id) } /** @@ -63,3 +67,14 @@ class RedisPersistentQueue(id: String) extends PersistentQueue[Array[Byte]] { val uuid = id val storage = RedisStorageBackend } + +/** + * Implements a persistent transactional sorted set based on the Redis + * storage. + * + * @author Debasish Ghosh + */ +class RedisPersistentSortedSet(id: String) extends PersistentSortedSet[Array[Byte]] { + val uuid = id + val storage = RedisStorageBackend +} diff --git a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala index 8bca9c6af6..c48c84fa39 100644 --- a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala +++ b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala @@ -364,11 +364,10 @@ private [akka] object RedisStorageBackend extends } } - def zscore(name: String, item: Array[Byte]): String = withErrorHandling { + def zscore(name: String, item: Array[Byte]): Option[Float] = withErrorHandling { db.zscore(new String(encode(name.getBytes)), new String(item)) match { - case None => - throw new Predef.NoSuchElementException(new String(item) + " not present") - case Some(s) => s + case Some(s) => Some(s.toFloat) + case None => None } } @@ -380,6 +379,16 @@ private [akka] object RedisStorageBackend extends s.map(_.get.getBytes) } } + + def zrangeWithScore(name: String, start: Int, end: Int): List[(Array[Byte], Float)] = withErrorHandling { + db.zrangeWithScore( + new String(encode(name.getBytes)), start.toString, end.toString, RedisClient.ASC) match { + case None => + throw new Predef.NoSuchElementException(name + " not present") + case Some(l) => + l.map{ case (elem, score) => (elem.get.getBytes, score.get.toFloat) } + } + } def flushDB = withErrorHandling(db.flushDb) diff --git a/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentActorSpec.scala b/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentActorSpec.scala index 9405789bfd..41ee6fb909 100644 --- a/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentActorSpec.scala +++ b/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentActorSpec.scala @@ -87,7 +87,7 @@ class AccountActor extends Transactor { } @serializable class PersistentFailerActor extends Transactor { - //timeout = 5000 + // timeout = 5000 def receive = { case "Failure" => throw new RuntimeException("expected") diff --git a/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentSortedSetSpec.scala b/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentSortedSetSpec.scala new file mode 100644 index 0000000000..a2abb2cd40 --- /dev/null +++ b/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentSortedSetSpec.scala @@ -0,0 +1,237 @@ +package se.scalablesolutions.akka.persistence.redis + +import org.scalatest.Spec +import org.scalatest.Assertions +import org.scalatest.matchers.ShouldMatchers +import org.scalatest.BeforeAndAfterAll +import org.scalatest.junit.JUnitRunner +import org.junit.runner.RunWith + +import se.scalablesolutions.akka.actor.{Actor, Transactor} + +/** + * A persistent actor based on Redis sortedset storage. + *

+ * Needs a running Redis server. + * @author Debasish Ghosh + */ + +trait ZScorable { + def zscore: Float +} + +case class Hacker(name: String, birth: String) extends ZScorable { + def zscore = birth.toFloat +} + +class SetThresholdViolationException extends RuntimeException + +// add hacker to the set +case class ADD(h: Hacker) + +// remove hacker from set +case class REMOVE(h: Hacker) + +// size of the set +case object SIZE + +// zscore of the hacker +case class SCORE(h: Hacker) + +// zrange +case class RANGE(start: Int, end: Int) + +// add and remove subject to the condition that there will be at least 3 hackers +case class MULTI(add: List[Hacker], rem: List[Hacker], failer: Actor) + +class SortedSetActor extends Transactor { + timeout = 100000 + private lazy val hackers = RedisStorage.newSortedSet + + def receive = { + case ADD(h) => + hackers.+(h.name.getBytes, h.zscore) + reply(true) + + case REMOVE(h) => + hackers.-(h.name.getBytes) + reply(true) + + case SIZE => + reply(hackers.size) + + case SCORE(h) => + reply(hackers.zscore(h.name.getBytes)) + + case RANGE(s, e) => + reply(hackers.zrange(s, e)) + + case MULTI(a, r, failer) => + a.foreach{ h: Hacker => + hackers.+(h.name.getBytes, h.zscore) + } + try { + r.foreach{ h => + if (hackers.size <= 3) + throw new SetThresholdViolationException + hackers.-(h.name.getBytes) + } + } catch { + case e: Exception => + failer !! "Failure" + } + reply((a.size, r.size)) + } +} + +import RedisStorageBackend._ + +@RunWith(classOf[JUnitRunner]) +class RedisPersistentSortedSetSpec extends + Spec with + ShouldMatchers with + BeforeAndAfterAll { + + override def beforeAll { + flushDB + println("** destroyed database") + } + + override def afterAll { + flushDB + println("** destroyed database") + } + + val h1 = Hacker("Alan kay", "1940") + val h2 = Hacker("Richard Stallman", "1953") + val h3 = Hacker("Yukihiro Matsumoto", "1965") + val h4 = Hacker("Claude Shannon", "1916") + val h5 = Hacker("Linus Torvalds", "1969") + val h6 = Hacker("Alan Turing", "1912") + + describe("Add and report cardinality of the set") { + val qa = new SortedSetActor + qa.start + + it("should enter 6 hackers") { + qa !! ADD(h1) + qa !! ADD(h2) + qa !! ADD(h3) + qa !! ADD(h4) + qa !! ADD(h5) + qa !! ADD(h6) + (qa !! SIZE).get.asInstanceOf[Int] should equal(6) + } + + it("should fetch correct scores for hackers") { + (qa !! SCORE(h1)).get.asInstanceOf[Float] should equal(1940.0f) + (qa !! SCORE(h5)).get.asInstanceOf[Float] should equal(1969.0f) + (qa !! SCORE(h6)).get.asInstanceOf[Float] should equal(1912.0f) + } + + it("should fetch proper range") { + (qa !! RANGE(0, 4)).get.asInstanceOf[List[_]].size should equal(5) + (qa !! RANGE(0, 6)).get.asInstanceOf[List[_]].size should equal(6) + } + + it("should remove and throw exception for removing non-existent hackers") { + qa !! REMOVE(h2) + (qa !! SIZE).get.asInstanceOf[Int] should equal(5) + qa !! REMOVE(h3) + (qa !! SIZE).get.asInstanceOf[Int] should equal(4) + val h7 = Hacker("Paul Snively", "1952") + try { + qa !! REMOVE(h7) + } + catch { + case e: Predef.NoSuchElementException => + e.getMessage should endWith("not present") + } + } + + it("should change score for entering the same hacker name with diff score") { + (qa !! SIZE).get.asInstanceOf[Int] should equal(4) + + // same name as h6 + val h7 = Hacker("Alan Turing", "1992") + qa !! ADD(h7) + + // size remains same + (qa !! SIZE).get.asInstanceOf[Int] should equal(4) + + // score updated + (qa !! SCORE(h7)).get.asInstanceOf[Float] should equal(1992.0f) + } + } + + describe("Transaction semantics") { + it("should rollback on exception") { + val qa = new SortedSetActor + qa.start + + val failer = new PersistentFailerActor + failer.start + + (qa !! SIZE).get.asInstanceOf[Int] should equal(0) + val add = List(h1, h2, h3, h4) + val rem = List(h2) + (qa !! MULTI(add, rem, failer)).get.asInstanceOf[Tuple2[Int, Int]] should equal((4,1)) + (qa !! SIZE).get.asInstanceOf[Int] should equal(3) + // size == 3 + + // add 2 more + val add1 = List(h5, h6) + + // remove 3 + val rem1 = List(h1, h3, h4) + try { + qa !! MULTI(add1, rem1, failer) + } catch { case e: Exception => {} + } + (qa !! SIZE).get.asInstanceOf[Int] should equal(3) + } + } + + describe("zrange") { + it ("should report proper range") { + val qa = new SortedSetActor + qa.start + qa !! ADD(h1) + qa !! ADD(h2) + qa !! ADD(h3) + qa !! ADD(h4) + qa !! ADD(h5) + qa !! ADD(h6) + (qa !! SIZE).get.asInstanceOf[Int] should equal(6) + val l = (qa !! RANGE(0, 6)).get.asInstanceOf[List[(Array[Byte], Float)]] + l.map { case (e, s) => (new String(e), s) }.head should equal(("Alan Turing", 1912.0f)) + val h7 = Hacker("Alan Turing", "1992") + qa !! ADD(h7) + (qa !! SIZE).get.asInstanceOf[Int] should equal(6) + val m = (qa !! RANGE(0, 6)).get.asInstanceOf[List[(Array[Byte], Float)]] + m.map { case (e, s) => (new String(e), s) }.head should equal(("Claude Shannon", 1916.0f)) + } + + it ("should report proper rge") { + val qa = new SortedSetActor + qa.start + qa !! ADD(h1) + qa !! ADD(h2) + qa !! ADD(h3) + qa !! ADD(h4) + qa !! ADD(h5) + qa !! ADD(h6) + (qa !! SIZE).get.asInstanceOf[Int] should equal(6) + (qa !! RANGE(0, 5)).get.asInstanceOf[List[_]].size should equal(6) + (qa !! RANGE(0, 6)).get.asInstanceOf[List[_]].size should equal(6) + (qa !! RANGE(0, 3)).get.asInstanceOf[List[_]].size should equal(4) + (qa !! RANGE(0, 1)).get.asInstanceOf[List[_]].size should equal(2) + (qa !! RANGE(0, 0)).get.asInstanceOf[List[_]].size should equal(1) + (qa !! RANGE(3, 1)).get.asInstanceOf[List[_]].size should equal(0) + (qa !! RANGE(0, -1)).get.asInstanceOf[List[_]].size should equal(6) + (qa !! RANGE(0, -2)).get.asInstanceOf[List[_]].size should equal(5) + (qa !! RANGE(0, -4)).get.asInstanceOf[List[_]].size should equal(3) + (qa !! RANGE(-4, -1)).get.asInstanceOf[List[_]].size should equal(4) + } + } +} diff --git a/akka-persistence/akka-persistence-redis/src/test/scala/RedisStorageBackendSpec.scala b/akka-persistence/akka-persistence-redis/src/test/scala/RedisStorageBackendSpec.scala index cfe704c6ba..44081a43c6 100644 --- a/akka-persistence/akka-persistence-redis/src/test/scala/RedisStorageBackendSpec.scala +++ b/akka-persistence/akka-persistence-redis/src/test/scala/RedisStorageBackendSpec.scala @@ -191,10 +191,10 @@ class RedisStorageBackendSpec extends zcard("hackers") should equal(6) - zscore("hackers", "alan turing".getBytes) should equal("1912") - zscore("hackers", "richard stallman".getBytes) should equal("1953") - zscore("hackers", "claude shannon".getBytes) should equal("1916") - zscore("hackers", "linus torvalds".getBytes) should equal("1969") + zscore("hackers", "alan turing".getBytes).get should equal(1912.0f) + zscore("hackers", "richard stallman".getBytes).get should equal(1953.0f) + zscore("hackers", "claude shannon".getBytes).get should equal(1916.0f) + zscore("hackers", "linus torvalds".getBytes).get should equal(1969.0f) val s: List[Array[Byte]] = zrange("hackers", 0, 2) s.size should equal(3) @@ -206,6 +206,10 @@ class RedisStorageBackendSpec extends val t: List[Array[Byte]] = zrange("hackers", 0, -1) t.size should equal(6) t.map(new String(_)) should equal(sorted) + + val u: List[(Array[Byte], Float)] = zrangeWithScore("hackers", 0, -1) + u.size should equal(6) + u.map{ case (e, s) => new String(e) } should equal(sorted) } } } diff --git a/embedded-repo/com/redis/redisclient/1.1/redisclient-1.1.jar b/embedded-repo/com/redis/redisclient/1.1/redisclient-1.1.jar deleted file mode 100644 index a269f15f7aaab12b04c9a2ba8fc4c6572b0f017f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47464 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 Iyb8nv0Q<{W6aWAK diff --git a/embedded-repo/com/redis/redisclient/1.1/redisclient-1.1.pom b/embedded-repo/com/redis/redisclient/1.1/redisclient-1.1.pom deleted file mode 100755 index 16dd81402a..0000000000 --- a/embedded-repo/com/redis/redisclient/1.1/redisclient-1.1.pom +++ /dev/null @@ -1,8 +0,0 @@ - - - 4.0.0 - com.redis - redisclient - 1.1 - jar - diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index cd46dbea5c..783a8d010c 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -240,7 +240,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { } class AkkaRedisProject(info: ProjectInfo) extends DefaultProject(info) { - val redis = "com.redis" % "redisclient" % "1.1" % "compile" + val redis = "com.redis" % "redisclient" % "1.2-SNAPSHOT" % "compile" override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil lazy val dist = deployTask(info, distPath) dependsOn(`package`) describedAs("Deploying") }