2014-12-01 20:07:55 +02:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2014 Typesafe Inc. <http://www.typesafe.com>
|
|
|
|
|
*/
|
2015-04-10 16:49:49 +02:00
|
|
|
package akka.stream
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-04-09 12:21:12 +02:00
|
|
|
import akka.event.Logging
|
|
|
|
|
|
2015-04-10 16:49:49 +02:00
|
|
|
import scala.collection.immutable
|
2015-01-28 14:19:50 +01:00
|
|
|
import akka.stream.impl.Stages.StageModule
|
2015-04-09 12:21:12 +02:00
|
|
|
import akka.japi.function
|
2014-12-01 20:07:55 +02:00
|
|
|
|
|
|
|
|
/**
|
2015-04-09 12:21:12 +02:00
|
|
|
* Holds attributes which can be used to alter [[akka.stream.scaladsl.Flow]] / [[akka.stream.javadsl.Flow]]
|
|
|
|
|
* or [[akka.stream.scaladsl.FlowGraph]] / [[akka.stream.javadsl.FlowGraph]] materialization.
|
2015-04-10 16:49:49 +02:00
|
|
|
*
|
2015-06-23 17:32:55 +02:00
|
|
|
* Note that more attributes for the [[ActorFlowMaterializer]] are defined in [[ActorAttributes]].
|
2014-12-01 20:07:55 +02:00
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
final case class Attributes private (attributeList: immutable.Seq[Attributes.Attribute] = Nil) {
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-06-23 17:32:55 +02:00
|
|
|
import Attributes._
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-04-10 16:49:49 +02:00
|
|
|
/**
|
|
|
|
|
* Java API
|
|
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def getAttributeList(): java.util.List[Attribute] = {
|
2015-04-10 16:49:49 +02:00
|
|
|
import scala.collection.JavaConverters._
|
2015-06-23 17:32:55 +02:00
|
|
|
attributeList.asJava
|
2015-04-10 16:49:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Java API: Get all attributes of a given `Class` or
|
|
|
|
|
* subclass thereof.
|
|
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def getAttributeList[T <: Attribute](c: Class[T]): java.util.List[T] =
|
|
|
|
|
if (attributeList.isEmpty) java.util.Collections.emptyList()
|
2015-04-10 16:49:49 +02:00
|
|
|
else {
|
|
|
|
|
val result = new java.util.ArrayList[T]
|
2015-06-23 17:32:55 +02:00
|
|
|
attributeList.foreach { a ⇒
|
2015-04-10 16:49:49 +02:00
|
|
|
if (c.isInstance(a))
|
2015-06-06 14:13:26 +02:00
|
|
|
result.add(c.cast(a))
|
2015-04-10 16:49:49 +02:00
|
|
|
}
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get first attribute of a given `Class` or subclass thereof.
|
|
|
|
|
* If no such attribute exists the `default` value is returned.
|
|
|
|
|
*/
|
|
|
|
|
def getAttribute[T <: Attribute](c: Class[T], default: T): T =
|
2015-06-23 17:32:55 +02:00
|
|
|
attributeList.find(c.isInstance) match {
|
2015-06-06 14:13:26 +02:00
|
|
|
case Some(a) ⇒ c.cast(a)
|
2015-04-10 16:49:49 +02:00
|
|
|
case None ⇒ default
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 20:07:55 +02:00
|
|
|
/**
|
|
|
|
|
* Adds given attributes to the end of these attributes.
|
|
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def and(other: Attributes): Attributes =
|
|
|
|
|
if (attributeList.isEmpty) other
|
|
|
|
|
else if (other.attributeList.isEmpty) this
|
|
|
|
|
else Attributes(attributeList ++ other.attributeList)
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
/**
|
|
|
|
|
* INTERNAL API
|
|
|
|
|
*/
|
2014-12-01 20:07:55 +02:00
|
|
|
private[akka] def nameLifted: Option[String] =
|
2015-06-23 17:32:55 +02:00
|
|
|
if (attributeList.isEmpty)
|
2015-04-20 21:04:03 +02:00
|
|
|
None
|
|
|
|
|
else {
|
|
|
|
|
val sb = new java.lang.StringBuilder
|
2015-06-23 17:32:55 +02:00
|
|
|
val iter = attributeList.iterator
|
2015-04-20 21:04:03 +02:00
|
|
|
while (iter.hasNext) {
|
|
|
|
|
iter.next() match {
|
|
|
|
|
case Name(name) ⇒
|
|
|
|
|
if (sb.length == 0) sb.append(name)
|
|
|
|
|
else sb.append("-").append(name)
|
|
|
|
|
case _ ⇒
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (sb.length == 0) None
|
|
|
|
|
else Some(sb.toString)
|
|
|
|
|
}
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
/**
|
|
|
|
|
* INTERNAL API
|
|
|
|
|
*/
|
2015-04-10 16:49:49 +02:00
|
|
|
private[akka] def nameOrDefault(default: String = "unknown-operation"): String = nameLifted match {
|
2014-12-01 20:07:55 +02:00
|
|
|
case Some(name) ⇒ name
|
2015-04-10 16:49:49 +02:00
|
|
|
case _ ⇒ default
|
2014-12-01 20:07:55 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
/**
|
|
|
|
|
* INTERNAL API
|
|
|
|
|
*/
|
|
|
|
|
private[akka] def nameOption: Option[String] =
|
2015-06-23 17:32:55 +02:00
|
|
|
attributeList.collectFirst { case Name(name) ⇒ name }
|
2015-03-05 12:21:17 +01:00
|
|
|
|
2015-04-10 16:49:49 +02:00
|
|
|
/**
|
|
|
|
|
* INTERNAL API
|
|
|
|
|
*/
|
2015-04-09 12:21:12 +02:00
|
|
|
private[akka] def logLevels: Option[LogLevels] =
|
2015-06-23 17:32:55 +02:00
|
|
|
attributeList.collectFirst { case l: LogLevels ⇒ l }
|
2015-04-09 12:21:12 +02:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
private[akka] def transform(node: StageModule): StageModule =
|
2015-06-23 17:32:55 +02:00
|
|
|
if ((this eq Attributes.none) || (this eq node.attributes)) node
|
2014-12-01 20:07:55 +02:00
|
|
|
else node.withAttributes(attributes = this and node.attributes)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-10 16:49:49 +02:00
|
|
|
/**
|
2015-06-23 17:32:55 +02:00
|
|
|
* Note that more attributes for the [[ActorFlowMaterializer]] are defined in [[ActorAttributes]].
|
2015-04-10 16:49:49 +02:00
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
object Attributes {
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-04-10 16:49:49 +02:00
|
|
|
trait Attribute
|
2015-02-26 22:42:34 +01:00
|
|
|
final case class Name(n: String) extends Attribute
|
|
|
|
|
final case class InputBuffer(initial: Int, max: Int) extends Attribute
|
2015-04-09 12:21:12 +02:00
|
|
|
final case class LogLevels(onElement: Logging.LogLevel, onFinish: Logging.LogLevel, onFailure: Logging.LogLevel) extends Attribute
|
|
|
|
|
object LogLevels {
|
2015-06-23 17:32:55 +02:00
|
|
|
/** Use to disable logging on certain operations when configuring [[Attributes.LogLevels]] */
|
2015-04-09 12:21:12 +02:00
|
|
|
final val Off: Logging.LogLevel = Logging.levelFor("off").get
|
|
|
|
|
}
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-04-10 16:49:49 +02:00
|
|
|
/**
|
|
|
|
|
* INTERNAL API
|
|
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
private[akka] def apply(attribute: Attribute): Attributes =
|
2014-12-01 20:07:55 +02:00
|
|
|
apply(List(attribute))
|
|
|
|
|
|
2015-06-23 17:32:55 +02:00
|
|
|
val none: Attributes = Attributes()
|
2014-12-01 20:07:55 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Specifies the name of the operation.
|
2015-03-05 12:21:17 +01:00
|
|
|
* If the name is null or empty the name is ignored, i.e. [[#none]] is returned.
|
2014-12-01 20:07:55 +02:00
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def name(name: String): Attributes =
|
2015-03-05 12:21:17 +01:00
|
|
|
if (name == null || name.isEmpty) none
|
2015-06-23 17:32:55 +02:00
|
|
|
else Attributes(Name(name))
|
2014-12-01 20:07:55 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Specifies the initial and maximum size of the input buffer.
|
|
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def inputBuffer(initial: Int, max: Int): Attributes = Attributes(InputBuffer(initial, max))
|
2014-12-01 20:07:55 +02:00
|
|
|
|
2015-04-09 12:21:12 +02:00
|
|
|
/**
|
|
|
|
|
* Java API
|
|
|
|
|
*
|
|
|
|
|
* Configures `log()` stage log-levels to be used when logging.
|
|
|
|
|
* Logging a certain operation can be completely disabled by using [[LogLevels.Off]].
|
|
|
|
|
*
|
|
|
|
|
* Passing in null as any of the arguments sets the level to its default value, which is:
|
|
|
|
|
* `Debug` for `onElement` and `onFinish`, and `Error` for `onFailure`.
|
|
|
|
|
*/
|
|
|
|
|
def createLogLevels(onElement: Logging.LogLevel, onFinish: Logging.LogLevel, onFailure: Logging.LogLevel) =
|
|
|
|
|
logLevels(
|
|
|
|
|
onElement = Option(onElement).getOrElse(Logging.DebugLevel),
|
|
|
|
|
onFinish = Option(onFinish).getOrElse(Logging.DebugLevel),
|
|
|
|
|
onFailure = Option(onFailure).getOrElse(Logging.ErrorLevel))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configures `log()` stage log-levels to be used when logging.
|
|
|
|
|
* Logging a certain operation can be completely disabled by using [[LogLevels.Off]].
|
|
|
|
|
*
|
2015-06-23 17:32:55 +02:00
|
|
|
* See [[Attributes.createLogLevels]] for Java API
|
2015-04-09 12:21:12 +02:00
|
|
|
*/
|
|
|
|
|
def logLevels(onElement: Logging.LogLevel = Logging.DebugLevel, onFinish: Logging.LogLevel = Logging.DebugLevel, onFailure: Logging.LogLevel = Logging.ErrorLevel) =
|
2015-06-23 17:32:55 +02:00
|
|
|
Attributes(LogLevels(onElement, onFinish, onFailure))
|
2015-04-09 12:21:12 +02:00
|
|
|
|
2015-04-10 16:49:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Attributes for the [[ActorFlowMaterializer]].
|
2015-06-23 17:32:55 +02:00
|
|
|
* Note that more attributes defined in [[Attributes]].
|
2015-04-10 16:49:49 +02:00
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
object ActorAttributes {
|
|
|
|
|
import Attributes._
|
2015-04-10 16:49:49 +02:00
|
|
|
final case class Dispatcher(dispatcher: String) extends Attribute
|
|
|
|
|
final case class SupervisionStrategy(decider: Supervision.Decider) extends Attribute
|
|
|
|
|
|
2014-12-01 20:07:55 +02:00
|
|
|
/**
|
|
|
|
|
* Specifies the name of the dispatcher.
|
|
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def dispatcher(dispatcher: String): Attributes = Attributes(Dispatcher(dispatcher))
|
2015-02-04 09:26:32 +01:00
|
|
|
|
|
|
|
|
/**
|
2015-04-10 16:49:49 +02:00
|
|
|
* Scala API: Decides how exceptions from user are to be handled.
|
2015-02-04 09:26:32 +01:00
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def supervisionStrategy(decider: Supervision.Decider): Attributes =
|
|
|
|
|
Attributes(SupervisionStrategy(decider))
|
2015-04-10 16:49:49 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Java API: Decides how exceptions from application code are to be handled.
|
|
|
|
|
*/
|
2015-06-23 17:32:55 +02:00
|
|
|
def withSupervisionStrategy(decider: function.Function[Throwable, Supervision.Directive]): Attributes =
|
|
|
|
|
ActorAttributes.supervisionStrategy(decider.apply _)
|
2015-04-09 12:21:12 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Java API
|
|
|
|
|
*
|
|
|
|
|
* Configures `log()` stage log-levels to be used when logging.
|
|
|
|
|
* Logging a certain operation can be completely disabled by using [[LogLevels.Off]].
|
|
|
|
|
*
|
|
|
|
|
* Passing in null as any of the arguments sets the level to its default value, which is:
|
|
|
|
|
* `Debug` for `onElement` and `onFinish`, and `Error` for `onFailure`.
|
|
|
|
|
*/
|
|
|
|
|
def createLogLevels(onElement: Logging.LogLevel, onFinish: Logging.LogLevel, onFailure: Logging.LogLevel) =
|
|
|
|
|
logLevels(
|
|
|
|
|
onElement = Option(onElement).getOrElse(Logging.DebugLevel),
|
|
|
|
|
onFinish = Option(onFinish).getOrElse(Logging.DebugLevel),
|
|
|
|
|
onFailure = Option(onFailure).getOrElse(Logging.ErrorLevel))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configures `log()` stage log-levels to be used when logging.
|
|
|
|
|
* Logging a certain operation can be completely disabled by using [[LogLevels.Off]].
|
|
|
|
|
*
|
2015-06-23 17:32:55 +02:00
|
|
|
* See [[Attributes.createLogLevels]] for Java API
|
2015-04-09 12:21:12 +02:00
|
|
|
*/
|
|
|
|
|
def logLevels(onElement: Logging.LogLevel = Logging.DebugLevel, onFinish: Logging.LogLevel = Logging.DebugLevel, onFailure: Logging.LogLevel = Logging.ErrorLevel) =
|
2015-06-23 17:32:55 +02:00
|
|
|
Attributes(LogLevels(onElement, onFinish, onFailure))
|
2015-04-09 12:21:12 +02:00
|
|
|
|
2014-12-01 20:07:55 +02:00
|
|
|
}
|