Skip to content

Commit e4c68fe

Browse files
Merge pull request #10730 from IoannisPanagiotas/write-service-more
Write service more
2 parents 3b278da + b74350f commit e4c68fe

File tree

11 files changed

+340
-390
lines changed

11 files changed

+340
-390
lines changed

applications/algorithms/machinery/src/main/java/org/neo4j/gds/applications/algorithms/machinery/Neo4jDatabaseRelationshipWriter.java

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,32 @@
1919
*/
2020
package org.neo4j.gds.applications.algorithms.machinery;
2121

22+
import org.neo4j.gds.api.ExportedRelationship;
2223
import org.neo4j.gds.api.Graph;
2324
import org.neo4j.gds.api.IdMap;
2425
import org.neo4j.gds.api.ResultStore;
26+
import org.neo4j.gds.api.nodeproperties.ValueType;
2527
import org.neo4j.gds.api.properties.relationships.RelationshipWithPropertyConsumer;
2628
import org.neo4j.gds.applications.algorithms.metadata.RelationshipsWritten;
29+
import org.neo4j.gds.core.concurrency.Concurrency;
2730
import org.neo4j.gds.core.utils.logging.LoggerForProgressTrackingAdapter;
2831
import org.neo4j.gds.core.utils.progress.JobId;
2932
import org.neo4j.gds.core.utils.progress.TaskRegistryFactory;
3033
import org.neo4j.gds.core.utils.progress.tasks.TaskProgressTracker;
3134
import org.neo4j.gds.core.write.RelationshipExporter;
3235
import org.neo4j.gds.core.write.RelationshipExporterBuilder;
36+
import org.neo4j.gds.core.write.RelationshipStreamExporter;
37+
import org.neo4j.gds.core.write.RelationshipStreamExporterBuilder;
3338
import org.neo4j.gds.logging.Log;
3439
import org.neo4j.gds.termination.TerminationFlag;
3540

41+
import java.util.List;
3642
import java.util.Optional;
43+
import java.util.stream.Stream;
3744

3845
final class Neo4jDatabaseRelationshipWriter {
39-
static RelationshipsWritten writeRelationship(
46+
47+
static RelationshipsWritten writeRelationshipsFromGraph(
4048
String writeRelationshipType,
4149
String writeProperty,
4250
TaskRegistryFactory taskRegistryFactory,
@@ -49,24 +57,23 @@ static RelationshipsWritten writeRelationship(
4957
Optional<ResultStore> resultStore,
5058
RelationshipWithPropertyConsumer relationshipConsumer,
5159
JobId jobId
52-
){
60+
) {
5361

5462
var progressTracker = new TaskProgressTracker(
55-
RelationshipExporter.baseTask(taskName, graph.relationshipCount()),
56-
new LoggerForProgressTrackingAdapter(log),
57-
RelationshipExporterBuilder.TYPED_DEFAULT_WRITE_CONCURRENCY,
58-
taskRegistryFactory
59-
);
60-
61-
var exporter = relationshipExporterBuilder
62-
.withIdMappingOperator(rootIdMap::toOriginalNodeId)
63-
.withGraph(graph)
64-
.withTerminationFlag(algorithmTerminationFlag)
65-
.withProgressTracker(progressTracker)
66-
.withResultStore(resultStore)
67-
.withJobId(jobId)
68-
.build();
63+
RelationshipExporter.baseTask(taskName, graph.relationshipCount()),
64+
new LoggerForProgressTrackingAdapter(log),
65+
RelationshipExporterBuilder.TYPED_DEFAULT_WRITE_CONCURRENCY,
66+
taskRegistryFactory
67+
);
6968

69+
var exporter = relationshipExporterBuilder
70+
.withIdMappingOperator(rootIdMap::toOriginalNodeId)
71+
.withGraph(graph)
72+
.withTerminationFlag(algorithmTerminationFlag)
73+
.withProgressTracker(progressTracker)
74+
.withResultStore(resultStore)
75+
.withJobId(jobId)
76+
.build();
7077

7178
try {
7279
exporter.write(
@@ -82,8 +89,58 @@ static RelationshipsWritten writeRelationship(
8289
}
8390

8491
return new RelationshipsWritten(graph.relationshipCount());
92+
}
8593

94+
static RelationshipsWritten writeRelationshipsFromStream(
95+
String writeRelationshipType,
96+
List<String> properties,
97+
List<ValueType> valueTypes,
98+
TaskRegistryFactory taskRegistryFactory,
99+
RelationshipStreamExporterBuilder relationshipStreamExporterBuilder,
100+
Stream<ExportedRelationship> relationshipStream,
101+
IdMap rootIdMap,
102+
Log log,
103+
String taskName,
104+
TerminationFlag algorithmTerminationFlag,
105+
Optional<ResultStore> maybeResultStore,
106+
JobId jobId
107+
) {
108+
109+
var progressTracker = new TaskProgressTracker(
110+
RelationshipStreamExporter.baseTask(taskName),
111+
new LoggerForProgressTrackingAdapter(log),
112+
new Concurrency(1),
113+
taskRegistryFactory
114+
);
115+
116+
// When we are writing to the result store, the result stream might not be consumed
117+
// inside the current transaction. This causes the stream to immediately return an empty stream
118+
// as the termination flag, which is bound to the current transaction is set to true. We therefore
119+
// need to collect the stream and trigger an eager computation.
120+
var maybeCollectedStream = maybeResultStore
121+
.map(__ -> relationshipStream.toList().stream())
122+
.orElse(relationshipStream);
123+
124+
// configure the exporter
125+
var relationshipStreamExporter = relationshipStreamExporterBuilder
126+
.withResultStore(maybeResultStore)
127+
.withIdMappingOperator(rootIdMap::toOriginalNodeId)
128+
.withProgressTracker(progressTracker)
129+
.withRelationships(maybeCollectedStream)
130+
.withTerminationFlag(algorithmTerminationFlag)
131+
.withJobId(jobId)
132+
.build();
133+
134+
var relationshipsWritten = relationshipStreamExporter.write(
135+
writeRelationshipType,
136+
properties,
137+
valueTypes
138+
);
139+
140+
return new RelationshipsWritten(relationshipsWritten);
86141
}
87142

143+
88144
private Neo4jDatabaseRelationshipWriter() {}
89145
}
146+

applications/algorithms/machinery/src/main/java/org/neo4j/gds/applications/algorithms/machinery/WriteRelationshipService.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@
1919
*/
2020
package org.neo4j.gds.applications.algorithms.machinery;
2121

22+
import org.neo4j.gds.api.ExportedRelationship;
2223
import org.neo4j.gds.api.Graph;
2324
import org.neo4j.gds.api.IdMap;
2425
import org.neo4j.gds.api.ResultStore;
26+
import org.neo4j.gds.api.nodeproperties.ValueType;
2527
import org.neo4j.gds.api.properties.relationships.RelationshipWithPropertyConsumer;
2628
import org.neo4j.gds.applications.algorithms.metadata.RelationshipsWritten;
2729
import org.neo4j.gds.core.utils.progress.JobId;
2830
import org.neo4j.gds.logging.Log;
2931

32+
import java.util.List;
3033
import java.util.Optional;
34+
import java.util.stream.Stream;
3135

3236
public class WriteRelationshipService {
3337
private final Log log;
@@ -40,22 +44,23 @@ public WriteRelationshipService(Log log, RequestScopedDependencies requestScoped
4044
this.writeContext = writeContext;
4145
}
4246

43-
public RelationshipsWritten write(
47+
public RelationshipsWritten writeFromGraph(
4448
String writeRelationshipType,
4549
String writeProperty,
46-
Graph graph,
50+
Graph writeGraph,
4751
IdMap rootIdMap,
4852
String taskName,
4953
Optional<ResultStore> resultStore,
5054
RelationshipWithPropertyConsumer relationshipWithPropertyConsumer,
5155
JobId jobId
5256
) {
53-
return Neo4jDatabaseRelationshipWriter.writeRelationship(
57+
58+
return Neo4jDatabaseRelationshipWriter.writeRelationshipsFromGraph(
5459
writeRelationshipType,
5560
writeProperty,
5661
requestScopedDependencies.taskRegistryFactory(),
5762
writeContext.relationshipExporterBuilder(),
58-
graph,
63+
writeGraph,
5964
rootIdMap,
6065
log,
6166
taskName,
@@ -65,4 +70,33 @@ public RelationshipsWritten write(
6570
jobId
6671
);
6772
}
73+
74+
public RelationshipsWritten writeFromRelationshipStream(
75+
String writeRelationshipType,
76+
List<String> properties,
77+
List<ValueType> valueTypes,
78+
Stream<ExportedRelationship> relationshipStream,
79+
IdMap rootIdMap,
80+
String taskName,
81+
Optional<ResultStore> resultStore,
82+
JobId jobId
83+
){
84+
85+
return Neo4jDatabaseRelationshipWriter.writeRelationshipsFromStream(
86+
writeRelationshipType,
87+
properties,
88+
valueTypes,
89+
requestScopedDependencies.taskRegistryFactory(),
90+
writeContext.relationshipStreamExporterBuilder(),
91+
relationshipStream,
92+
rootIdMap,
93+
log,
94+
taskName,
95+
requestScopedDependencies.terminationFlag(),
96+
resultStore,
97+
jobId
98+
);
99+
}
100+
101+
68102
}

0 commit comments

Comments
 (0)