From 358963f3066acb55515eb31ebf2e727f03705810 Mon Sep 17 00:00:00 2001 From: Debasish Ghosh Date: Thu, 22 Jul 2010 16:57:19 +0530 Subject: [PATCH 1/4] MongoDB based persistent Maps now use Mongo updates. Also upgraded mongo-java driver to 2.0 --- .../src/main/scala/MongoStorageBackend.scala | 6 ++---- project/build/AkkaProject.scala | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala b/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala index d5581b373b..950165567d 100644 --- a/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala +++ b/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala @@ -78,10 +78,8 @@ private[akka] object MongoStorageBackend extends val o = dbo.get(VALUE).asInstanceOf[Map[AnyRef, AnyRef]] o.putAll(m) - // remove existing reference - removeMapStorageFor(name) - // and insert - coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, o)) + val newdbo = new BasicDBObject().append(KEY, name).append(VALUE, o) + coll.update(new BasicDBObject().append(KEY, name), newdbo, true, false) } } } diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 6c770d4e54..4507193de9 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -162,7 +162,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val log4j = "log4j" % "log4j" % "1.2.15" % "compile" - lazy val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" + lazy val mongo = "org.mongodb" % "mongo-java-driver" % "2.0" % "compile" lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive From cd3a90da3cc6e725a742aa4110392f7897e3bf5c Mon Sep 17 00:00:00 2001 From: momania Date: Thu, 22 Jul 2010 18:20:53 +0200 Subject: [PATCH 2/4] WIP --- akka-core/src/test/scala/ScalazSpec.scala | 66 +++++++++++++++++++++++ project/build/AkkaProject.scala | 58 +++++++++++--------- 2 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 akka-core/src/test/scala/ScalazSpec.scala diff --git a/akka-core/src/test/scala/ScalazSpec.scala b/akka-core/src/test/scala/ScalazSpec.scala new file mode 100644 index 0000000000..123f213f10 --- /dev/null +++ b/akka-core/src/test/scala/ScalazSpec.scala @@ -0,0 +1,66 @@ +package se.scalablesolutions.akka.actor + +import org.scalatest.junit.JUnitSuite +import org.junit.Test + +import Actor._ +import org.multiverse.api.latches.StandardLatch +import scalaz._ +import concurrent.{Strategy, Promise} +import java.lang.String +import Scalaz._ +import se.scalablesolutions.akka.config.ScalaConfig.{LifeCycle, Permanent} +import se.scalablesolutions.akka.dispatch.{Future, FutureTimeoutException} +import java.util.concurrent.{Executors, TimeUnit} + +class ScalazSpec extends JUnitSuite { + val actorRef = actorOf(new Actor { + protected def receive = { + case "one" => self.reply(1) + case "error" => TimeUnit.SECONDS.sleep(10) + } + }).start + + @Test def callActorAndGetValidation = { + + implicit val executorService = Executors.newFixedThreadPool(2) + import Strategy.Executor + + val promiseError: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) + val promiseOne: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) + + //[X]Promise[X] <-- Applicative / Monad + //[X]Option[X] <-- Applicative / Monad + //[X]Validation[String, X] <-- Applicative / Monad iff Semigroup[String] + //[X]Promise[Option[X]] <-- Applicative + + val pvi: Promise[ValidationNEL[String, Option[Int]]] = (promiseError |@| promiseOne) { + (v1, v2) => + (v1 |@| v2) { + (o1, o2) => + (o1 |@| o2) { _ + _} + } + } + + println(pvi.get) + + val listOptionInt: List[Option[Int]] = List.fill(5)(1.some) + // val listOptionInt = (listOptionInt.comp) map (_ * 2) + + println(listOptionInt.sequence[Option, Int]) + + } + + def callActor(msg: String): ValidationNEL[String, Option[Int]] = { + try { + val future: Future[Int] = (actorRef !!! msg) + future.await + future.exception match { + case Some((_, t)) => t.getMessage.failNel + case None => future.result.successNel + } + } catch { + case e: FutureTimeoutException => e.getMessage.failNel + } + } +} \ No newline at end of file diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 89685dffd6..ede37d51fd 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -38,16 +38,22 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- - object Repositories { - lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") - lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") +// object Repositories { +// lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") +// lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) - lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") - lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") - lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") - lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") - lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") - } +// lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") +// lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") +// lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") +// lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") +// lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") +// lazy val ScalazRepo = MavenRepository("Scalaz Repo", "http://scala-tools.org/repo-releases") +// } + + val mavenLocal = "Local Maven Repository" at "file:/e:/maven-repository" + + val efgfpNexusReleasesRepository = "Nexus Releases" at "http://nexus/nexus/content/groups/public" + val efgfpNexusSnaphotsRepository = "Nexus Snapshots" at "http://nexus/nexus/content/groups/public-snapshots" // ------------------------------------------------------------------------------------------------------------------- // ModuleConfigurations @@ -55,21 +61,22 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- - import Repositories._ - lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) - lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) - lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) - lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) - lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) - lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) - lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) - lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) - lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) - lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) - lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) - lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) - lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) - lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) +// import Repositories._ +// lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) +// lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) +// lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) +// lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) +// lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) +// lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) +// lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) +// lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) +// lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) +// lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) +// lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) +// lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) +// lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) +// lazy val scalazModuleConfig = ModuleConfiguration("scalaz", ScalazRepo) +// lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) lazy val embeddedRepo = EmbeddedRepo // This is the only exception, because the embedded repo is fast! // ------------------------------------------------------------------------------------------------------------------- @@ -171,6 +178,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val sbinary = "sbinary" % "sbinary" % "2.8.0-0.3.1" % "compile" + lazy val scalaz = "com.googlecode.scalaz" % "scalaz-core_2.8.0" % "5.0" % "compile" + lazy val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" lazy val sjson = "sjson.json" % "sjson" % "0.7-SNAPSHOT-2.8.0" % "compile" @@ -321,6 +330,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val multiverse = Dependencies.multiverse val netty = Dependencies.netty val protobuf = Dependencies.protobuf + val scalaz = Dependencies.scalaz val sbinary = Dependencies.sbinary val sjson = Dependencies.sjson val werkz = Dependencies.werkz From 45514de15eef31d6c06b0b578b8394f42999ee9b Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 11:28:42 +0200 Subject: [PATCH 3/4] Test #307 - Proof schedule continues with retarted actor --- akka-core/src/main/scala/actor/Actor.scala | 10 +- .../src/main/scala/actor/ActorRegistry.scala | 2 +- akka-core/src/test/scala/ScalazSpec.scala | 66 ------ akka-core/src/test/scala/SchedulerSpec.scala | 51 ++++- project/build/AkkaProject.scala | 191 +++++++++++++++--- project/plugins/Plugins.scala | 7 +- 6 files changed, 225 insertions(+), 102 deletions(-) delete mode 100644 akka-core/src/test/scala/ScalazSpec.scala diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index 76adf9c729..244fd8fbc7 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -414,6 +414,14 @@ trait Actor extends Logging { * Is the actor able to handle the message passed in as arguments? */ def isDefinedAt(message: Any): Boolean = base.isDefinedAt(message) + + /** One of the fundamental methods of the ActorsModel + * Actor assumes a new behavior + */ + def become(behavior: Option[Receive]) { + self.hotswap = behavior + self.checkReceiveTimeout // FIXME : how to reschedule receivetimeout on hotswap? + } // ========================================= // ==== INTERNAL IMPLEMENTATION DETAILS ==== @@ -427,7 +435,7 @@ trait Actor extends Logging { } private val lifeCycles: Receive = { - case HotSwap(code) => self.hotswap = code; self.checkReceiveTimeout // FIXME : how to reschedule receivetimeout on hotswap? + case HotSwap(code) => become(code) case Exit(dead, reason) => self.handleTrapExit(dead, reason) case Link(child) => self.link(child) case Unlink(child) => self.unlink(child) diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index 88113a30a0..57b27f08b0 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -159,7 +159,7 @@ object ActorRegistry extends ListenerManagement { /** * Shuts down and unregisters all actors in the system. */ - def shutdownAll = { + def shutdownAll() { log.info("Shutting down all actors in the system...") foreach(_.stop) actorsByUUID.clear diff --git a/akka-core/src/test/scala/ScalazSpec.scala b/akka-core/src/test/scala/ScalazSpec.scala deleted file mode 100644 index 123f213f10..0000000000 --- a/akka-core/src/test/scala/ScalazSpec.scala +++ /dev/null @@ -1,66 +0,0 @@ -package se.scalablesolutions.akka.actor - -import org.scalatest.junit.JUnitSuite -import org.junit.Test - -import Actor._ -import org.multiverse.api.latches.StandardLatch -import scalaz._ -import concurrent.{Strategy, Promise} -import java.lang.String -import Scalaz._ -import se.scalablesolutions.akka.config.ScalaConfig.{LifeCycle, Permanent} -import se.scalablesolutions.akka.dispatch.{Future, FutureTimeoutException} -import java.util.concurrent.{Executors, TimeUnit} - -class ScalazSpec extends JUnitSuite { - val actorRef = actorOf(new Actor { - protected def receive = { - case "one" => self.reply(1) - case "error" => TimeUnit.SECONDS.sleep(10) - } - }).start - - @Test def callActorAndGetValidation = { - - implicit val executorService = Executors.newFixedThreadPool(2) - import Strategy.Executor - - val promiseError: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) - val promiseOne: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) - - //[X]Promise[X] <-- Applicative / Monad - //[X]Option[X] <-- Applicative / Monad - //[X]Validation[String, X] <-- Applicative / Monad iff Semigroup[String] - //[X]Promise[Option[X]] <-- Applicative - - val pvi: Promise[ValidationNEL[String, Option[Int]]] = (promiseError |@| promiseOne) { - (v1, v2) => - (v1 |@| v2) { - (o1, o2) => - (o1 |@| o2) { _ + _} - } - } - - println(pvi.get) - - val listOptionInt: List[Option[Int]] = List.fill(5)(1.some) - // val listOptionInt = (listOptionInt.comp) map (_ * 2) - - println(listOptionInt.sequence[Option, Int]) - - } - - def callActor(msg: String): ValidationNEL[String, Option[Int]] = { - try { - val future: Future[Int] = (actorRef !!! msg) - future.await - future.exception match { - case Some((_, t)) => t.getMessage.failNel - case None => future.result.successNel - } - } catch { - case e: FutureTimeoutException => e.getMessage.failNel - } - } -} \ No newline at end of file diff --git a/akka-core/src/test/scala/SchedulerSpec.scala b/akka-core/src/test/scala/SchedulerSpec.scala index 0fe7c45ea5..7db5727834 100644 --- a/akka-core/src/test/scala/SchedulerSpec.scala +++ b/akka-core/src/test/scala/SchedulerSpec.scala @@ -3,10 +3,11 @@ package se.scalablesolutions.akka.actor import org.scalatest.junit.JUnitSuite import Actor._ import java.util.concurrent.{CountDownLatch, TimeUnit} -import org.junit.{After, Test} +import org.junit.Test +import se.scalablesolutions.akka.config.ScalaConfig._ +import org.multiverse.api.latches.StandardLatch class SchedulerSpec extends JUnitSuite { - @Test def schedulerShouldScheduleMoreThanOnce = { case object Tick @@ -35,4 +36,50 @@ class SchedulerSpec extends JUnitSuite { // should still be 1 left assert(countDownLatch.getCount == 1) } + + /** + * ticket #307 + */ + @Test def actorRestartShouldPickUpScheduleAgain = { + + try { + object Ping + object Crash + + val restartLatch = new StandardLatch + val pingLatch = new CountDownLatch(4) + + val actor = actorOf(new Actor { + self.lifeCycle = Some(LifeCycle(Permanent)) + + def receive = { + case Ping => pingLatch.countDown + case Crash => throw new Exception("CRASH") + } + + override def postRestart(reason: Throwable) = restartLatch.open + }) + + Supervisor( + SupervisorConfig( + RestartStrategy(AllForOne, 3, 1000, + List(classOf[Exception])), + Supervise( + actor, + LifeCycle(Permanent)) + :: Nil)).start + + Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS) + // appx 2 pings before crash + Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS) + + assert(restartLatch.tryAwait(4, TimeUnit.SECONDS)) + // should be enough time for the ping countdown to recover and reach 4 pings + assert(pingLatch.await(4, TimeUnit.SECONDS)) + + } finally { + + Scheduler.shutdown + } + } } diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 03fbc9b80c..4507193de9 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -2,21 +2,21 @@ | Copyright (C) 2009-2010 Scalable Solutions AB | \---------------------------------------------------------------------------*/ -import sbt._ -import sbt.CompileOrder._ - -import spde._ +import com.weiglewilczek.bnd4sbt.BNDPlugin import de.tuxed.codefellow.plugin.CodeFellowPlugin - +import java.io.File import java.util.jar.Attributes import java.util.jar.Attributes.Name._ -import java.io.File +import sbt._ +import sbt.CompileOrder._ +import spde._ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Compile settings // ------------------------------------------------------------------------------------------------------------------- + override def compileOptions = super.compileOptions ++ Seq("-deprecation", "-Xmigration", @@ -30,6 +30,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Deploy/dist settings // ------------------------------------------------------------------------------------------------------------------- + lazy val deployPath = info.projectPath / "deploy" lazy val distPath = info.projectPath / "dist" def distName = "%s_%s-%s.zip".format(name, buildScalaVersion, version) @@ -38,6 +39,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- + object Repositories { lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") @@ -47,20 +49,15 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") - lazy val ScalazRepo = MavenRepository("Scalaz Repo", "http://scala-tools.org/repo-releases") } - val mavenLocal = "Local Maven Repository" at "file:/e:/maven-repository" - - val efgfpNexusReleasesRepository = "Nexus Releases" at "http://nexus/nexus/content/groups/public" - val efgfpNexusSnaphotsRepository = "Nexus Snapshots" at "http://nexus/nexus/content/groups/public-snapshots" - // ------------------------------------------------------------------------------------------------------------------- // ModuleConfigurations // Every dependency that cannot be resolved from the built-in repositories (Maven Central and Scala Tools Releases) // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- + import Repositories._ lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) @@ -75,13 +72,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) - lazy val scalazModuleConfig = ModuleConfiguration("scalaz", ScalazRepo) lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) lazy val embeddedRepo = EmbeddedRepo // This is the only exception, because the embedded repo is fast! // ------------------------------------------------------------------------------------------------------------------- // Versions // ------------------------------------------------------------------------------------------------------------------- + lazy val ATMO_VERSION = "0.6" lazy val CAMEL_VERSION = "2.4.0" lazy val CASSANDRA_VERSION = "0.6.1" @@ -98,6 +95,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------------------------------------------------- + object Dependencies { // Compile @@ -157,29 +155,29 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" - lazy val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() + lazy val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive - lazy val lift = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" - lazy val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + lazy val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + lazy val lift_webkit = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" lazy val log4j = "log4j" % "log4j" % "1.2.15" % "compile" - lazy val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" + lazy val mongo = "org.mongodb" % "mongo-java-driver" % "2.0" % "compile" - lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive() + lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive lazy val netty = "org.jboss.netty" % "netty" % "3.2.1.Final" % "compile" lazy val protobuf = "com.google.protobuf" % "protobuf-java" % "2.3.0" % "compile" + lazy val osgi_core = "org.osgi" % "org.osgi.core" % "4.2.0" + lazy val rabbit = "com.rabbitmq" % "amqp-client" % "1.8.1" % "compile" lazy val redis = "com.redis" % "redisclient" % "2.8.0-1.4" % "compile" lazy val sbinary = "sbinary" % "sbinary" % "2.8.0-0.3.1" % "compile" - lazy val scalaz = "com.googlecode.scalaz" % "scalaz-core_2.8.0" % "5.0" % "compile" - lazy val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" lazy val sjson = "sjson.json" % "sjson" % "0.7-SNAPSHOT-2.8.0" % "compile" @@ -213,6 +211,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Subprojects // ------------------------------------------------------------------------------------------------------------------- + lazy val akka_core = project("akka-core", "akka-core", new AkkaCoreProject(_)) lazy val akka_amqp = project("akka-amqp", "akka-amqp", new AkkaAMQPProject(_), akka_core) lazy val akka_http = project("akka-http", "akka-http", new AkkaHttpProject(_), akka_core, akka_camel) @@ -222,10 +221,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val akka_jta = project("akka-jta", "akka-jta", new AkkaJTAProject(_), akka_core) lazy val akka_kernel = project("akka-kernel", "akka-kernel", new AkkaKernelProject(_), akka_core, akka_http, akka_spring, akka_camel, akka_persistence, akka_amqp) + lazy val akka_osgi = project("akka-osgi", "akka-osgi", new AkkaOSGiParentProject(_)) lazy val akka_samples = project("akka-samples", "akka-samples", new AkkaSamplesParentProject(_)) - // ------------------------------------------------------------ - // Run Akka microkernel using 'sbt run' + use for packaging executable JAR + // ------------------------------------------------------------------------------------------------------------------- + // Miscellaneous + // ------------------------------------------------------------------------------------------------------------------- + override def mainClass = Some("se.scalablesolutions.akka.kernel.Main") override def packageOptions = @@ -307,12 +309,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { " -Dpackaging=jar -DgeneratePom=true" command ! log } - None + None } dependsOn(dist) describedAs("Run mvn install for artifacts in dist.") // ------------------------------------------------------------------------------------------------------------------- // akka-core subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val aopalliance = Dependencies.aopalliance val commons_codec = Dependencies.commons_codec @@ -330,7 +333,6 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val multiverse = Dependencies.multiverse val netty = Dependencies.netty val protobuf = Dependencies.protobuf - val scalaz = Dependencies.scalaz val sbinary = Dependencies.sbinary val sjson = Dependencies.sjson val werkz = Dependencies.werkz @@ -344,6 +346,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-amqp subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val commons_io = Dependencies.commons_io val rabbit = Dependencies.rabbit @@ -357,6 +360,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-http subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaHttpProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val annotation = Dependencies.annotation val atmo = Dependencies.atmo @@ -385,6 +389,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-camel subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val camel_core = Dependencies.camel_core } @@ -392,6 +397,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaPersistenceParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_persistence_common = project("akka-persistence-common", "akka-persistence-common", new AkkaPersistenceCommonProject(_), akka_core) @@ -414,6 +420,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-redis subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val commons_codec = Dependencies.commons_codec val redis = Dependencies.redis @@ -424,6 +431,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-mongo subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaMongoProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val mongo = Dependencies.mongo @@ -433,6 +441,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-cassandra subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCassandraProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val cassandra = Dependencies.cassandra val log4j = Dependencies.log4j @@ -451,11 +460,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-kernel subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaKernelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) // ------------------------------------------------------------------------------------------------------------------- // akka-spring subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaSpringProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val spring_beans = Dependencies.spring_beans val spring_context = Dependencies.spring_context @@ -469,6 +480,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-jta subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaJTAProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val atomikos_transactions = Dependencies.atomikos_transactions val atomikos_transactions_api = Dependencies.atomikos_transactions_api @@ -477,7 +489,112 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { //val atomikos_transactions_util = "com.atomikos" % "transactions-util" % "3.2.3" % "compile" } - // ================= EXAMPLES ================== + // ------------------------------------------------------------------------------------------------------------------- + // OSGi stuff + // ------------------------------------------------------------------------------------------------------------------- + + class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { + lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle", + new AkkaOSGiDependenciesBundleProject(_), akka_kernel, akka_jta) // akka_kernel does not depend on akka_jta (why?) therefore we list akka_jta here + lazy val akka_osgi_assembly = project("akka-osgi-assembly", "akka-osgi-assembly", + new AkkaOSGiAssemblyProject(_), akka_osgi_dependencies_bundle, akka_core, akka_amqp, akka_http, + akka_camel, akka_spring, akka_jta, akka_persistence.akka_persistence_common, + akka_persistence.akka_persistence_redis, akka_persistence.akka_persistence_mongo, + akka_persistence.akka_persistence_cassandra) + } + + class AkkaOSGiDependenciesBundleProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { + override def bndClasspath = compileClasspath + override def bndPrivatePackage = Seq("") + override def bndImportPackage = Seq("*;resolution:=optional") + override def bndExportPackage = Seq( + "org.aopalliance.*;version=1.0.0", + + // Provided by other bundles + "!se.scalablesolutions.akka.*", + "!net.liftweb.*", + "!com.google.inject.*", + "!javax.transaction.*", + "!javax.ws.rs.*", + "!javax.jms.*", + "!javax.transaction,*", + "!org.apache.commons.io.*", + "!org.apache.commons.pool.*", + "!org.codehaus.jackson.*", + "!org.jboss.netty.*", + "!org.springframework.*", + "!org.apache.camel.*", + "!org.fusesource.commons.management.*", + + "*;version=0.0.0") + } + + class AkkaOSGiAssemblyProject(info: ProjectInfo) extends DefaultProject(info) { + + // Scala bundle + val scala_bundle = "com.weiglewilczek.scala-lang-osgi" % "scala-library" % buildScalaVersion % "compile" intransitive + + // Lift bundles +// val lift_util = Dependencies.lift_util.intransitive +// val lift_actor = "net.liftweb" % "lift-actor" % LIFT_VERSION % "compile" intransitive +// val lift_common = "net.liftweb" % "lift-common" % LIFT_VERSION % "compile" intransitive +// val lift_json = "net.liftweb" % "lift-json" % LIFT_VERSION % "compile" intransitive + + // Camel bundles + val camel_core = Dependencies.camel_core.intransitive + val fusesource_commonman = "org.fusesource.commonman" % "commons-management" % "1.0" intransitive + + // Spring bundles + val spring_beans = Dependencies.spring_beans.intransitive + val spring_context = Dependencies.spring_context.intransitive + val spring_aop = "org.springframework" % "spring-aop" % SPRING_VERSION % "compile" intransitive + val spring_asm = "org.springframework" % "spring-asm" % SPRING_VERSION % "compile" intransitive + val spring_core = "org.springframework" % "spring-core" % SPRING_VERSION % "compile" intransitive + val spring_expression = "org.springframework" % "spring-expression" % SPRING_VERSION % "compile" intransitive + val spring_jms = "org.springframework" % "spring-jms" % SPRING_VERSION % "compile" intransitive + val spring_tx = "org.springframework" % "spring-tx" % SPRING_VERSION % "compile" intransitive + + val commons_codec = Dependencies.commons_codec.intransitive + val commons_io = Dependencies.commons_io.intransitive + val commons_pool = Dependencies.commons_pool.intransitive + val guicey = Dependencies.guicey.intransitive + val jackson = Dependencies.jackson.intransitive + val jackson_core = Dependencies.jackson_core.intransitive + val jsr311 = Dependencies.jsr311.intransitive + val jta_1_1 = Dependencies.jta_1_1.intransitive + val netty = Dependencies.netty.intransitive + val commons_fileupload = "commons-fileupload" % "commons-fileupload" % "1.2.1" % "compile" intransitive + val jms_1_1 = "org.apache.geronimo.specs" % "geronimo-jms_1.1_spec" % "1.1.1" % "compile" intransitive + val joda = "joda-time" % "joda-time" % "1.6" intransitive + + override def packageAction = + task { + val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq + val prjs: Seq[Path] = info.dependencies.toSeq.asInstanceOf[Seq[DefaultProject]] map { _.jarPath } + val all = libs ++ prjs + val destination = outputPath / "bundles" + FileUtilities.copyFlat(all, destination, log) + log info "Copied %s bundles to %s".format(all.size, destination) + None + } + + override def artifacts = Set.empty + } + + // ------------------------------------------------------------------------------------------------------------------- + // Test + // ------------------------------------------------------------------------------------------------------------------- + + class AkkaActiveObjectTestProject(info: ProjectInfo) extends DefaultProject(info) { + // testing + val junit = "junit" % "junit" % "4.5" % "test" + val jmock = "org.jmock" % "jmock" % "2.4.0" % "test" + } + + // ------------------------------------------------------------------------------------------------------------------- + // Examples + // ------------------------------------------------------------------------------------------------------------------- + class AkkaSampleAntsProject(info: ProjectInfo) extends DefaultSpdeProject(info) with CodeFellowPlugin { // val scalaToolsSnapshots = ScalaToolsSnapshots override def spdeSourcePath = mainSourcePath / "spde" @@ -488,8 +605,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaSampleLiftProject(info: ProjectInfo) extends DefaultWebProject(info) with DeployProject with CodeFellowPlugin { val commons_logging = Dependencies.commons_logging - val lift = Dependencies.lift val lift_util = Dependencies.lift_util + val lift_webkit = Dependencies.lift_webkit val servlet = Dependencies.servlet // testing @@ -530,6 +647,12 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val jsr311 = Dependencies.jsr311 } + class AkkaSampleOSGiProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { + val osgi_core = Dependencies.osgi_core + override lazy val bndBundleActivator = Some("se.scalablesolutions.akka.sample.osgi.Activator") + override lazy val bndExportPackage = Nil // Necessary because of mixing-in AkkaDefaultProject which exports all ...akka.* packages! + } + class AkkaSamplesParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_sample_ants = project("akka-sample-ants", "akka-sample-ants", new AkkaSampleAntsProject(_), akka_core) @@ -549,10 +672,14 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { new AkkaSampleSecurityProject(_), akka_kernel) lazy val akka_sample_remote = project("akka-sample-remote", "akka-sample-remote", new AkkaSampleRemoteProject(_), akka_kernel) + lazy val akka_sample_osgi = project("akka-sample-osgi", "akka-sample-osgi", + new AkkaSampleOSGiProject(_), akka_core) } - // ------------------------------------------------------------ - // helper functions + // ------------------------------------------------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------------------------------------------------- + def removeDupEntries(paths: PathFinder) = Path.lazyPathFinder { val mapped = paths.get map { p => (p.relativePath, p) } @@ -576,11 +703,11 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { !jar.toString.endsWith("scala-library-2.7.7.jar") ) } - + def akkaArtifacts = descendents(info.projectPath / "dist", "*" + buildScalaVersion + "-" + version + ".jar") // ------------------------------------------------------------ - class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject + class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject trait DeployProject { self: Project => // defines where the deployTask copies jars to @@ -601,4 +728,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { FileUtilities.copyFile(jar, toDir / jar.name, log) } else None } + + trait OSGiProject extends DefaultProject with BNDPlugin { + override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=%s".format(projectVersion.value)) + } } diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index b19b0ebf8c..f0332505da 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -6,6 +6,7 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- object Repositories { + lazy val AquteRepo = "aQute Maven Repository" at "http://www.aqute.biz/repo" lazy val DatabinderRepo = "Databinder Repository" at "http://databinder.net/repo" lazy val EmbeddedRepo = "Embedded Repo" at (info.projectPath / "embedded-repo").asURL.toString } @@ -17,12 +18,14 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- import Repositories._ + lazy val aquteModuleConfig = ModuleConfiguration("biz.aQute", AquteRepo) lazy val codeFellowModuleConfig = ModuleConfiguration("de.tuxed", EmbeddedRepo) lazy val spdeModuleConfig = ModuleConfiguration("us.technically.spde", DatabinderRepo) // ------------------------------------------------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------------------------------------------------- - lazy val codeFellow = "de.tuxed" % "codefellow-plugin" % "0.3" // for code completion and more in VIM - lazy val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" + lazy val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC4" + lazy val codeFellow = "de.tuxed" % "codefellow-plugin" % "0.3" // for code completion and more in VIM + lazy val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" } From 39d81284c28562fe4fdfd825db0c74f50720a552 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 19:06:53 +0200 Subject: [PATCH 4/4] clean end state --- akka-core/src/test/scala/SchedulerSpec.scala | 74 ++++++++++---------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/akka-core/src/test/scala/SchedulerSpec.scala b/akka-core/src/test/scala/SchedulerSpec.scala index 7db5727834..08be87d728 100644 --- a/akka-core/src/test/scala/SchedulerSpec.scala +++ b/akka-core/src/test/scala/SchedulerSpec.scala @@ -3,12 +3,20 @@ package se.scalablesolutions.akka.actor import org.scalatest.junit.JUnitSuite import Actor._ import java.util.concurrent.{CountDownLatch, TimeUnit} -import org.junit.Test import se.scalablesolutions.akka.config.ScalaConfig._ import org.multiverse.api.latches.StandardLatch +import org.junit.Test class SchedulerSpec extends JUnitSuite { - @Test def schedulerShouldScheduleMoreThanOnce = { + + def withCleanEndState(action: => Unit) { + action + Scheduler.restart + ActorRegistry.shutdownAll + } + + + @Test def schedulerShouldScheduleMoreThanOnce = withCleanEndState { case object Tick val countDownLatch = new CountDownLatch(3) @@ -22,7 +30,7 @@ class SchedulerSpec extends JUnitSuite { assert(countDownLatch.await(1, TimeUnit.SECONDS)) } - @Test def schedulerShouldScheduleOnce = { + @Test def schedulerShouldScheduleOnce = withCleanEndState { case object Tick val countDownLatch = new CountDownLatch(2) val tickActor = actor { @@ -40,46 +48,40 @@ class SchedulerSpec extends JUnitSuite { /** * ticket #307 */ - @Test def actorRestartShouldPickUpScheduleAgain = { + @Test def actorRestartShouldPickUpScheduleAgain = withCleanEndState { - try { - object Ping - object Crash + object Ping + object Crash - val restartLatch = new StandardLatch - val pingLatch = new CountDownLatch(4) + val restartLatch = new StandardLatch + val pingLatch = new CountDownLatch(6) - val actor = actorOf(new Actor { - self.lifeCycle = Some(LifeCycle(Permanent)) + val actor = actorOf(new Actor { + self.lifeCycle = Some(LifeCycle(Permanent)) - def receive = { - case Ping => pingLatch.countDown - case Crash => throw new Exception("CRASH") - } + def receive = { + case Ping => pingLatch.countDown + case Crash => throw new Exception("CRASH") + } - override def postRestart(reason: Throwable) = restartLatch.open - }) + override def postRestart(reason: Throwable) = restartLatch.open + }) - Supervisor( - SupervisorConfig( - RestartStrategy(AllForOne, 3, 1000, - List(classOf[Exception])), - Supervise( - actor, - LifeCycle(Permanent)) - :: Nil)).start + Supervisor( + SupervisorConfig( + RestartStrategy(AllForOne, 3, 1000, + List(classOf[Exception])), + Supervise( + actor, + LifeCycle(Permanent)) + :: Nil)).start - Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS) - // appx 2 pings before crash - Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS) + Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS) + // appx 2 pings before crash + Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS) - assert(restartLatch.tryAwait(4, TimeUnit.SECONDS)) - // should be enough time for the ping countdown to recover and reach 4 pings - assert(pingLatch.await(4, TimeUnit.SECONDS)) - - } finally { - - Scheduler.shutdown - } + assert(restartLatch.tryAwait(2, TimeUnit.SECONDS)) + // should be enough time for the ping countdown to recover and reach 6 pings + assert(pingLatch.await(4, TimeUnit.SECONDS)) } }