diff options
author | gjoranv <gv@yahoo-inc.com> | 2017-05-19 00:51:34 +0200 |
---|---|---|
committer | gjoranv <gv@yahoo-inc.com> | 2017-05-19 01:02:36 +0200 |
commit | 4bc200ee0c8f3e48fa34d2e741b4691a723c0398 (patch) | |
tree | b333044a38f00572e4192cfc188d2dc4ba782586 /container-di/src/main/scala/com/yahoo/container | |
parent | 55bb871b9bd9f5dac8c65a9c87060b746b7dde2a (diff) |
Wrap component construction in a future, and throw upon timeout.
- Throw ComponentConstructorException for same behaviour as when
a component ctor throws an exception.
- Add test
- Remove unnecessarily duplicated test code.
Diffstat (limited to 'container-di/src/main/scala/com/yahoo/container')
-rw-r--r-- | container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala b/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala index eb0511f3427..5c42626614e 100644 --- a/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala +++ b/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala @@ -13,6 +13,11 @@ import com.yahoo.container.di.componentgraph.core.Node.equalEdges import com.yahoo.container.di.{ConfigKeyT, JavaAnnotation, createKey, makeClassCovariant, preserveStackTrace, removeStackTrace} import com.yahoo.vespa.config.ConfigKey +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.duration._ +import scala.concurrent.{Await, Future, TimeoutException} +import scala.language.postfixOps + /** * @author tonytv * @author gjoranv @@ -90,17 +95,29 @@ class ComponentNode(componentId: ComponentId, case other => other } - val instance = + val instanceFuture = Future { + try { + constructor.newInstance(actualArguments: _*) + } catch { + case e: InvocationTargetException => + throw removeStackTrace(ErrorOrComponentConstructorException(cutStackTraceAtConstructor(e.getCause), s"Error constructing $idAndType")) + } + } + try { - constructor.newInstance(actualArguments: _*) + val instance = Await.result(instanceFuture, ComponentConstructTimeout) + initId(instance) } catch { - case e: InvocationTargetException => - throw removeStackTrace(ErrorOrComponentConstructorException(cutStackTraceAtConstructor(e.getCause), s"Error constructing $idAndType")) + case constructorException: ComponentConstructorException => + throw constructorException + case _:TimeoutException => + throw new ComponentConstructorException(s"Timed out after $ComponentConstructTimeout while constructing component $idAndType.") + case _: InterruptedException => + Thread.currentThread().interrupt() + throw new RuntimeException(s"Interrupted while constructing component $idAndType") } - - initId(instance) } - + private def ErrorOrComponentConstructorException(cause: Throwable, message: String) : Throwable = { if (cause != null && cause.isInstanceOf[Error]) // don't convert Errors to RuntimeExceptions new Error(message, cause) @@ -169,6 +186,9 @@ class ComponentNode(componentId: ComponentId, object ComponentNode { val log = Logger.getLogger(classOf[ComponentNode].getName) + // XXX: var for testing only. Do not reset in production code! + var ComponentConstructTimeout: FiniteDuration = 60 seconds + private def bestConstructor(clazz: Class[AnyRef]) = { val publicConstructors = clazz.getConstructors.asInstanceOf[Array[Constructor[AnyRef]]] |