2015-06-08 12:26:19 +02:00
/*
2016-02-23 12:58:39 +01:00
* Copyright ( C ) 2009 - 2016 Lightbend Inc . < http : //www.lightbend.com>
2015-06-08 12:26:19 +02:00
*/
package akka.persistence.query
import java.util.concurrent.atomic.AtomicReference
import akka.actor._
import akka.event.Logging
2015-06-08 12:26:19 +02:00
import scala.annotation.tailrec
2015-06-08 12:26:19 +02:00
import scala.util.Failure
2015-08-19 11:14:43 +02:00
import com.typesafe.config.Config
2015-06-08 12:26:19 +02:00
/* *
* Persistence extension for queries .
*/
object PersistenceQuery extends ExtensionId [ PersistenceQuery ] with ExtensionIdProvider {
/* *
* Java API .
*/
override def get ( system : ActorSystem ) : PersistenceQuery = super . get ( system )
def createExtension ( system : ExtendedActorSystem ) : PersistenceQuery = new PersistenceQuery ( system )
def lookup ( ) = PersistenceQuery
/* * INTERNAL API. */
2015-09-14 11:08:22 +02:00
private [ persistence ] case class PluginHolder (
scaladslPlugin : scaladsl . ReadJournal , javadslPlugin : akka . persistence . query . javadsl . ReadJournal )
extends Extension
2015-06-08 12:26:19 +02:00
}
class PersistenceQuery ( system : ExtendedActorSystem ) extends Extension {
import PersistenceQuery._
private val log = Logging ( system , getClass )
/* * Discovered query plugins. */
private val readJournalPluginExtensionIds = new AtomicReference [ Map [ String , ExtensionId [ PluginHolder ] ] ] ( Map . empty )
/* *
2015-09-14 11:08:22 +02:00
* Scala API : Returns the [ [ akka . persistence . query . scaladsl . ReadJournal ] ] specified by the given
* read journal configuration entry .
2015-06-08 12:26:19 +02:00
*/
2015-09-14 11:08:22 +02:00
final def readJournalFor [ T <: scaladsl . ReadJournal ] ( readJournalPluginId : String ) : T =
readJournalPluginFor ( readJournalPluginId ) . scaladslPlugin . asInstanceOf [ T ]
/* *
* Java API : Returns the [ [ akka . persistence . query . javadsl . ReadJournal ] ] specified by the given
* read journal configuration entry .
*/
final def getReadJournalFor [ T <: javadsl . ReadJournal ] ( clazz : Class [ T ] , readJournalPluginId : String ) : T =
readJournalPluginFor ( readJournalPluginId ) . javadslPlugin . asInstanceOf [ T ]
@tailrec private def readJournalPluginFor ( readJournalPluginId : String ) : PluginHolder = {
2015-06-08 12:26:19 +02:00
val configPath = readJournalPluginId
val extensionIdMap = readJournalPluginExtensionIds . get
extensionIdMap . get ( configPath ) match {
case Some ( extensionId ) ⇒
2015-09-14 11:08:22 +02:00
extensionId ( system )
2015-06-08 12:26:19 +02:00
case None ⇒
val extensionId = new ExtensionId [ PluginHolder ] {
2015-09-14 11:08:22 +02:00
override def createExtension ( system : ExtendedActorSystem ) : PluginHolder = {
val provider = createPlugin ( configPath )
PluginHolder ( provider . scaladslReadJournal ( ) , provider . javadslReadJournal ( ) )
}
2015-06-08 12:26:19 +02:00
}
readJournalPluginExtensionIds . compareAndSet ( extensionIdMap , extensionIdMap . updated ( configPath , extensionId ) )
2015-09-14 11:08:22 +02:00
readJournalPluginFor ( readJournalPluginId ) // Recursive invocation.
2015-06-08 12:26:19 +02:00
}
}
2015-09-14 11:08:22 +02:00
private def createPlugin ( configPath : String ) : ReadJournalProvider = {
2016-06-02 14:06:57 +02:00
require (
! isEmpty ( configPath ) && system . settings . config . hasPath ( configPath ) ,
2015-06-08 12:26:19 +02:00
s" 'reference.conf' is missing persistence read journal plugin config path: ' ${ configPath } ' " )
val pluginConfig = system . settings . config . getConfig ( configPath )
val pluginClassName = pluginConfig . getString ( "class" )
2015-06-08 12:26:19 +02:00
log . debug ( s" Create plugin: ${ configPath } ${ pluginClassName } " )
2015-06-08 12:26:19 +02:00
val pluginClass = system . dynamicAccess . getClassFor [ AnyRef ] ( pluginClassName ) . get
2015-10-12 09:32:23 +02:00
def instantiate ( args : collection.immutable.Seq [ ( Class [ _ ] , AnyRef ) ] ) =
system . dynamicAccess . createInstanceFor [ ReadJournalProvider ] ( pluginClass , args )
instantiate ( ( classOf [ ExtendedActorSystem ] , system ) : : ( classOf [ Config ] , pluginConfig ) : : Nil )
. recoverWith { case x : NoSuchMethodException ⇒ instantiate ( ( classOf [ ExtendedActorSystem ] , system ) : : Nil ) }
. recoverWith { case x : NoSuchMethodException ⇒ instantiate ( Nil ) }
2015-09-14 11:08:22 +02:00
. recoverWith {
case ex : Exception ⇒ Failure . apply ( new IllegalArgumentException ( s" Unable to create read journal plugin instance for path [ $configPath ], class [ $pluginClassName ]! " , ex ) )
} . get
2015-06-08 12:26:19 +02:00
}
/* * Check for default or missing identity. */
private def isEmpty ( text : String ) = text == null || text . length == 0
}