@@ -8,10 +8,10 @@ import java.util.concurrent.atomic.AtomicReference
88import scala .annotation .compileTimeOnly
99import scala .annotation .unchecked .uncheckedVariance
1010
11- case class ComponentInitializationException (component : Component [_ ], cause : Throwable )
11+ case class ComponentInitializationException (component : Component [? ], cause : Throwable )
1212 extends Exception (s " failed to initialize component ${component.info}" , cause)
1313
14- case class DependencyCycleException (cyclePath : List [Component [_ ]])
14+ case class DependencyCycleException (cyclePath : List [Component [? ]])
1515 extends Exception (s " component dependency cycle detected: \n ${cyclePath.iterator.map(_.info).map(" " + _).mkString(" ->\n " )}" )
1616
1717case class ComponentInfo (
@@ -41,7 +41,7 @@ object ComponentInfo {
4141 */
4242final class Component [+ T ](
4343 val info : ComponentInfo ,
44- deps : => IndexedSeq [Component [_ ]],
44+ deps : => IndexedSeq [Component [? ]],
4545 creator : IndexedSeq [Any ] => ExecutionContext => Future [T ],
4646 destroyer : DestroyFunction [T ] = Component .emptyDestroy,
4747 cachedStorage : Opt [AtomicReference [Future [T ]]] = Opt .Empty ,
@@ -58,12 +58,12 @@ final class Component[+T](
5858 * Returns dependencies of this component extracted from the component definition.
5959 * You can use this to inspect the dependency graph without initializing any components.
6060 */
61- lazy val dependencies : IndexedSeq [Component [_ ]] = deps
61+ lazy val dependencies : IndexedSeq [Component [? ]] = deps
6262
6363 private [this ] val storage : AtomicReference [Future [T ]] =
6464 cachedStorage.getOrElse(new AtomicReference )
6565
66- private def sameStorage (otherStorage : AtomicReference [_ ]): Boolean =
66+ private def sameStorage (otherStorage : AtomicReference [? ]): Boolean =
6767 storage eq otherStorage
6868
6969 // equality based on storage identity is important for cycle detection with cached components
@@ -106,7 +106,7 @@ final class Component[+T](
106106 /**
107107 * Forces a dependency on another component or components.
108108 */
109- def dependsOn (moreDeps : Component [_ ]* ): Component [T ] =
109+ def dependsOn (moreDeps : Component [? ]* ): Component [T ] =
110110 new Component (info, deps ++ moreDeps, creator, destroyer, cachedStorage)
111111
112112 /**
@@ -126,7 +126,7 @@ final class Component[+T](
126126 def destroyWith (destroyFun : T => Unit ): Component [T ] =
127127 asyncDestroyWith(implicit ctx => t => Future (destroyFun(t)))
128128
129- private [di] def cached (cachedStorage : AtomicReference [Future [T @ uncheckedVariance]], info : ComponentInfo ): Component [T ] =
129+ private [di] def cached (cachedStorage : AtomicReference [Future [T @ uncheckedVariance]], info : ComponentInfo ): Component [T ] =
130130 new Component (info, deps, creator, destroyer, Opt (cachedStorage))
131131
132132 /**
@@ -171,10 +171,15 @@ final class Component[+T](
171171 val resultFuture =
172172 Future .traverse(dependencies)(_.doInit(starting = false ))
173173 .flatMap(resolvedDeps => creator(resolvedDeps)(ec))
174+ .flatMap {
175+ case component : AsyncInitializingComponent => component.init().map(_ => component)
176+ case component : InitializingComponent => Future (component.init()).map(_ => component)
177+ case component => Future .successful(component)
178+ }
174179 .recoverNow {
175180 case NonFatal (cause) =>
176181 throw ComponentInitializationException (this , cause)
177- }
182+ }. asInstanceOf [ Future [ T ]]
178183 promise.completeWith(resultFuture)
179184 }
180185 storage.get()
@@ -194,7 +199,7 @@ object Component {
194199 def async [T ](definition : => T ): ExecutionContext => Future [T ] =
195200 implicit ctx => Future (definition)
196201
197- def validateAll (components : Seq [Component [_ ]]): Unit =
202+ def validateAll (components : Seq [Component [? ]]): Unit =
198203 GraphUtils .dfs(components)(
199204 _.dependencies.toList,
200205 onCycle = (node, stack) => {
@@ -210,9 +215,9 @@ object Component {
210215 * (reverse initialization order).
211216 * Independent components are destroyed in parallel, using given `ExecutionContext`.
212217 */
213- def destroyAll (components : Seq [Component [_ ]])(implicit ec : ExecutionContext ): Future [Unit ] = {
214- val reverseGraph = new MHashMap [Component [_ ], MListBuffer [Component [_ ]]]
215- val terminals = new MHashSet [Component [_ ]]
218+ def destroyAll (components : Seq [Component [? ]])(implicit ec : ExecutionContext ): Future [Unit ] = {
219+ val reverseGraph = new MHashMap [Component [? ], MListBuffer [Component [? ]]]
220+ val terminals = new MHashSet [Component [? ]]
216221 GraphUtils .dfs(components)(
217222 _.dependencies.toList,
218223 onEnter = { (c, _) =>
@@ -225,9 +230,9 @@ object Component {
225230 terminals += c
226231 },
227232 )
228- val destroyFutures = new MHashMap [Component [_ ], Future [Unit ]]
233+ val destroyFutures = new MHashMap [Component [? ], Future [Unit ]]
229234
230- def doDestroy (c : Component [_ ]): Future [Unit ] =
235+ def doDestroy (c : Component [? ]): Future [Unit ] =
231236 destroyFutures.getOrElseUpdate(c, Future .traverse(reverseGraph(c))(doDestroy).flatMap(_ => c.doDestroy))
232237
233238 Future .traverse(reverseGraph.keys)(doDestroy).toUnit
0 commit comments