From a9371c229b977370cbbe84ff0b01d5ddfcb944e6 Mon Sep 17 00:00:00 2001
From: debasishg
Date: Mon, 11 Jan 2010 15:30:38 +0530
Subject: [PATCH] Implemented persistent transactional queue with Redis backend
---
.../src/main/scala/Storage.scala | 129 +++++++++++++++++
.../src/main/scala/StorageBackend.scala | 35 +++++
.../src/main/scala/RedisStorage.scala | 18 ++-
.../src/main/scala/RedisStorageBackend.scala | 87 ++++++++++++
.../src/test/scala/RedisPersistentQSpec.scala | 133 ++++++++++++++++++
.../test/scala/RedisStorageBackendSpec.scala | 53 +++++++
.../redisclient/1.0.1/redisclient-1.0.1.jar | Bin 42194 -> 50730 bytes
7 files changed, 453 insertions(+), 2 deletions(-)
create mode 100644 akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentQSpec.scala
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 cac0004879..78cdd5c207 100644
--- a/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
+++ b/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
@@ -40,6 +40,7 @@ class NoTransactionInScopeException extends RuntimeException
*
*
* @author Jonas Bonér
+ * @author Debasish Ghosh
*/
trait Storage {
type ElementType
@@ -47,14 +48,17 @@ trait Storage {
def newMap: PersistentMap[ElementType, ElementType]
def newVector: PersistentVector[ElementType]
def newRef: PersistentRef[ElementType]
+ def newQueue: PersistentQueue[ElementType]
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]
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]
}
@@ -269,3 +273,128 @@ trait PersistentRef[T] extends Transactional with Committable {
currentTransaction.get.get.register(uuid, this)
}
}
+
+/**
+ * Implementation of PersistentQueue for every concrete
+ * storage will have the same workflow. This abstracts the workflow.
+ *
+ * Enqueue is simpler, we just have to record the operation in a local
+ * transactional store for playback during commit. This store
+ * enqueueNDequeuedEntries stores the entire history of enqueue
+ * and dequeue that will be played at commit on the underlying store.
+ *
+ * The main challenge with dequeue is that we need to return the element
+ * that has been dequeued. Hence in addition to the above store, we need to
+ * have another local queue that actually does the enqueue dequeue operations
+ * that take place only during this transaction. This gives us the
+ * element that will be dequeued next from the set of elements enqueued
+ * during this transaction.
+ *
+ * The third item that we need is an index to the underlying storage element
+ * that may also have to be dequeued as part of the current transaction. This
+ * is modeled using a ref to an Int that points to elements in the underlyinng store.
+ *
+ * Subclasses just need to provide the actual concrete instance for the
+ * abstract val storage.
+ *
+ * @author Debasish Ghosh
+ */
+trait PersistentQueue[A] extends scala.collection.mutable.Queue[A]
+ with Transactional with Committable with Logging {
+
+ abstract case class QueueOp
+ case object ENQ extends QueueOp
+ case object DEQ extends QueueOp
+
+ import scala.collection.immutable.Queue
+
+ // current trail that will be played on commit to the underlying store
+ protected val enqueuedNDequeuedEntries = TransactionalState.newVector[(Option[A], QueueOp)]
+ protected val shouldClearOnCommit = TransactionalRef[Boolean]()
+
+ // local queue that will record all enqueues and dequeues in the current txn
+ protected val localQ = TransactionalRef[Queue[A]]()
+
+ // keeps a pointer to the underlying storage for the enxt candidate to be dequeued
+ protected val pickMeForDQ = TransactionalRef[Int]()
+
+ localQ.swap(Queue.Empty)
+ pickMeForDQ.swap(0)
+
+ // to be concretized in subclasses
+ val storage: QueueStorageBackend[A]
+
+ def commit = {
+ enqueuedNDequeuedEntries.toList.foreach { e =>
+ e._2 match {
+ case ENQ => storage.enqueue(uuid, e._1.get)
+ case DEQ => storage.dequeue(uuid)
+ }
+ }
+ if (shouldClearOnCommit.isDefined && shouldClearOnCommit.get.get) {
+ storage.remove(uuid)
+ }
+ enqueuedNDequeuedEntries.clear
+ localQ.swap(Queue.Empty)
+ pickMeForDQ.swap(0)
+ }
+
+ override def enqueue(elems: A*) {
+ register
+ elems.foreach(e => {
+ enqueuedNDequeuedEntries.add((Some(e), ENQ))
+ localQ.get.get.enqueue(e)
+ })
+ }
+
+ override def dequeue: A = {
+ register
+ // record for later playback
+ enqueuedNDequeuedEntries.add((None, DEQ))
+
+ val i = pickMeForDQ.get.get
+ if (i < storage.size(uuid)) {
+ // still we can DQ from storage
+ pickMeForDQ.swap(i + 1)
+ storage.peek(uuid, i, 1)(0)
+ } else {
+ // check we have transient candidates in localQ for DQ
+ if (localQ.get.get.isEmpty == false) {
+ val (a, q) = localQ.get.get.dequeue
+ localQ.swap(q)
+ a
+ }
+ else
+ throw new NoSuchElementException("trying to dequeue from empty queue")
+ }
+ }
+
+ override def clear = {
+ register
+ shouldClearOnCommit.swap(true)
+ localQ.swap(Queue.Empty)
+ pickMeForDQ.swap(0)
+ }
+
+ override def size: Int = try {
+ storage.size(uuid) + localQ.get.get.length
+ } catch { case e: Exception => 0 }
+
+ override def isEmpty: Boolean =
+ size == 0
+
+ override def +=(elem: A): Unit = enqueue(elem)
+ override def ++=(elems: Iterator[A]): Unit = enqueue(elems.toList: _*)
+ override def ++=(elems: Iterable[A]): Unit = this ++= elems.elements
+
+ override def dequeueFirst(p: A => Boolean): Option[A] =
+ throw new UnsupportedOperationException("dequeueFirst not supported")
+
+ override def dequeueAll(p: A => Boolean): Seq[A] =
+ throw new UnsupportedOperationException("dequeueAll not supported")
+
+ private def register = {
+ if (currentTransaction.get.isEmpty) throw new NoTransactionInScopeException
+ currentTransaction.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 e616b0599a..94233acd0a 100644
--- a/akka-persistence/akka-persistence-common/src/main/scala/StorageBackend.scala
+++ b/akka-persistence/akka-persistence-common/src/main/scala/StorageBackend.scala
@@ -34,3 +34,38 @@ trait RefStorageBackend[T] extends StorageBackend {
def insertRefStorageFor(name: String, element: T)
def getRefStorageFor(name: String): Option[T]
}
+
+// for Queue
+trait QueueStorageBackend[T] extends StorageBackend {
+ // add to the end of the queue
+ def enqueue(name: String, item: T): Boolean
+
+ // pop from the front of the queue
+ def dequeue(name: String): Option[T]
+
+ // get the size of the queue
+ def size(name: String): Int
+
+ // return an array of items currently stored in the queue
+ // start is the item to begin, count is how many items to return
+ def peek(name: String, start: Int, count: Int): List[T]
+
+ // completely delete the queue
+ def remove(name: String): Boolean
+}
+
+trait SortedSetStorageBackend[T] extends StorageBackend {
+ // add item to sorted set identified by name
+ def zadd(name: String, zscore: String, item: T): Boolean
+
+ // remove item from sorted set identified by name
+ def zrem(name: String, item: T): Boolean
+
+ // cardinality of the set idnetified by name
+ def zcard(name: String): Int
+
+ def zscore(name: String, item: T): String
+
+ def zrange(name: String, start: Int, end: Int): List[T]
+}
+
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 0eba6dbb62..886245d147 100644
--- a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorage.scala
+++ b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorage.scala
@@ -12,18 +12,21 @@ object RedisStorage extends Storage {
def newMap: PersistentMap[ElementType, ElementType] = newMap(Uuid.newUuid.toString)
def newVector: PersistentVector[ElementType] = newVector(Uuid.newUuid.toString)
def newRef: PersistentRef[ElementType] = newRef(Uuid.newUuid.toString)
+ def newQueue: PersistentQueue[ElementType] = newQueue(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)
+ def getQueue(id: String): PersistentQueue[ElementType] = newQueue(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)
+ def newQueue(id: String): PersistentQueue[ElementType] = new RedisPersistentQueue(id)
}
/**
- * Implements a persistent transactional map based on the MongoDB document storage.
+ * Implements a persistent transactional map based on the Redis storage.
*
* @author Debasish Ghosh
*/
@@ -34,7 +37,7 @@ class RedisPersistentMap(id: String) extends PersistentMap[Array[Byte], Array[By
/**
* Implements a persistent transactional vector based on the Redis
- * document storage.
+ * storage.
*
* @author Debasish Ghosh
*/
@@ -47,3 +50,14 @@ class RedisPersistentRef(id: String) extends PersistentRef[Array[Byte]] {
val uuid = id
val storage = RedisStorageBackend
}
+
+/**
+ * Implements a persistent transactional queue based on the Redis
+ * storage.
+ *
+ * @author Debasish Ghosh
+ */
+class RedisPersistentQueue(id: String) extends PersistentQueue[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 802319cfad..00a44d0513 100644
--- a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala
+++ b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala
@@ -38,6 +38,8 @@ private [akka] object RedisStorageBackend extends
MapStorageBackend[Array[Byte], Array[Byte]] with
VectorStorageBackend[Array[Byte]] with
RefStorageBackend[Array[Byte]] with
+ QueueStorageBackend[Array[Byte]] with
+ SortedSetStorageBackend[Array[Byte]] with
Logging {
val REDIS_SERVER_HOSTNAME = config.getString("akka.storage.redis.hostname", "127.0.0.1")
@@ -246,6 +248,91 @@ private [akka] object RedisStorageBackend extends
case Some(s) => Some(s.getBytes)
}
}
+
+ // add to the end of the queue
+ def enqueue(name: String, item: Array[Byte]): Boolean = {
+ db.pushTail(new String(encode(name.getBytes)), new String(item))
+ }
+
+ // pop from the front of the queue
+ def dequeue(name: String): Option[Array[Byte]] = {
+ db.popHead(new String(encode(name.getBytes))) match {
+ case None =>
+ throw new Predef.NoSuchElementException(name + " not present")
+ case Some(s) =>
+ Some(s.getBytes)
+ }
+ }
+
+ // get the size of the queue
+ def size(name: String): Int = {
+ db.listLength(new String(encode(name.getBytes))) match {
+ case None =>
+ throw new Predef.NoSuchElementException(name + " not present")
+ case Some(l) => l
+ }
+ }
+
+ // return an array of items currently stored in the queue
+ // start is the item to begin, count is how many items to return
+ def peek(name: String, start: Int, count: Int): List[Array[Byte]] = count match {
+ case 1 =>
+ db.listIndex(new String(encode(name.getBytes)), start) match {
+ case None =>
+ throw new Predef.NoSuchElementException("No element at " + start)
+ case Some(s) =>
+ List(s.getBytes)
+ }
+ case n =>
+ db.listRange(new String(encode(name.getBytes)), start, start + count - 1) match {
+ case None =>
+ throw new Predef.NoSuchElementException(
+ "No element found between " + start + " and " + (start + count - 1))
+ case Some(es) =>
+ es.map(_.getBytes)
+ }
+ }
+
+ // completely delete the queue
+ def remove(name: String): Boolean = {
+ db.delete(new String(encode(name.getBytes)))
+ }
+
+ // add item to sorted set identified by name
+ def zadd(name: String, zscore: String, item: Array[Byte]): Boolean = {
+ db.zAdd(new String(encode(name.getBytes)), zscore, new String(item))
+ }
+
+ // remove item from sorted set identified by name
+ def zrem(name: String, item: Array[Byte]): Boolean = {
+ db.zRem(new String(encode(name.getBytes)), new String(item))
+ }
+
+ // cardinality of the set identified by name
+ def zcard(name: String): Int = {
+ db.zCard(new String(encode(name.getBytes))) match {
+ case None =>
+ throw new Predef.NoSuchElementException(name + " not present")
+ case Some(l) => l
+ }
+ }
+
+ def zscore(name: String, item: Array[Byte]): String = {
+ 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
+ }
+ }
+
+ def zrange(name: String, start: Int, end: Int): List[Array[Byte]] = {
+ db.zRange(new String(encode(name.getBytes)), start.toString, end.toString, SocketOperations.ASC, false) match {
+ case None =>
+ throw new Predef.NoSuchElementException(name + " not present")
+ case Some(s) =>
+ s.map(_.getBytes)
+ }
+ }
def flushDB = db.flushDb
}
diff --git a/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentQSpec.scala b/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentQSpec.scala
new file mode 100644
index 0000000000..2adc980aad
--- /dev/null
+++ b/akka-persistence/akka-persistence-redis/src/test/scala/RedisPersistentQSpec.scala
@@ -0,0 +1,133 @@
+package se.scalablesolutions.akka.state
+
+import junit.framework.TestCase
+
+import org.junit.{Test, Before}
+import org.junit.Assert._
+
+import se.scalablesolutions.akka.actor.{Actor, Transactor}
+
+/**
+ * A persistent actor based on Redis queue storage.
+ *
+ * Needs a running Redis server.
+ * @author Debasish Ghosh
+ */
+
+case class NQ(accountNo: String)
+case class DQ
+case class MNDQ(accountNos: List[String], noOfDQs: Int, failer: Actor)
+case class SZ
+
+class QueueActor extends Transactor {
+ private val accounts = RedisStorage.newQueue
+
+ def receive = {
+ // enqueue
+ case NQ(accountNo) =>
+ accounts.enqueue(accountNo.getBytes)
+ reply(true)
+
+ // dequeue
+ case DQ =>
+ val d = new String(accounts.dequeue)
+ reply(d)
+
+ // multiple NQ and DQ
+ case MNDQ(enqs, no, failer) =>
+ accounts.enqueue(enqs.map(_.getBytes): _*)
+ try {
+ (1 to no).foreach(e => accounts.dequeue)
+ } catch {
+ case e: Exception =>
+ failer !! "Failure"
+ }
+ reply(true)
+
+ // size
+ case SZ =>
+ reply(accounts.size)
+ }
+}
+
+class RedisPersistentQSpec extends TestCase {
+ @Test
+ def testSuccessfulNQ = {
+ val qa = new QueueActor
+ qa.start
+ qa !! NQ("a-123")
+ qa !! NQ("a-124")
+ qa !! NQ("a-125")
+ assertEquals(3, (qa !! SZ).get)
+ }
+
+ @Test
+ def testSuccessfulDQ = {
+ val qa = new QueueActor
+ qa.start
+ qa !! NQ("a-123")
+ qa !! NQ("a-124")
+ qa !! NQ("a-125")
+ assertEquals(3, (qa !! SZ).get)
+ assertEquals("a-123", (qa !! DQ).get)
+ assertEquals("a-124", (qa !! DQ).get)
+ assertEquals("a-125", (qa !! DQ).get)
+ assertEquals(0, (qa !! SZ).get)
+ }
+
+ @Test
+ def testSuccessfulMNDQ = {
+ val qa = new QueueActor
+ qa.start
+ val failer = new PersistentFailerActor
+ failer.start
+
+ qa !! NQ("a-123")
+ qa !! NQ("a-124")
+ qa !! NQ("a-125")
+ assertEquals(3, (qa !! SZ).get)
+ assertEquals("a-123", (qa !! DQ).get)
+ assertEquals(2, (qa !! SZ).get)
+ qa !! MNDQ(List("a-126", "a-127"), 2, failer)
+ assertEquals(2, (qa !! SZ).get)
+ }
+
+ @Test
+ def testMixedMNDQ = {
+ val qa = new QueueActor
+ qa.start
+ val failer = new PersistentFailerActor
+ failer.start
+
+ // 3 enqueues
+ qa !! NQ("a-123")
+ qa !! NQ("a-124")
+ qa !! NQ("a-125")
+
+ assertEquals(3, (qa !! SZ).get)
+
+ // dequeue 1
+ assertEquals("a-123", (qa !! DQ).get)
+
+ // size == 2
+ assertEquals(2, (qa !! SZ).get)
+
+ // enqueue 2, dequeue 2 => size == 2
+ qa !! MNDQ(List("a-126", "a-127"), 2, failer)
+ assertEquals(2, (qa !! SZ).get)
+
+ // enqueue 2 => size == 4
+ qa !! NQ("a-128")
+ qa !! NQ("a-129")
+ assertEquals(4, (qa !! SZ).get)
+
+ // enqueue 1 => size 5
+ // dequeue 6 => fail transaction
+ // size should remain 4
+ try {
+ qa !! MNDQ(List("a-130"), 6, failer)
+ } catch { case e: Exception => {} }
+
+ assertEquals(4, (qa !! SZ).get)
+ }
+}
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 cd91d4a591..504a0e114d 100644
--- a/akka-persistence/akka-persistence-redis/src/test/scala/RedisStorageBackendSpec.scala
+++ b/akka-persistence/akka-persistence-redis/src/test/scala/RedisStorageBackendSpec.scala
@@ -113,6 +113,59 @@ class RedisStorageBackendSpec extends
n.fromBytes(getRefStorageFor("T-4").get) should equal(n)
}
}
+
+ describe("store and query in queue") {
+ it("should give proper queue semantics") {
+ enqueue("T-5", "alan kay".getBytes)
+ enqueue("T-5", "alan turing".getBytes)
+ enqueue("T-5", "richard stallman".getBytes)
+ enqueue("T-5", "yukihiro matsumoto".getBytes)
+ enqueue("T-5", "claude shannon".getBytes)
+ enqueue("T-5", "linus torvalds".getBytes)
+
+ RedisStorageBackend.size("T-5") should equal(6)
+
+ new String(dequeue("T-5").get) should equal("alan kay")
+ new String(dequeue("T-5").get) should equal("alan turing")
+
+ RedisStorageBackend.size("T-5") should equal(4)
+
+ val l = peek("T-5", 0, 3)
+ l.size should equal(3)
+ new String(l(0)) should equal("richard stallman")
+ new String(l(1)) should equal("yukihiro matsumoto")
+ new String(l(2)) should equal("claude shannon")
+ }
+ }
+
+ describe("store and query in sorted set") {
+ it("should give proper sorted set semantics") {
+ zadd("hackers", "1965", "yukihiro matsumoto".getBytes)
+ zadd("hackers", "1953", "richard stallman".getBytes)
+ zadd("hackers", "1916", "claude shannon".getBytes)
+ zadd("hackers", "1969", "linus torvalds".getBytes)
+ zadd("hackers", "1940", "alan kay".getBytes)
+ zadd("hackers", "1912", "alan turing".getBytes)
+
+ 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")
+
+ val s: List[Array[Byte]] = zrange("hackers", 0, 2)
+ s.size should equal(3)
+ s.map(new String(_)) should equal(List("alan turing", "claude shannon", "alan kay"))
+
+ var sorted: List[String] =
+ List("alan turing", "claude shannon", "alan kay", "richard stallman", "yukihiro matsumoto", "linus torvalds")
+
+ val t: List[Array[Byte]] = zrange("hackers", 0, -1)
+ t.size should equal(6)
+ t.map(new String(_)) should equal(sorted)
+ }
+ }
}
case class Name(id: Int, name: String, address: String)
diff --git a/embedded-repo/com/redis/redisclient/1.0.1/redisclient-1.0.1.jar b/embedded-repo/com/redis/redisclient/1.0.1/redisclient-1.0.1.jar
index d4a293effa9c046fd41993742f5b23d8e5fc9c97..ec9c6c8ab44d2552946c18f1ae0daee03f2570c4 100644
GIT binary patch
delta 21078
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