=per #18219 Find plugin constructor automatically

This commit is contained in:
Patrik Nordwall 2015-08-18 16:10:29 +02:00
parent e19d3cb3e8
commit 7ec0493923
7 changed files with 68 additions and 16 deletions

View file

@ -763,6 +763,9 @@ The journal plugin instance is an actor so the methods corresponding to requests
are executed sequentially. It may delegate to asynchronous libraries, spawn futures, or delegate to other
actors to achive parallelism.
The journal plugin class must have a constructor without parameters or constructor with one ``com.typesafe.config.Config``
parameter. The plugin section of the actor system's config will be passed in the config constructor parameter.
Don't run journal tasks/futures on the system default dispatcher, since that might starve other tasks.
Snapshot store plugin API
@ -783,6 +786,9 @@ The snapshot store instance is an actor so the methods corresponding to requests
are executed sequentially. It may delegate to asynchronous libraries, spawn futures, or delegate to other
actors to achive parallelism.
The snapshot store plugin class must have a constructor without parameters or constructor with one ``com.typesafe.config.Config``
parameter. The plugin section of the actor system's config will be passed in the config constructor parameter.
Don't run snapshot store tasks/futures on the system default dispatcher, since that might starve other tasks.
Pre-packaged plugins

View file

@ -713,6 +713,9 @@ The journal plugin instance is an actor so the methods corresponding to requests
are executed sequentially. It may delegate to asynchronous libraries, spawn futures, or delegate to other
actors to achive parallelism.
The journal plugin class must have a constructor without parameters or constructor with one ``com.typesafe.config.Config``
parameter. The plugin section of the actor system's config will be passed in the config constructor parameter.
Don't run journal tasks/futures on the system default dispatcher, since that might starve other tasks.
Snapshot store plugin API
@ -733,6 +736,9 @@ The snapshot store instance is an actor so the methods corresponding to requests
are executed sequentially. It may delegate to asynchronous libraries, spawn futures, or delegate to other
actors to achive parallelism.
The snapshot store plugin class must have a constructor without parameters or constructor with one ``com.typesafe.config.Config``
parameter. The plugin section of the actor system's config will be passed in the config constructor parameter.
Don't run snapshot store tasks/futures on the system default dispatcher, since that might starve other tasks.
Plugin TCK

View file

@ -29,8 +29,6 @@ object PersistenceMultiDocSpec {
class = "akka.persistence.chronicle.ChronicleSyncJournal"
# Custom setting specific for the journal `ChronicleSyncJournal`.
folder = ${user.dir}/store/journal
# Standard persistence extension property: plugin actor uses config injection.
inject-config = true
}
# Configuration entry for the custom snapshot store plugin, see `snapshotPluginId`.
akka.persistence.chronicle.snapshot-store {
@ -38,8 +36,6 @@ object PersistenceMultiDocSpec {
class = "akka.persistence.chronicle.ChronicleSnapshotStore"
# Custom setting specific for the snapshot store `ChronicleSnapshotStore`.
folder = ${user.dir}/store/snapshot
# Standard persistence extension property: plugin actor uses config injection.
inject-config = true
}
//#override-config
"""

View file

@ -773,6 +773,9 @@ The journal plugin instance is an actor so the methods corresponding to requests
are executed sequentially. It may delegate to asynchronous libraries, spawn futures, or delegate to other
actors to achive parallelism.
The journal plugin class must have a constructor without parameters or constructor with one ``com.typesafe.config.Config``
parameter. The plugin section of the actor system's config will be passed in the config constructor parameter.
Don't run journal tasks/futures on the system default dispatcher, since that might starve other tasks.
Snapshot store plugin API
@ -793,6 +796,9 @@ The snapshot store instance is an actor so the methods corresponding to requests
are executed sequentially. It may delegate to asynchronous libraries, spawn futures, or delegate to other
actors to achive parallelism.
The snapshot store plugin class must have a constructor without parameters or constructor with one ``com.typesafe.config.Config``
parameter. The plugin section of the actor system's config will be passed in the config constructor parameter.
Don't run snapshot store tasks/futures on the system default dispatcher, since that might starve other tasks.
Plugin TCK

View file

@ -6,13 +6,15 @@
# Make your edits in your application.conf in order to override these settings.
# Note that both journal and snapshot store plugin configuration entries require few fields:
# `class` : Fully qualified class name providing journal-plugin-api or snapshot-store-plugin-api implementation.
# `inject-config` : Plugin actor has a constructor which expects plugin configuration entry. This boolean field is optional.
# `class` : Fully qualified class name providing journal-plugin-api or snapshot-store-plugin-api implementation,
# The class must have a constructor without parameters or constructor with
# one `com.typesafe.config.Config` parameter.
# `plugin-dispatcher` : Absolute configuration path to the akka dispatcher configuration entry. This string field is optional.
# Note that journal and snapshot store plugins included with the extension are suitable for testing purposes only.
# You should change extension defaults or override `journalPluginId` and `snapshotPluginId` in the persistent actor or view.
# Directory of persistence journal and snapshot store plugins is available at the Akka Community Projects page http://akka.io/community/
# Directory of persistence journal and snapshot store plugins is available at the Akka Community Projects page
# http://akka.io/community/
# Default persistence extension settings.
akka.persistence {
@ -89,10 +91,6 @@ akka.persistence {
# Dispatcher for message replay.
replay-dispatcher = "akka.persistence.dispatchers.default-replay-dispatcher"
# Set this to true if plugin actor has a constructor which expects plugin
# configuration entry.
inject-config = false
# Maximum size of a persistent message batch written to the journal.
max-message-batch-size = 200
@ -130,8 +128,6 @@ akka.persistence {
# Dispatcher for the plugin actor.
plugin-dispatcher = "akka.persistence.dispatchers.default-plugin-dispatcher"
inject-config = false
circuit-breaker {
max-failures = 5
call-timeout = 20s

View file

@ -14,6 +14,8 @@ import com.typesafe.config.Config
import scala.annotation.tailrec
import scala.concurrent.duration._
import java.util.Locale
import akka.util.Reflect
import scala.util.control.NonFatal
/**
* Persistence configuration.
@ -254,9 +256,11 @@ class Persistence(val system: ExtendedActorSystem) extends Extension {
val pluginClassName = pluginConfig.getString("class")
log.debug(s"Create plugin: $pluginActorName $pluginClassName")
val pluginClass = system.dynamicAccess.getClassFor[Any](pluginClassName).get
val pluginInjectConfig = pluginConfig.getBoolean("inject-config")
val pluginDispatcherId = pluginConfig.getString("plugin-dispatcher")
val pluginActorArgs = if (pluginInjectConfig) List(pluginConfig) else Nil
val pluginActorArgs = try {
Reflect.findConstructor(pluginClass, List(pluginConfig)) // will throw if not found
List(pluginConfig)
} catch { case NonFatal(_) Nil } // otherwise use empty constructor
val pluginActorProps = Props(Deploy(dispatcher = pluginDispatcherId), pluginClass, pluginActorArgs)
system.systemActorOf(pluginActorProps, pluginActorName)
}

View file

@ -0,0 +1,38 @@
/**
* Copyright (C) 2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.persistence
import akka.persistence.journal.inmem.InmemJournal
import com.typesafe.config.Config
import akka.testkit.ImplicitSender
import akka.actor.Actor
object LoadJournalSpec {
case object GetConfig
class JournalWithConfig(val config: Config) extends InmemJournal {
override def receivePluginInternal: Actor.Receive = {
case GetConfig sender() ! config
}
}
}
class LoadJournalSpec extends PersistenceSpec(PersistenceSpec.config("inmem", "LoadJournalSpec", extraConfig = Some(
"""
akka.persistence.journal.inmem.class = "akka.persistence.LoadJournalSpec$JournalWithConfig"
akka.persistence.journal.inmem.extra-property = 17
"""))) with ImplicitSender {
import LoadJournalSpec._
"A journal with config parameter" must {
"be created with plugin config" in {
val journalRef = Persistence(system).journalFor("akka.persistence.journal.inmem")
journalRef ! GetConfig
expectMsgType[Config].getInt("extra-property") should be(17)
}
}
}