Ensure PartialReevaluation cycle node's deps are fetched if necessary
Previously, in case when the cycle node supports partial reevaluation, all of cycle nodes deps are not fetched if `env.ensurePreviouslyRequestedDepsFetched()` is not called, which will cause further execution to fail. This is a very uncommon case, so it was never caught.
On the other hand, if cycle node does not support partial reevaluation, `env.ensurePreviouslyRequestedDepsFetched()` is just a no-op, meaning this change does not introduce side effect.
PiperOrigin-RevId: 625423771
Change-Id: Iec275e7c6a45ade18f7fd0daab44b15e8d3bbe16
diff --git a/src/main/java/com/google/devtools/build/skyframe/SimpleCycleDetector.java b/src/main/java/com/google/devtools/build/skyframe/SimpleCycleDetector.java
index d0fca7e..47d4a55 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SimpleCycleDetector.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SimpleCycleDetector.java
@@ -166,6 +166,10 @@
Sets.difference(entry.getAllRemainingDirtyDirectDeps(), removedDeps),
entry.getMaxTransitiveSourceVersion(),
evaluatorContext);
+ // When the environment sets a cycle node to be in error and commits afterwards, it
+ // requires all of its deps to be fetched. See `SkyFunctionEnvironment#setError()`'s
+ // JavaDoc for more details.
+ env.ensurePreviouslyRequestedDepsFetched();
} catch (UndonePreviouslyRequestedDeps undoneDeps) {
// All children were finished according to the CHILDREN_FINISHED sentinel, and cycle
// detection does not do normal SkyFunction evaluation, so no restarting nor child
diff --git a/src/test/java/com/google/devtools/build/skyframe/GraphTester.java b/src/test/java/com/google/devtools/build/skyframe/GraphTester.java
index 02efc54..dbfe6a4 100644
--- a/src/test/java/com/google/devtools/build/skyframe/GraphTester.java
+++ b/src/test/java/com/google/devtools/build/skyframe/GraphTester.java
@@ -419,6 +419,10 @@
return ImmutableMap.copyOf(functionMap);
}
+ public void putDelegateFunction(SkyFunctionName functionName) {
+ putSkyFunction(functionName, new DelegatingFunction());
+ }
+
public void putSkyFunction(SkyFunctionName functionName, SkyFunction function) {
functionMap.put(functionName, function);
}
diff --git a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
index 39f1dd9..a6579e2 100644
--- a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
@@ -1839,11 +1839,20 @@
assertThat(numComputes.get()).isEqualTo(2);
}
+ private SkyKey createCycleKey(String keyName, boolean isCycleNodePartialReevaluation) {
+ if (isCycleNodePartialReevaluation) {
+ tester.putDelegateFunction(PartialReevaluationKey.FUNCTION_NAME);
+ return new PartialReevaluationKey(keyName);
+ }
+ return skyKey(keyName);
+ }
+
/** Make sure that multiple unfinished children can be cleared from a cycle value. */
@Test
- public void cycleWithMultipleUnfinishedChildren() throws Exception {
+ public void cycleWithMultipleUnfinishedChildren(
+ @TestParameter boolean isCycleNodePartialReevaluation) throws Exception {
graph = new DeterministicHelper.DeterministicProcessableGraph(new InMemoryGraphImpl());
- SkyKey cycleKey = skyKey("zcycle");
+ SkyKey cycleKey = createCycleKey("cycle", isCycleNodePartialReevaluation);
SkyKey midKey = skyKey("mid");
SkyKey topKey = skyKey("top");
SkyKey selfEdge1 = skyKey("selfEdge1");
@@ -1873,11 +1882,13 @@
* and cycle. Error bubbles up from mid to cycle, and we should detect cycle.
*/
@Test
- public void cycleAndErrorInBubbleUp(@TestParameter boolean keepGoing) throws Exception {
+ public void cycleAndErrorInBubbleUp(
+ @TestParameter boolean keepGoing, @TestParameter boolean isCycleNodePartialReevaluation)
+ throws Exception {
graph = new DeterministicHelper.DeterministicProcessableGraph(new InMemoryGraphImpl());
tester = new GraphTester();
SkyKey errorKey = skyKey("error");
- SkyKey cycleKey = skyKey("cycle");
+ SkyKey cycleKey = createCycleKey("cycle", isCycleNodePartialReevaluation);
SkyKey midKey = skyKey("mid");
SkyKey topKey = skyKey("top");
tester.getOrCreate(topKey).addDependency(midKey).setComputedValue(CONCATENATE);
@@ -1982,11 +1993,13 @@
* error, just to mix it up.
*/
@Test
- public void cycleAndErrorAndError(@TestParameter boolean keepGoing) throws Exception {
+ public void cycleAndErrorAndError(
+ @TestParameter boolean keepGoing, @TestParameter boolean isCycleNodePartialReevaluation)
+ throws Exception {
graph = new DeterministicHelper.DeterministicProcessableGraph(new InMemoryGraphImpl());
tester = new GraphTester();
SkyKey errorKey = skyKey("error");
- SkyKey cycleKey = skyKey("cycle");
+ SkyKey cycleKey = createCycleKey("cycle", isCycleNodePartialReevaluation);
SkyKey midKey = skyKey("mid");
SkyKey topKey = skyKey("top");
tester.getOrCreate(topKey).addDependency(midKey).setComputedValue(CONCATENATE);