Add threadpool injectability to invalidator

--
MOS_MIGRATED_REVID=99961435
diff --git a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
index fc2a2c7..cfe03e2 100644
--- a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
@@ -13,11 +13,17 @@
 // limitations under the License.
 package com.google.devtools.build.skyframe;
 
-import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor;
+import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor.ThreadPoolExecutorParams;
 import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DeletingNodeVisitor;
 import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingNodeVisitor;
 import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState;
 
+import java.util.concurrent.ThreadPoolExecutor;
+
+import javax.annotation.Nullable;
+
 /**
  * Utility class for performing eager invalidation on Skyframe graphs.
  *
@@ -39,29 +45,61 @@
       EvaluationProgressReceiver invalidationReceiver, InvalidationState state,
       boolean traverseGraph, DirtyKeyTracker dirtyKeyTracker) throws InterruptedException {
     InvalidatingNodeVisitor visitor =
-        createVisitor(/*delete=*/true, graph, diff, invalidationReceiver, state, traverseGraph,
+        createDeletingVisitorIfNeeded(graph, diff, invalidationReceiver, state, traverseGraph,
             dirtyKeyTracker);
     if (visitor != null) {
       visitor.run();
     }
   }
 
-  /**
-   * Creates an invalidation visitor that is ready to run. Caller should call #run() on the visitor.
-   * Allows test classes to keep a reference to the visitor, and await exceptions/interrupts.
-   */
-  @VisibleForTesting
-  static InvalidatingNodeVisitor createVisitor(boolean delete, DirtiableGraph graph,
+  @Nullable
+  static InvalidatingNodeVisitor createDeletingVisitorIfNeeded(DirtiableGraph graph,
       Iterable<SkyKey> diff, EvaluationProgressReceiver invalidationReceiver,
       InvalidationState state, boolean traverseGraph, DirtyKeyTracker dirtyKeyTracker) {
     state.update(diff);
-    if (state.isEmpty()) {
-      return null;
+    return state.isEmpty() ? null
+        : new DeletingNodeVisitor(graph, invalidationReceiver, state, traverseGraph,
+            dirtyKeyTracker);
+  }
+
+  @Nullable
+  static InvalidatingNodeVisitor createInvalidatingVisitorIfNeeded(DirtiableGraph graph,
+      Iterable<SkyKey> diff, EvaluationProgressReceiver invalidationReceiver,
+      InvalidationState state, DirtyKeyTracker dirtyKeyTracker,
+      Function<ThreadPoolExecutorParams, ThreadPoolExecutor> executorFactory) {
+    state.update(diff);
+    return state.isEmpty() ? null
+        : new DirtyingNodeVisitor(graph, invalidationReceiver, state, dirtyKeyTracker,
+            executorFactory);
+  }
+
+  @Nullable
+  static InvalidatingNodeVisitor createInvalidatingVisitorIfNeeded(DirtiableGraph graph,
+      Iterable<SkyKey> diff, EvaluationProgressReceiver invalidationReceiver,
+      InvalidationState state, DirtyKeyTracker dirtyKeyTracker) {
+    return createInvalidatingVisitorIfNeeded(graph, diff, invalidationReceiver, state,
+        dirtyKeyTracker, AbstractQueueVisitor.EXECUTOR_FACTORY);
+  }
+
+  /**
+   * Invalidates given values and their upward transitive closure in the graph, using an executor
+   * constructed with the provided factory, if necessary.
+   */
+  public static void invalidate(DirtiableGraph graph, Iterable<SkyKey> diff,
+      EvaluationProgressReceiver invalidationReceiver, InvalidationState state,
+      DirtyKeyTracker dirtyKeyTracker,
+      Function<ThreadPoolExecutorParams, ThreadPoolExecutor> executorFactory)
+          throws InterruptedException {
+    // If we are invalidating, we must be in an incremental build by definition, so we must
+    // maintain a consistent graph state by traversing the graph and invalidating transitive
+    // dependencies. If edges aren't present, it would be impossible to check the dependencies of
+    // a dirty node in any case.
+    InvalidatingNodeVisitor visitor =
+        createInvalidatingVisitorIfNeeded(graph, diff, invalidationReceiver, state,
+            dirtyKeyTracker, executorFactory);
+    if (visitor != null) {
+      visitor.run();
     }
-    return delete
-        ? new DeletingNodeVisitor(graph, invalidationReceiver, state, traverseGraph,
-          dirtyKeyTracker)
-        : new DirtyingNodeVisitor(graph, invalidationReceiver, state, dirtyKeyTracker);
   }
 
   /**
@@ -70,16 +108,9 @@
   public static void invalidate(DirtiableGraph graph, Iterable<SkyKey> diff,
       EvaluationProgressReceiver invalidationReceiver, InvalidationState state,
       DirtyKeyTracker dirtyKeyTracker)
-          throws InterruptedException {
-    // If we are invalidating, we must be in an incremental build by definition, so we must
-    // maintain a consistent graph state by traversing the graph and invalidating transitive
-    // dependencies. If edges aren't present, it would be impossible to check the dependencies of
-    // a dirty node in any case.
-    InvalidatingNodeVisitor visitor =
-        createVisitor(/*delete=*/false, graph, diff, invalidationReceiver, state,
-            /*traverseGraph=*/true, dirtyKeyTracker);
-    if (visitor != null) {
-      visitor.run();
-    }
+      throws InterruptedException {
+    invalidate(graph, diff, invalidationReceiver, state, dirtyKeyTracker,
+        AbstractQueueVisitor.EXECUTOR_FACTORY);
   }
+
 }