summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--component/src/main/java/com/yahoo/component/AbstractComponent.java3
-rw-r--r--container-di/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java8
-rw-r--r--container-di/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java32
-rwxr-xr-xdocumentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java2
4 files changed, 41 insertions, 4 deletions
diff --git a/component/src/main/java/com/yahoo/component/AbstractComponent.java b/component/src/main/java/com/yahoo/component/AbstractComponent.java
index 7fc828becb5..163a2b0b7ef 100644
--- a/component/src/main/java/com/yahoo/component/AbstractComponent.java
+++ b/component/src/main/java/com/yahoo/component/AbstractComponent.java
@@ -124,7 +124,8 @@ public class AbstractComponent implements Component {
* <p>
* All other calls to this component is completed before this method is called.
* It will only be called once. It should block while doing cleanup tasks and return when
- * this class is ready for garbage collection.
+ * this class is ready for garbage collection. This method is called in reverse dependency order,
+ * so a component will be deconstructed after any other components it is injected into.
* <p>
* This default implementation does nothing.
*/
diff --git a/container-di/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java b/container-di/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java
index 2e4db01fb1b..a054ef5ffe0 100644
--- a/container-di/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java
+++ b/container-di/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java
@@ -15,6 +15,8 @@ import com.yahoo.config.ConfigInstance;
import com.yahoo.container.di.componentgraph.Provider;
import com.yahoo.container.di.componentgraph.cycle.CycleFinder;
import com.yahoo.container.di.componentgraph.cycle.Graph;
+
+import java.util.Collections;
import java.util.logging.Level;
import com.yahoo.vespa.config.ConfigKey;
@@ -164,8 +166,10 @@ public class ComponentGraph {
}
}
- public Collection<Object> allConstructedComponentsAndProviders() {
- return nodes().stream().map(node -> node.constructedInstance().get()).collect(Collectors.toList());
+ public List<Object> allConstructedComponentsAndProviders() {
+ List<Node> orderedNodes = topologicalSort(nodes());
+ Collections.reverse(orderedNodes);
+ return orderedNodes.stream().map(node -> node.constructedInstance().get()).collect(Collectors.toList());
}
private void completeComponentRegistryNode(ComponentRegistryNode registry) {
diff --git a/container-di/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java b/container-di/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java
index e7b269e5172..2a30d71c338 100644
--- a/container-di/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java
+++ b/container-di/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java
@@ -27,6 +27,7 @@ import org.junit.Test;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -87,6 +88,28 @@ public class ComponentGraphTest {
}
@Test
+ public void all_created_components_are_returned_in_reverse_topological_order() {
+ Node innerComponent = mockComponentNode(SimpleComponent.class);
+ Node middleComponent = mockComponentNode(ComponentTakingComponent.class);
+ Node outerComponent = mockComponentNode(ComponentTakingComponentTakingComponent.class);
+ middleComponent.inject(innerComponent);
+ outerComponent.inject(innerComponent);
+
+ ComponentGraph componentGraph = new ComponentGraph();
+ componentGraph.add(innerComponent);
+ componentGraph.add(middleComponent);
+ componentGraph.add(outerComponent);
+ componentGraph.complete();
+
+ innerComponent.constructInstance();
+ middleComponent.constructInstance();
+ outerComponent.constructInstance();
+
+ assertEquals(List.of(outerComponent.constructedInstance().get(), middleComponent.constructedInstance().get(), innerComponent.constructedInstance().get()),
+ componentGraph.allConstructedComponentsAndProviders());
+ }
+
+ @Test
public void component_can_be_injected_into_another_component() {
Node injectedComponent = mockComponentNode(SimpleComponent.class);
Node targetComponent = mockComponentNode(ComponentTakingComponent.class);
@@ -526,6 +549,15 @@ public class ComponentGraphTest {
}
}
+ public static class ComponentTakingComponentTakingComponent extends AbstractComponent {
+ private final ComponentTakingComponent injectedComponent;
+
+ public ComponentTakingComponentTakingComponent(ComponentTakingComponent injectedComponent) {
+ assertThat(injectedComponent, notNullValue());
+ this.injectedComponent = injectedComponent;
+ }
+ }
+
@SuppressWarnings("unused")
public static class ComponentTakingConfigAndComponent extends AbstractComponent {
private final TestConfig config;
diff --git a/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java b/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java
index 69db27686f0..6203b724e95 100755
--- a/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java
+++ b/documentapi/src/main/java/com/yahoo/documentapi/messagebus/MessageBusVisitorSession.java
@@ -1152,7 +1152,7 @@ public class MessageBusVisitorSession implements VisitorSession {
synchronized (completionMonitor) {
// If we are destroying the session before it has completed (e.g. because
// waitUntilDone timed out or an interactive visiting was interrupted)
- // set us to aborted state so that we'll seize sending new visitors.
+ // set us to aborted state so that we'll cease sending new visitors.
if (!done) {
transitionTo(new StateDescription(State.ABORTED, "Session explicitly destroyed before completion"));
}