Skip to content

Commit 60c54bf

Browse files
authored
Merge pull request #9807 from FlorentinD/gds/progress-tracker-cleanup
Cleanup Graph Aggregation tasks in case of failure
2 parents 1485e48 + 1d40e77 commit 60c54bf

File tree

5 files changed

+51
-3
lines changed

5 files changed

+51
-3
lines changed

cypher-aggregation/src/integrationTest/java/org/neo4j/gds/projection/ProductGraphAggregatorTest.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
import org.junit.jupiter.params.ParameterizedTest;
2424
import org.junit.jupiter.params.provider.Arguments;
2525
import org.junit.jupiter.params.provider.MethodSource;
26+
import org.neo4j.gds.TestTaskStore;
2627
import org.neo4j.gds.api.DatabaseId;
2728
import org.neo4j.gds.core.loading.Capabilities.WriteMode;
2829
import org.neo4j.gds.core.loading.GraphStoreCatalog;
2930
import org.neo4j.gds.core.utils.progress.EmptyTaskStore;
3031
import org.neo4j.gds.logging.Log;
3132
import org.neo4j.gds.metrics.projections.ProjectionMetricsService;
33+
import org.neo4j.values.AnyValue;
3234
import org.neo4j.values.storable.NoValue;
3335
import org.neo4j.values.storable.Values;
3436
import org.neo4j.values.virtual.MapValue;
@@ -37,6 +39,7 @@
3739

3840
import static org.assertj.core.api.Assertions.assertThat;
3941
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
42+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4043

4144
class ProductGraphAggregatorTest {
4245

@@ -85,14 +88,15 @@ void shouldImportHighNodeIds() {
8588
@MethodSource("emptyGraphNames")
8689
void shouldFailOnEmptyGraphName(String emptyGraphName, String description) {
8790

91+
TestTaskStore taskStore = new TestTaskStore();
8892
var aggregator = new ProductGraphAggregator(
8993
DatabaseId.random(),
9094
"neo4j",
9195
WriteMode.LOCAL,
9296
QueryEstimator.empty(),
9397
ExecutingQueryProvider.empty(),
9498
ProjectionMetricsService.DISABLED,
95-
EmptyTaskStore.INSTANCE,
99+
taskStore,
96100
Log.noOpLog()
97101
);
98102

@@ -105,6 +109,8 @@ void shouldFailOnEmptyGraphName(String emptyGraphName, String description) {
105109
MapValue.EMPTY,
106110
NoValue.NO_VALUE
107111
)).withMessageContaining("`graphName` can not be null or blank");
112+
113+
assertThat(taskStore.tasks()).isEmpty();
108114
}
109115

110116
private static Stream<Arguments> emptyGraphNames() {
@@ -115,4 +121,33 @@ private static Stream<Arguments> emptyGraphNames() {
115121
Arguments.of(" ", "spaces")
116122
);
117123
}
124+
125+
@Test
126+
void shouldCleanupTaskOnFailure() {
127+
TestTaskStore taskStore = new TestTaskStore();
128+
var aggregator = new ProductGraphAggregator(
129+
DatabaseId.random(),
130+
"neo4j",
131+
WriteMode.LOCAL,
132+
QueryEstimator.empty(),
133+
ExecutingQueryProvider.empty(),
134+
ProjectionMetricsService.DISABLED,
135+
taskStore,
136+
Log.noOpLog()
137+
);
138+
139+
assertThatThrownBy(() ->
140+
aggregator.update(new AnyValue[] {
141+
Values.stringValue("my-graph"),
142+
Values.longValue(1L),
143+
Values.stringValue("invalidID"),
144+
MapValue.EMPTY,
145+
MapValue.EMPTY,
146+
NoValue.NO_VALUE }
147+
))
148+
.hasCauseInstanceOf(IllegalArgumentException.class)
149+
.hasMessageContaining("The node has to be either a NODE or an INTEGER, but got String");
150+
151+
assertThat(taskStore.tasks()).isEmpty();
152+
}
118153
}

cypher-aggregation/src/main/java/org/neo4j/gds/projection/AlphaGraphAggregator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public void update(AnyValue[] input) throws ProcedureException {
7272
NoValue.NO_VALUE
7373
);
7474
} catch (Exception e) {
75+
super.onFailure();
7576
throw new ProcedureException(
7677
Status.Procedure.ProcedureCallFailed,
7778
e,

cypher-aggregation/src/main/java/org/neo4j/gds/projection/GraphAggregator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.neo4j.gds.core.utils.progress.BatchingTaskProgressTracker;
4242
import org.neo4j.gds.core.utils.progress.TaskRegistryFactory;
4343
import org.neo4j.gds.core.utils.progress.TaskStore;
44+
import org.neo4j.gds.core.utils.progress.tasks.ProgressTracker;
4445
import org.neo4j.gds.core.utils.progress.tasks.TaskProgressTracker;
4546
import org.neo4j.gds.core.utils.warnings.EmptyUserLogRegistryFactory;
4647
import org.neo4j.gds.logging.Log;
@@ -97,6 +98,7 @@ abstract class GraphAggregator implements UserAggregationReducer, UserAggregatio
9798

9899
// #result() may be called twice, we cache the result of the first call to return it again in the second invocation
99100
private @Nullable AggregationResult result;
101+
private ProgressTracker progressTracker;
100102

101103
GraphAggregator(
102104
DatabaseId databaseId,
@@ -213,7 +215,7 @@ private GraphImporter createGraphImporter(
213215
TaskRegistryFactory.local(username, taskStore),
214216
EmptyUserLogRegistryFactory.INSTANCE
215217
);
216-
var progressTracker = BatchingTaskProgressTracker.create(internalProgressTracker, taskVolume, config.readConcurrency());
218+
this.progressTracker = BatchingTaskProgressTracker.create(internalProgressTracker, taskVolume, config.readConcurrency());
217219

218220
return new GraphImporter(
219221
config,
@@ -281,6 +283,7 @@ public AnyValue result() throws ProcedureException {
281283
projectionMetric.start();
282284
result = buildGraph();
283285
} catch (Exception e) {
286+
this.onFailure();
284287
projectionMetric.failed(e);
285288
throw new ProcedureException(
286289
Status.Procedure.ProcedureCallFailed,
@@ -305,6 +308,12 @@ public AnyValue result() throws ProcedureException {
305308
return builder.build();
306309
}
307310

311+
void onFailure() {
312+
if (progressTracker != null) {
313+
this.progressTracker.endSubTaskWithFailure();
314+
}
315+
}
316+
308317
public @Nullable AggregationResult buildGraph() {
309318
var importer = this.importer;
310319
if (importer == null) {

cypher-aggregation/src/main/java/org/neo4j/gds/projection/ProductGraphAggregator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public void update(AnyValue[] input) throws ProcedureException {
5858
input[5]
5959
);
6060
} catch (Exception e) {
61+
super.onFailure();
6162
throw new ProcedureException(
6263
Status.Procedure.ProcedureCallFailed,
6364
e,

triplet-graph-builder/src/test/java/org/neo4j/gds/projection/GraphImporterTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,5 +451,7 @@ void shouldRegisterTaskAndLogProgress() {
451451
log.assertContainsMessage(TestLog.INFO, "Graph aggregation :: Build graph store :: Relationships :: Finished");
452452
log.assertContainsMessage(TestLog.INFO, "Graph aggregation :: Build graph store :: Finished");
453453
log.assertContainsMessage(TestLog.INFO, "Graph aggregation :: Finished");
454-
}
454+
455+
assertThat(taskStore.tasks()).isEmpty();
456+
}
455457
}

0 commit comments

Comments
 (0)