From 65895963c098309322a554a4e8691eb33b9445a3 Mon Sep 17 00:00:00 2001 From: Lasse Westh-Nielsen Date: Mon, 27 May 2024 11:58:17 +0200 Subject: [PATCH 1/4] mov escaffolding from ProcedureRunner into procedures facade factory method, with a view to moving _all_ scaffolding in there --- .../src/main/java/org/neo4j/gds/BaseProc.java | 2 + .../java/org/neo4j/gds/ProcedureRunner.java | 80 ++++---------- procedures/facade/build.gradle | 1 + .../GraphDataScienceProcedures.java | 101 +++++++++++++++++- .../ProcedureCallContextReturnColumns.java | 4 +- .../TransactionCloseableResourceRegistry.java | 3 +- .../AlgorithmFacadeFactoryProvider.java | 4 +- .../integration/CatalogFacadeProvider.java | 2 +- 8 files changed, 123 insertions(+), 74 deletions(-) rename {proc/common/src/main/java/org/neo4j/gds => procedures/facade/src/main/java/org/neo4j/gds/procedures}/ProcedureCallContextReturnColumns.java (97%) rename {proc/common/src/main/java/org/neo4j/gds => procedures/facade/src/main/java/org/neo4j/gds/procedures}/TransactionCloseableResourceRegistry.java (97%) diff --git a/proc/common/src/main/java/org/neo4j/gds/BaseProc.java b/proc/common/src/main/java/org/neo4j/gds/BaseProc.java index a00092828dd..090577b0d15 100644 --- a/proc/common/src/main/java/org/neo4j/gds/BaseProc.java +++ b/proc/common/src/main/java/org/neo4j/gds/BaseProc.java @@ -33,6 +33,8 @@ import org.neo4j.gds.executor.ImmutableExecutionContext; import org.neo4j.gds.metrics.MetricsFacade; import org.neo4j.gds.procedures.GraphDataScienceProcedures; +import org.neo4j.gds.procedures.ProcedureCallContextReturnColumns; +import org.neo4j.gds.procedures.TransactionCloseableResourceRegistry; import org.neo4j.gds.procedures.integration.TransactionTerminationMonitor; import org.neo4j.gds.transaction.DatabaseTransactionContext; import org.neo4j.gds.transaction.EmptyTransactionContext; diff --git a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java index 3a7b278567b..afd672bbf5b 100644 --- a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java +++ b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java @@ -19,12 +19,9 @@ */ package org.neo4j.gds; -import org.neo4j.gds.algorithms.similarity.WriteRelationshipService; import org.neo4j.gds.api.AlgorithmMetaDataSetter; import org.neo4j.gds.api.GraphLoaderContext; import org.neo4j.gds.api.User; -import org.neo4j.gds.applications.ApplicationsFacade; -import org.neo4j.gds.applications.algorithms.machinery.AlgorithmEstimationTemplate; import org.neo4j.gds.applications.algorithms.machinery.DefaultAlgorithmProcessingTemplate; import org.neo4j.gds.applications.algorithms.machinery.MemoryGuard; import org.neo4j.gds.applications.algorithms.machinery.RequestScopedDependencies; @@ -36,18 +33,8 @@ import org.neo4j.gds.core.utils.progress.TaskRegistryFactory; import org.neo4j.gds.core.utils.warnings.EmptyUserLogRegistryFactory; import org.neo4j.gds.core.utils.warnings.UserLogRegistryFactory; -import org.neo4j.gds.memest.DatabaseGraphStoreEstimationService; import org.neo4j.gds.metrics.MetricsFacade; import org.neo4j.gds.procedures.GraphDataScienceProcedures; -import org.neo4j.gds.procedures.GraphDataScienceProceduresBuilder; -import org.neo4j.gds.procedures.algorithms.centrality.CentralityProcedureFacade; -import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationCreator; -import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationParser; -import org.neo4j.gds.procedures.algorithms.runners.EstimationModeRunner; -import org.neo4j.gds.procedures.algorithms.runners.StatsModeAlgorithmRunner; -import org.neo4j.gds.procedures.algorithms.runners.StreamModeAlgorithmRunner; -import org.neo4j.gds.procedures.algorithms.runners.WriteModeAlgorithmRunner; -import org.neo4j.gds.procedures.algorithms.stubs.GenericStub; import org.neo4j.gds.procedures.integration.LogAdapter; import org.neo4j.gds.services.DatabaseIdAccessor; import org.neo4j.graphdb.GraphDatabaseService; @@ -158,66 +145,35 @@ private static GraphDataScienceProcedures createGraphDataScienceProcedures( ) { var gdsLog = new LogAdapter(log); - var configurationParser = new ConfigurationParser(DefaultsConfiguration.Instance, LimitsConfiguration.Instance); - var graphStoreCatalogService = new GraphStoreCatalogService(); var requestScopedDependencies = RequestScopedDependencies.builder() .with(new DatabaseIdAccessor().getDatabaseId(graphDatabaseService)) .with(taskRegistryFactory) .with(new User(username.username(), false)) .with(EmptyUserLogRegistryFactory.INSTANCE) .build(); + var graphStoreCatalogService = new GraphStoreCatalogService(); - var configurationCreator = new ConfigurationCreator( - configurationParser, - AlgorithmMetaDataSetter.EMPTY, - requestScopedDependencies.getUser() - ); - - var algorithmEstimationTemplate = new AlgorithmEstimationTemplate( + var algorithmProcessingTemplate = new DefaultAlgorithmProcessingTemplate( + gdsLog, + MetricsFacade.PASSTHROUGH_METRICS_FACADE.algorithmMetrics(), graphStoreCatalogService, - new DatabaseGraphStoreEstimationService( - GraphLoaderContext.NULL_CONTEXT, - requestScopedDependencies.getUser() - ), + MemoryGuard.DISABLED, requestScopedDependencies ); - var closeableResourceRegistry = new TransactionCloseableResourceRegistry(kernelTransaction); - - var centralityProcedureFacade = CentralityProcedureFacade.create( - new GenericStub( - DefaultsConfiguration.Instance, - LimitsConfiguration.Instance, - configurationCreator, - configurationParser, - requestScopedDependencies.getUser(), - algorithmEstimationTemplate - ), - ApplicationsFacade.create( - gdsLog, - Optional.empty(), - graphStoreCatalogService, - MetricsFacade.PASSTHROUGH_METRICS_FACADE.projectionMetrics(), - algorithmEstimationTemplate, - new DefaultAlgorithmProcessingTemplate( - gdsLog, - MetricsFacade.PASSTHROUGH_METRICS_FACADE.algorithmMetrics(), - graphStoreCatalogService, - MemoryGuard.DISABLED, - requestScopedDependencies - ), - requestScopedDependencies, - new WriteRelationshipService(gdsLog, requestScopedDependencies) - ), - new ProcedureCallContextReturnColumns(procedureCallContext), - new EstimationModeRunner(configurationCreator), - new StatsModeAlgorithmRunner(configurationCreator), - new StreamModeAlgorithmRunner(closeableResourceRegistry, configurationCreator), - new WriteModeAlgorithmRunner(configurationCreator) + return GraphDataScienceProcedures.create( + gdsLog, + DefaultsConfiguration.Instance, + LimitsConfiguration.Instance, + Optional.empty(), + graphStoreCatalogService, + MetricsFacade.PASSTHROUGH_METRICS_FACADE.projectionMetrics(), + AlgorithmMetaDataSetter.EMPTY, + algorithmProcessingTemplate, + kernelTransaction, + GraphLoaderContext.NULL_CONTEXT, + procedureCallContext, + requestScopedDependencies ); - - return new GraphDataScienceProceduresBuilder(gdsLog) - .with(centralityProcedureFacade) - .build(); } } diff --git a/procedures/facade/build.gradle b/procedures/facade/build.gradle index ccf233fe0e7..fbdbda468d4 100644 --- a/procedures/facade/build.gradle +++ b/procedures/facade/build.gradle @@ -32,6 +32,7 @@ dependencies { implementation project(':graph-store-catalog-applications') implementation project(':legacy-cypher-projection') implementation project(':logging') + implementation project(':memory-estimation') implementation project(':memory-usage') implementation project(':metrics-api') implementation project(':ml-algo') diff --git a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java index f651060f856..42734cd210c 100644 --- a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java @@ -19,22 +19,47 @@ */ package org.neo4j.gds.procedures; +import org.neo4j.gds.algorithms.similarity.WriteRelationshipService; +import org.neo4j.gds.api.AlgorithmMetaDataSetter; +import org.neo4j.gds.api.GraphLoaderContext; +import org.neo4j.gds.applications.ApplicationsFacade; +import org.neo4j.gds.applications.algorithms.machinery.AlgorithmEstimationTemplate; +import org.neo4j.gds.applications.algorithms.machinery.AlgorithmProcessingTemplate; +import org.neo4j.gds.applications.algorithms.machinery.RequestScopedDependencies; +import org.neo4j.gds.applications.graphstorecatalog.CatalogBusinessFacade; +import org.neo4j.gds.configuration.DefaultsConfiguration; +import org.neo4j.gds.configuration.LimitsConfiguration; +import org.neo4j.gds.core.loading.GraphStoreCatalogService; import org.neo4j.gds.logging.Log; +import org.neo4j.gds.memest.DatabaseGraphStoreEstimationService; import org.neo4j.gds.metrics.procedures.DeprecatedProceduresMetricService; +import org.neo4j.gds.metrics.projections.ProjectionMetricsService; import org.neo4j.gds.procedures.algorithms.AlgorithmsProcedureFacade; +import org.neo4j.gds.procedures.algorithms.centrality.CentralityProcedureFacade; +import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationCreator; +import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationParser; +import org.neo4j.gds.procedures.algorithms.runners.EstimationModeRunner; +import org.neo4j.gds.procedures.algorithms.runners.StatsModeAlgorithmRunner; +import org.neo4j.gds.procedures.algorithms.runners.StreamModeAlgorithmRunner; +import org.neo4j.gds.procedures.algorithms.runners.WriteModeAlgorithmRunner; +import org.neo4j.gds.procedures.algorithms.stubs.GenericStub; import org.neo4j.gds.procedures.catalog.CatalogProcedureFacade; -import org.neo4j.gds.procedures.centrality.CentralityProcedureFacade; import org.neo4j.gds.procedures.community.CommunityProcedureFacade; import org.neo4j.gds.procedures.embeddings.NodeEmbeddingsProcedureFacade; import org.neo4j.gds.procedures.misc.MiscAlgorithmsProcedureFacade; import org.neo4j.gds.procedures.pipelines.PipelinesProcedureFacade; +import org.neo4j.internal.kernel.api.procs.ProcedureCallContext; +import org.neo4j.kernel.api.KernelTransaction; + +import java.util.Optional; +import java.util.function.Function; public class GraphDataScienceProcedures { private final Log log; private final AlgorithmsProcedureFacade algorithmsProcedureFacade; private final CatalogProcedureFacade catalogProcedureFacade; - private final CentralityProcedureFacade centralityProcedureFacade; + private final org.neo4j.gds.procedures.centrality.CentralityProcedureFacade centralityProcedureFacade; private final CommunityProcedureFacade communityProcedureFacade; private final MiscAlgorithmsProcedureFacade miscAlgorithmsProcedureFacade; private final NodeEmbeddingsProcedureFacade nodeEmbeddingsProcedureFacade; @@ -49,7 +74,7 @@ public class GraphDataScienceProcedures { Log log, AlgorithmsProcedureFacade algorithmsProcedureFacade, CatalogProcedureFacade catalogProcedureFacade, - CentralityProcedureFacade centralityProcedureFacade, + org.neo4j.gds.procedures.centrality.CentralityProcedureFacade centralityProcedureFacade, CommunityProcedureFacade communityProcedureFacade, MiscAlgorithmsProcedureFacade miscAlgorithmsProcedureFacade, NodeEmbeddingsProcedureFacade nodeEmbeddingsProcedureFacade, @@ -67,6 +92,74 @@ public class GraphDataScienceProcedures { this.deprecatedProceduresMetricService = deprecatedProceduresMetricService; } + public static GraphDataScienceProcedures create( + Log log, + DefaultsConfiguration defaultsConfiguration, + LimitsConfiguration limitsConfiguration, + Optional> catalogBusinessFacadeDecorator, + GraphStoreCatalogService graphStoreCatalogService, + ProjectionMetricsService projectionMetricsService, + AlgorithmMetaDataSetter algorithmMetaDataSetter, + AlgorithmProcessingTemplate algorithmProcessingTemplate, + KernelTransaction kernelTransaction, + GraphLoaderContext graphLoaderContext, + ProcedureCallContext procedureCallContext, + RequestScopedDependencies requestScopedDependencies + ) { + var configurationParser = new ConfigurationParser(defaultsConfiguration, limitsConfiguration); + var configurationCreator = new ConfigurationCreator( + configurationParser, + algorithmMetaDataSetter, + requestScopedDependencies.getUser() + ); + var databaseGraphStoreEstimationService = new DatabaseGraphStoreEstimationService( + graphLoaderContext, + requestScopedDependencies.getUser() + ); + var algorithmEstimationTemplate = new AlgorithmEstimationTemplate( + graphStoreCatalogService, + databaseGraphStoreEstimationService, + requestScopedDependencies + ); + var genericStub = new GenericStub( + defaultsConfiguration, + limitsConfiguration, + configurationCreator, + configurationParser, + requestScopedDependencies.getUser(), + algorithmEstimationTemplate + ); + + var writeRelationshipService = new WriteRelationshipService(log, requestScopedDependencies); + + var applicationsFacade = ApplicationsFacade.create( + log, + catalogBusinessFacadeDecorator, + graphStoreCatalogService, + projectionMetricsService, + algorithmEstimationTemplate, + algorithmProcessingTemplate, + requestScopedDependencies, + writeRelationshipService + ); + + var closeableResourceRegistry = new TransactionCloseableResourceRegistry(kernelTransaction); + + var centralityProcedureFacade = CentralityProcedureFacade.create( + genericStub, + applicationsFacade, + new ProcedureCallContextReturnColumns(procedureCallContext), + new EstimationModeRunner(configurationCreator), + new StatsModeAlgorithmRunner(configurationCreator), + new StreamModeAlgorithmRunner(closeableResourceRegistry, configurationCreator), + new WriteModeAlgorithmRunner(configurationCreator) + ); + + return new GraphDataScienceProceduresBuilder(log) + .with(centralityProcedureFacade) + .build(); + } + public Log log() { return log; } @@ -79,7 +172,7 @@ public CatalogProcedureFacade catalog() { return catalogProcedureFacade; } - public CentralityProcedureFacade centrality() { + public org.neo4j.gds.procedures.centrality.CentralityProcedureFacade centrality() { return centralityProcedureFacade; } diff --git a/proc/common/src/main/java/org/neo4j/gds/ProcedureCallContextReturnColumns.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/ProcedureCallContextReturnColumns.java similarity index 97% rename from proc/common/src/main/java/org/neo4j/gds/ProcedureCallContextReturnColumns.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/ProcedureCallContextReturnColumns.java index 0269662e723..952451d84f5 100644 --- a/proc/common/src/main/java/org/neo4j/gds/ProcedureCallContextReturnColumns.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/ProcedureCallContextReturnColumns.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds; +package org.neo4j.gds.procedures; import org.neo4j.gds.api.ProcedureReturnColumns; import org.neo4j.internal.kernel.api.procs.ProcedureCallContext; @@ -26,7 +26,6 @@ import java.util.stream.Stream; public class ProcedureCallContextReturnColumns implements ProcedureReturnColumns { - private final Supplier> returnColumnsSupplier; public ProcedureCallContextReturnColumns(ProcedureCallContext procedureCallContext) { @@ -37,5 +36,4 @@ public ProcedureCallContextReturnColumns(ProcedureCallContext procedureCallConte public boolean contains(String fieldName) { return returnColumnsSupplier.get().anyMatch(column -> column.equals(fieldName)); } - } diff --git a/proc/common/src/main/java/org/neo4j/gds/TransactionCloseableResourceRegistry.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/TransactionCloseableResourceRegistry.java similarity index 97% rename from proc/common/src/main/java/org/neo4j/gds/TransactionCloseableResourceRegistry.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/TransactionCloseableResourceRegistry.java index 75d3dae4350..147a145f57f 100644 --- a/proc/common/src/main/java/org/neo4j/gds/TransactionCloseableResourceRegistry.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/TransactionCloseableResourceRegistry.java @@ -17,13 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds; +package org.neo4j.gds.procedures; import org.neo4j.gds.api.CloseableResourceRegistry; import org.neo4j.kernel.api.KernelTransaction; public class TransactionCloseableResourceRegistry implements CloseableResourceRegistry { - private final KernelTransaction kernelTransaction; public TransactionCloseableResourceRegistry(KernelTransaction kernelTransaction) { diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java index f07fc6efb9e..52c58306c7f 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java @@ -19,8 +19,8 @@ */ package org.neo4j.gds.procedures.integration; -import org.neo4j.gds.ProcedureCallContextReturnColumns; -import org.neo4j.gds.TransactionCloseableResourceRegistry; +import org.neo4j.gds.procedures.ProcedureCallContextReturnColumns; +import org.neo4j.gds.procedures.TransactionCloseableResourceRegistry; import org.neo4j.gds.TransactionNodeLookup; import org.neo4j.gds.algorithms.AlgorithmMemoryValidationService; import org.neo4j.gds.algorithms.estimation.AlgorithmEstimator; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java index b056c6669a5..6de01603df9 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java @@ -19,7 +19,7 @@ */ package org.neo4j.gds.procedures.integration; -import org.neo4j.gds.ProcedureCallContextReturnColumns; +import org.neo4j.gds.procedures.ProcedureCallContextReturnColumns; import org.neo4j.gds.applications.ApplicationsFacade; import org.neo4j.gds.applications.graphstorecatalog.GraphProjectMemoryUsageService; import org.neo4j.gds.compat.Neo4jProxy; From 70e9b60fad90f13a9ea941f33f95a47f75f2d618 Mon Sep 17 00:00:00 2001 From: Lasse Westh-Nielsen Date: Mon, 27 May 2024 13:56:06 +0200 Subject: [PATCH 2/4] move catalog facade scaffolding from into procedure facade factory method --- .../org/neo4j/gds/FakeSecurityContext.java | 118 ++++++++++++++++++ .../java/org/neo4j/gds/ProcedureRunner.java | 51 +++++++- .../OpenGraphDataScienceExtension.java | 2 +- .../CatalogProcedureFacadeFactory.java} | 47 +++---- .../gds/procedures}/DatabaseIdAccessor.java | 2 +- .../ExporterBuildersProviderService.java | 2 +- .../GraphDataScienceProcedures.java | 22 +++- .../neo4j/gds/procedures}/UserAccessor.java | 2 +- .../gds/procedures}/UserLogServices.java | 2 +- .../gds/procedures}/UserLogServicesTest.java | 2 +- .../GraphDataScienceExtensionBuilder.java | 3 +- .../GraphDataScienceProviderFactory.java | 8 +- .../PipelinesProcedureFacadeProvider.java | 8 +- .../TaskRegistryFactoryProvider.java | 4 +- .../integration/TaskStoreProvider.java | 2 +- .../UserLogRegistryFactoryProvider.java | 6 +- 16 files changed, 231 insertions(+), 50 deletions(-) create mode 100644 proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java rename procedures/{integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java => facade/src/main/java/org/neo4j/gds/procedures/CatalogProcedureFacadeFactory.java} (75%) rename {proc/common/src/main/java/org/neo4j/gds/services => procedures/facade/src/main/java/org/neo4j/gds/procedures}/DatabaseIdAccessor.java (96%) rename procedures/{integration/src/main/java/org/neo4j/gds/procedures/integration => facade/src/main/java/org/neo4j/gds/procedures}/ExporterBuildersProviderService.java (95%) rename {proc/common/src/main/java/org/neo4j/gds/services => procedures/facade/src/main/java/org/neo4j/gds/procedures}/UserAccessor.java (97%) rename {proc/common/src/main/java/org/neo4j/gds/services => procedures/facade/src/main/java/org/neo4j/gds/procedures}/UserLogServices.java (98%) rename {proc/common/src/test/java/org/neo4j/gds/services => procedures/facade/src/test/java/org/neo4j/gds/procedures}/UserLogServicesTest.java (98%) diff --git a/proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java b/proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java new file mode 100644 index 00000000000..d8072c04a59 --- /dev/null +++ b/proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds; + +import org.neo4j.internal.kernel.api.connectioninfo.ClientConnectionInfo; +import org.neo4j.internal.kernel.api.security.AbstractSecurityLog; +import org.neo4j.internal.kernel.api.security.AccessMode; +import org.neo4j.internal.kernel.api.security.AdminAccessMode; +import org.neo4j.internal.kernel.api.security.AdminActionOnResource; +import org.neo4j.internal.kernel.api.security.AuthSubject; +import org.neo4j.internal.kernel.api.security.DatabaseAccessMode; +import org.neo4j.internal.kernel.api.security.PermissionState; +import org.neo4j.internal.kernel.api.security.SecurityAuthorizationHandler; +import org.neo4j.internal.kernel.api.security.SecurityContext; + +import java.util.Set; + +/** + * Let's build this out as needed. + * It needs to be just good enough for what we need through ProcedureRunner, nothing more + */ +class FakeSecurityContext extends SecurityContext { + FakeSecurityContext() { + super(null, null, null, null); + } + + @Override + public AccessMode mode() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public DatabaseAccessMode databaseAccessMode() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public String database() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public PermissionState allowExecuteAdminProcedure(int procedureId) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public PermissionState allowsAdminAction(AdminActionOnResource action) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public Set roles() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public SecurityContext authorize(IdLookup idLookup, String dbName, AbstractSecurityLog securityLog) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public SecurityContext withMode(AccessMode mode) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public SecurityContext withMode(AdminAccessMode adminAccessMode) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public void assertCredentialsNotExpired(SecurityAuthorizationHandler handler) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public String description() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + protected String defaultString(String name) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public AuthSubject subject() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public ClientConnectionInfo connectionInfo() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public boolean impersonating() { + throw new UnsupportedOperationException("TODO"); + } +} diff --git a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java index afd672bbf5b..9cee83bf5cc 100644 --- a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java +++ b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java @@ -19,7 +19,9 @@ */ package org.neo4j.gds; +import org.jetbrains.annotations.Nullable; import org.neo4j.gds.api.AlgorithmMetaDataSetter; +import org.neo4j.gds.api.DatabaseId; import org.neo4j.gds.api.GraphLoaderContext; import org.neo4j.gds.api.User; import org.neo4j.gds.applications.algorithms.machinery.DefaultAlgorithmProcessingTemplate; @@ -33,14 +35,21 @@ import org.neo4j.gds.core.utils.progress.TaskRegistryFactory; import org.neo4j.gds.core.utils.warnings.EmptyUserLogRegistryFactory; import org.neo4j.gds.core.utils.warnings.UserLogRegistryFactory; +import org.neo4j.gds.core.write.ExporterContext; +import org.neo4j.gds.core.write.NativeExportBuildersProvider; import org.neo4j.gds.metrics.MetricsFacade; +import org.neo4j.gds.procedures.CatalogProcedureFacadeFactory; import org.neo4j.gds.procedures.GraphDataScienceProcedures; +import org.neo4j.gds.procedures.TaskRegistryFactoryService; import org.neo4j.gds.procedures.integration.LogAdapter; -import org.neo4j.gds.services.DatabaseIdAccessor; +import org.neo4j.gds.procedures.DatabaseIdAccessor; +import org.neo4j.gds.procedures.UserLogServices; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Transaction; import org.neo4j.internal.kernel.api.procs.ProcedureCallContext; +import org.neo4j.internal.kernel.api.security.SecurityContext; import org.neo4j.kernel.api.KernelTransaction; +import org.neo4j.kernel.impl.coreapi.InternalTransaction; import org.neo4j.logging.Log; import java.util.Optional; @@ -104,6 +113,7 @@ public static

P applyOnProcedure( databaseService, procedureCallContext, taskRegistryFactory, + tx, username ); @@ -141,6 +151,7 @@ private static GraphDataScienceProcedures createGraphDataScienceProcedures( GraphDatabaseService graphDatabaseService, ProcedureCallContext procedureCallContext, TaskRegistryFactory taskRegistryFactory, + Transaction procedureTransaction, Username username ) { var gdsLog = new LogAdapter(log); @@ -161,6 +172,37 @@ private static GraphDataScienceProcedures createGraphDataScienceProcedures( requestScopedDependencies ); + var catalogProcedureFacadeFactory = new CatalogProcedureFacadeFactory( + gdsLog, + __ -> new NativeExportBuildersProvider(), // procedure runner is OpenGDS + new TaskRegistryFactoryService(false, null) { + @Override + public TaskRegistryFactory getTaskRegistryFactory(DatabaseId databaseId, User user) { + return taskRegistryFactory; + } + }, + new UserLogServices() + ); + + var securityContext = new FakeSecurityContext(); + + var exporterContext = new ExporterContext() { + @Override + public GraphDatabaseService graphDatabaseAPI() { + return graphDatabaseService; + } + + @Override + public @Nullable InternalTransaction internalTransaction() { + return (InternalTransaction) procedureTransaction; + } + + @Override + public SecurityContext securityContext() { + return securityContext; + } + }; + return GraphDataScienceProcedures.create( gdsLog, DefaultsConfiguration.Instance, @@ -173,7 +215,12 @@ private static GraphDataScienceProcedures createGraphDataScienceProcedures( kernelTransaction, GraphLoaderContext.NULL_CONTEXT, procedureCallContext, - requestScopedDependencies + requestScopedDependencies, + catalogProcedureFacadeFactory, + securityContext, + exporterContext, + graphDatabaseService, + procedureTransaction ); } } diff --git a/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java b/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java index 276bbe8bb92..6dec91b0eb9 100644 --- a/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java +++ b/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java @@ -24,7 +24,7 @@ import org.neo4j.gds.core.model.OpenModelCatalogProvider; import org.neo4j.gds.core.write.NativeExportBuildersProvider; import org.neo4j.gds.metrics.MetricsFacade; -import org.neo4j.gds.procedures.integration.ExporterBuildersProviderService; +import org.neo4j.gds.procedures.ExporterBuildersProviderService; import org.neo4j.gds.procedures.integration.GraphDataScienceExtensionBuilder; import org.neo4j.gds.procedures.integration.LogAccessor; import org.neo4j.kernel.api.procedure.GlobalProcedures; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/CatalogProcedureFacadeFactory.java similarity index 75% rename from procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/CatalogProcedureFacadeFactory.java index 6de01603df9..a1c17198910 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CatalogFacadeProvider.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/CatalogProcedureFacadeFactory.java @@ -17,24 +17,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.procedures.integration; +package org.neo4j.gds.procedures; -import org.neo4j.gds.procedures.ProcedureCallContextReturnColumns; import org.neo4j.gds.applications.ApplicationsFacade; import org.neo4j.gds.applications.graphstorecatalog.GraphProjectMemoryUsageService; import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.core.write.ExporterContext; import org.neo4j.gds.logging.Log; -import org.neo4j.gds.procedures.KernelTransactionAccessor; -import org.neo4j.gds.procedures.ProcedureTransactionAccessor; -import org.neo4j.gds.procedures.TaskRegistryFactoryService; -import org.neo4j.gds.procedures.TerminationFlagAccessor; -import org.neo4j.gds.procedures.TransactionContextAccessor; import org.neo4j.gds.procedures.catalog.CatalogProcedureFacade; -import org.neo4j.gds.services.DatabaseIdAccessor; -import org.neo4j.gds.services.UserAccessor; -import org.neo4j.gds.services.UserLogServices; -import org.neo4j.kernel.api.procedure.Context; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Transaction; +import org.neo4j.internal.kernel.api.procs.ProcedureCallContext; +import org.neo4j.internal.kernel.api.security.SecurityContext; +import org.neo4j.kernel.api.KernelTransaction; import java.util.function.Consumer; @@ -43,14 +38,10 @@ * from a {@link org.neo4j.kernel.api.procedure.Context}, at request time. *

* We can resolve things like user and database id here, construct termination flags, and such. - *

- * We call it a provider because it is used as a sub-provider to the {@link org.neo4j.gds.procedures.GraphDataScienceProcedures} provider. */ -class CatalogFacadeProvider { +public class CatalogProcedureFacadeFactory { // dull bits private final DatabaseIdAccessor databaseIdAccessor = new DatabaseIdAccessor(); - private final KernelTransactionAccessor kernelTransactionAccessor = new KernelTransactionAccessor(); - private final ProcedureTransactionAccessor procedureTransactionAccessor = new ProcedureTransactionAccessor(); private final TerminationFlagAccessor terminationFlagAccessor = new TerminationFlagAccessor(); private final TransactionContextAccessor transactionContextAccessor = new TransactionContextAccessor(); private final UserAccessor userAccessor = new UserAccessor(); @@ -65,11 +56,11 @@ class CatalogFacadeProvider { /** * We inject services here so that we may control and isolate access to dependencies. - * Take {@link org.neo4j.gds.services.UserAccessor} for example. + * Take {@link org.neo4j.gds.procedures.UserAccessor} for example. * Without it, I would have to stub out Neo4j's {@link org.neo4j.kernel.api.procedure.Context}, in a non-trivial, * ugly way. Now instead I can inject the user by stubbing out GDS' own little POJO service. */ - CatalogFacadeProvider( + public CatalogProcedureFacadeFactory( Log log, ExporterBuildersProviderService exporterBuildersProviderService, TaskRegistryFactoryService taskRegistryFactoryService, @@ -86,16 +77,19 @@ class CatalogFacadeProvider { * We construct the catalog facade at request time. At this point things like user and database id are set in stone. * And we can readily construct things like termination flags. */ - CatalogProcedureFacade createCatalogProcedureFacade(ApplicationsFacade applicationsFacade, Context context) { - // Neo4j's basic request scoped services - var graphDatabaseService = context.graphDatabaseAPI(); - var kernelTransaction = kernelTransactionAccessor.getKernelTransaction(context); - var procedureTransaction = procedureTransactionAccessor.getProcedureTransaction(context); - + CatalogProcedureFacade createCatalogProcedureFacade( + ApplicationsFacade applicationsFacade, + GraphDatabaseService graphDatabaseService, + KernelTransaction kernelTransaction, + Transaction procedureTransaction, + ProcedureCallContext procedureCallContext, + SecurityContext securityContext, + ExporterContext exporterContext + ) { // Derived data and services var databaseId = databaseIdAccessor.getDatabaseId(graphDatabaseService); var graphProjectMemoryUsageService = new GraphProjectMemoryUsageService(log, graphDatabaseService); - var procedureReturnColumns = new ProcedureCallContextReturnColumns(context.procedureCallContext()); + var procedureReturnColumns = new ProcedureCallContextReturnColumns(procedureCallContext); var streamCloser = new Consumer() { @Override public void accept(AutoCloseable autoCloseable) { @@ -107,7 +101,7 @@ public void accept(AutoCloseable autoCloseable) { graphDatabaseService, procedureTransaction ); - var user = userAccessor.getUser(context.securityContext()); + var user = userAccessor.getUser(securityContext); var userLogStore = userLogServices.getUserLogStore(databaseId); var taskRegistryFactory = taskRegistryFactoryService.getTaskRegistryFactory(databaseId, user); @@ -115,7 +109,6 @@ public void accept(AutoCloseable autoCloseable) { // Exporter builders var exportBuildersProvider = exporterBuildersProviderService.identifyExportBuildersProvider(graphDatabaseService); - var exporterContext = new ExporterContext.ProcedureContextWrapper(context); var nodeLabelExporterBuilder = exportBuildersProvider.nodeLabelExporterBuilder(exporterContext); var nodePropertyExporterBuilder = exportBuildersProvider.nodePropertyExporterBuilder(exporterContext); var relationshipExporterBuilder = exportBuildersProvider.relationshipExporterBuilder(exporterContext); diff --git a/proc/common/src/main/java/org/neo4j/gds/services/DatabaseIdAccessor.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/DatabaseIdAccessor.java similarity index 96% rename from proc/common/src/main/java/org/neo4j/gds/services/DatabaseIdAccessor.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/DatabaseIdAccessor.java index a51f03d9189..1cfb3160a54 100644 --- a/proc/common/src/main/java/org/neo4j/gds/services/DatabaseIdAccessor.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/DatabaseIdAccessor.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.services; +package org.neo4j.gds.procedures; import org.neo4j.gds.api.DatabaseId; import org.neo4j.graphdb.GraphDatabaseService; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/ExporterBuildersProviderService.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/ExporterBuildersProviderService.java similarity index 95% rename from procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/ExporterBuildersProviderService.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/ExporterBuildersProviderService.java index c8d68e768fb..4675117bbab 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/ExporterBuildersProviderService.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/ExporterBuildersProviderService.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.procedures.integration; +package org.neo4j.gds.procedures; import org.neo4j.gds.core.write.ExportBuildersProvider; import org.neo4j.graphdb.GraphDatabaseService; diff --git a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java index 42734cd210c..8b3510b71f0 100644 --- a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java @@ -30,6 +30,7 @@ import org.neo4j.gds.configuration.DefaultsConfiguration; import org.neo4j.gds.configuration.LimitsConfiguration; import org.neo4j.gds.core.loading.GraphStoreCatalogService; +import org.neo4j.gds.core.write.ExporterContext; import org.neo4j.gds.logging.Log; import org.neo4j.gds.memest.DatabaseGraphStoreEstimationService; import org.neo4j.gds.metrics.procedures.DeprecatedProceduresMetricService; @@ -48,7 +49,10 @@ import org.neo4j.gds.procedures.embeddings.NodeEmbeddingsProcedureFacade; import org.neo4j.gds.procedures.misc.MiscAlgorithmsProcedureFacade; import org.neo4j.gds.procedures.pipelines.PipelinesProcedureFacade; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Transaction; import org.neo4j.internal.kernel.api.procs.ProcedureCallContext; +import org.neo4j.internal.kernel.api.security.SecurityContext; import org.neo4j.kernel.api.KernelTransaction; import java.util.Optional; @@ -104,7 +108,12 @@ public static GraphDataScienceProcedures create( KernelTransaction kernelTransaction, GraphLoaderContext graphLoaderContext, ProcedureCallContext procedureCallContext, - RequestScopedDependencies requestScopedDependencies + RequestScopedDependencies requestScopedDependencies, + CatalogProcedureFacadeFactory catalogProcedureFacadeFactory, + SecurityContext securityContext, + ExporterContext exporterContext, + GraphDatabaseService graphDatabaseService, + Transaction transaction ) { var configurationParser = new ConfigurationParser(defaultsConfiguration, limitsConfiguration); var configurationCreator = new ConfigurationCreator( @@ -143,6 +152,16 @@ public static GraphDataScienceProcedures create( writeRelationshipService ); + var catalogProcedureFacade = catalogProcedureFacadeFactory.createCatalogProcedureFacade( + applicationsFacade, + graphDatabaseService, + kernelTransaction, + transaction, + procedureCallContext, + securityContext, + exporterContext + ); + var closeableResourceRegistry = new TransactionCloseableResourceRegistry(kernelTransaction); var centralityProcedureFacade = CentralityProcedureFacade.create( @@ -156,6 +175,7 @@ public static GraphDataScienceProcedures create( ); return new GraphDataScienceProceduresBuilder(log) + .with(catalogProcedureFacade) .with(centralityProcedureFacade) .build(); } diff --git a/proc/common/src/main/java/org/neo4j/gds/services/UserAccessor.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/UserAccessor.java similarity index 97% rename from proc/common/src/main/java/org/neo4j/gds/services/UserAccessor.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/UserAccessor.java index e8ed16f340a..70909cb0bff 100644 --- a/proc/common/src/main/java/org/neo4j/gds/services/UserAccessor.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/UserAccessor.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.services; +package org.neo4j.gds.procedures; import org.neo4j.gds.api.User; import org.neo4j.gds.compat.Neo4jProxy; diff --git a/proc/common/src/main/java/org/neo4j/gds/services/UserLogServices.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/UserLogServices.java similarity index 98% rename from proc/common/src/main/java/org/neo4j/gds/services/UserLogServices.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/UserLogServices.java index fedda1e09bb..187fa10506a 100644 --- a/proc/common/src/main/java/org/neo4j/gds/services/UserLogServices.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/UserLogServices.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.services; +package org.neo4j.gds.procedures; import org.neo4j.gds.api.DatabaseId; import org.neo4j.gds.api.User; diff --git a/proc/common/src/test/java/org/neo4j/gds/services/UserLogServicesTest.java b/procedures/facade/src/test/java/org/neo4j/gds/procedures/UserLogServicesTest.java similarity index 98% rename from proc/common/src/test/java/org/neo4j/gds/services/UserLogServicesTest.java rename to procedures/facade/src/test/java/org/neo4j/gds/procedures/UserLogServicesTest.java index 10e362f532d..5151aa5caf1 100644 --- a/proc/common/src/test/java/org/neo4j/gds/services/UserLogServicesTest.java +++ b/procedures/facade/src/test/java/org/neo4j/gds/procedures/UserLogServicesTest.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.services; +package org.neo4j.gds.procedures; import org.junit.jupiter.api.Test; import org.neo4j.gds.api.DatabaseId; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceExtensionBuilder.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceExtensionBuilder.java index 1d478812203..900e9595dbe 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceExtensionBuilder.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceExtensionBuilder.java @@ -31,9 +31,10 @@ import org.neo4j.gds.logging.Log; import org.neo4j.gds.mem.MemoryGauge; import org.neo4j.gds.metrics.MetricsFacade; +import org.neo4j.gds.procedures.ExporterBuildersProviderService; import org.neo4j.gds.procedures.GraphDataScienceProcedures; import org.neo4j.gds.procedures.TaskRegistryFactoryService; -import org.neo4j.gds.services.UserLogServices; +import org.neo4j.gds.procedures.UserLogServices; import org.neo4j.gds.settings.GdsSettings; import org.neo4j.graphdb.config.Configuration; import org.neo4j.kernel.api.procedure.GlobalProcedures; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProviderFactory.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProviderFactory.java index cbf253022d0..ea4e33a0b06 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProviderFactory.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProviderFactory.java @@ -29,9 +29,11 @@ import org.neo4j.gds.mem.MemoryGauge; import org.neo4j.gds.metrics.MetricsFacade; import org.neo4j.gds.modelcatalogservices.ModelCatalogServiceProvider; +import org.neo4j.gds.procedures.CatalogProcedureFacadeFactory; +import org.neo4j.gds.procedures.ExporterBuildersProviderService; import org.neo4j.gds.procedures.TaskRegistryFactoryService; import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationParser; -import org.neo4j.gds.services.UserLogServices; +import org.neo4j.gds.procedures.UserLogServices; import java.util.Optional; import java.util.function.Function; @@ -83,7 +85,7 @@ GraphDataScienceProvider createGraphDataScienceProvider( boolean useMaxMemoryEstimation, UserLogServices userLogServices ) { - var catalogFacadeProvider = new CatalogFacadeProvider( + var catalogProcedureFacadeFactory = new CatalogProcedureFacadeFactory( log, exporterBuildersProviderService, taskRegistryFactoryService, @@ -105,7 +107,7 @@ GraphDataScienceProvider createGraphDataScienceProvider( metricsFacade.algorithmMetrics(), algorithmProcessingTemplateDecorator, catalogBusinessFacadeDecorator, - catalogFacadeProvider, + catalogProcedureFacadeFactory, configurationParser, metricsFacade.deprecatedProcedures(), exporterBuildersProviderService, diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java index 9c318a8d118..f7067307cbb 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java @@ -20,8 +20,8 @@ package org.neo4j.gds.procedures.integration; import org.neo4j.gds.procedures.pipelines.PipelinesProcedureFacade; -import org.neo4j.gds.services.UserAccessor; -import org.neo4j.kernel.api.procedure.Context; +import org.neo4j.gds.procedures.UserAccessor; +import org.neo4j.internal.kernel.api.security.SecurityContext; /** * Lifecycle: global @@ -29,8 +29,8 @@ class PipelinesProcedureFacadeProvider { private final UserAccessor userAccessor = new UserAccessor(); - PipelinesProcedureFacade createPipelinesProcedureFacade(Context context) { - var user = userAccessor.getUser(context.securityContext()); + PipelinesProcedureFacade createPipelinesProcedureFacade(SecurityContext securityContext) { + var user = userAccessor.getUser(securityContext); return new PipelinesProcedureFacade(user); } diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskRegistryFactoryProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskRegistryFactoryProvider.java index 8e21ca9860f..8ba5ffe3c99 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskRegistryFactoryProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskRegistryFactoryProvider.java @@ -22,8 +22,8 @@ import org.neo4j.function.ThrowingFunction; import org.neo4j.gds.core.utils.progress.TaskRegistryFactory; import org.neo4j.gds.procedures.TaskRegistryFactoryService; -import org.neo4j.gds.services.DatabaseIdAccessor; -import org.neo4j.gds.services.UserAccessor; +import org.neo4j.gds.procedures.DatabaseIdAccessor; +import org.neo4j.gds.procedures.UserAccessor; import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.procedure.Context; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskStoreProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskStoreProvider.java index ad8b2d174a1..2eba95ad0dc 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskStoreProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/TaskStoreProvider.java @@ -23,7 +23,7 @@ import org.neo4j.gds.api.DatabaseId; import org.neo4j.gds.core.utils.progress.TaskStore; import org.neo4j.gds.core.utils.progress.TaskStoreService; -import org.neo4j.gds.services.DatabaseIdAccessor; +import org.neo4j.gds.procedures.DatabaseIdAccessor; import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.procedure.Context; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/UserLogRegistryFactoryProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/UserLogRegistryFactoryProvider.java index 05e561f590f..d0f40098c84 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/UserLogRegistryFactoryProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/UserLogRegistryFactoryProvider.java @@ -21,9 +21,9 @@ import org.neo4j.function.ThrowingFunction; import org.neo4j.gds.core.utils.warnings.UserLogRegistryFactory; -import org.neo4j.gds.services.DatabaseIdAccessor; -import org.neo4j.gds.services.UserAccessor; -import org.neo4j.gds.services.UserLogServices; +import org.neo4j.gds.procedures.DatabaseIdAccessor; +import org.neo4j.gds.procedures.UserAccessor; +import org.neo4j.gds.procedures.UserLogServices; import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.procedure.Context; From 16819e8a69a346c798a466276f88888af8d695b8 Mon Sep 17 00:00:00 2001 From: Lasse Westh-Nielsen Date: Mon, 27 May 2024 14:13:32 +0200 Subject: [PATCH 3/4] move pipelines facade scaffolding from into procedure facade factory method --- .../GraphDataScienceProcedures.java | 3 ++ .../PipelinesProcedureFacadeProvider.java | 37 ------------------- 2 files changed, 3 insertions(+), 37 deletions(-) delete mode 100644 procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java diff --git a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java index 8b3510b71f0..62eeb50b321 100644 --- a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java @@ -174,9 +174,12 @@ public static GraphDataScienceProcedures create( new WriteModeAlgorithmRunner(configurationCreator) ); + var pipelinesProcedureFacade = new PipelinesProcedureFacade(requestScopedDependencies.getUser()); + return new GraphDataScienceProceduresBuilder(log) .with(catalogProcedureFacade) .with(centralityProcedureFacade) + .with(pipelinesProcedureFacade) .build(); } diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java deleted file mode 100644 index f7067307cbb..00000000000 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/PipelinesProcedureFacadeProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.gds.procedures.integration; - -import org.neo4j.gds.procedures.pipelines.PipelinesProcedureFacade; -import org.neo4j.gds.procedures.UserAccessor; -import org.neo4j.internal.kernel.api.security.SecurityContext; - -/** - * Lifecycle: global - */ -class PipelinesProcedureFacadeProvider { - private final UserAccessor userAccessor = new UserAccessor(); - - PipelinesProcedureFacade createPipelinesProcedureFacade(SecurityContext securityContext) { - var user = userAccessor.getUser(securityContext); - - return new PipelinesProcedureFacade(user); - } -} From fdbe655e20cccade46f91b6d97d6c68d76fb519e Mon Sep 17 00:00:00 2001 From: Lasse Westh-Nielsen Date: Mon, 27 May 2024 14:42:46 +0200 Subject: [PATCH 4/4] move algorithms facade scaffolding from into procedure facade factory method --- .../MemoryEstimationExecutorTest.java | 4 +- .../gds/executor/ProcedureExecutorTest.java | 4 +- .../src/main/java/org/neo4j/gds/BaseProc.java | 1 + proc/test/build.gradle | 1 + .../org/neo4j/gds/FakeSecurityContext.java | 118 ---------------- .../java/org/neo4j/gds/ProcedureRunner.java | 39 +++++- .../procedures/AlgorithmFacadeBuilder.java} | 6 +- .../AlgorithmFacadeBuilderFactory.java} | 21 ++- .../GraphDataScienceProcedures.java | 41 ++++-- .../procedures}/TransactionNodeLookup.java | 2 +- .../integration/GraphDataScienceProvider.java | 128 +++++------------- .../GraphDataScienceProviderFactory.java | 9 +- 12 files changed, 119 insertions(+), 255 deletions(-) delete mode 100644 proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java rename procedures/{integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactory.java => facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilder.java} (99%) rename procedures/{integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java => facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilderFactory.java} (91%) rename {proc/common/src/main/java/org/neo4j/gds => procedures/facade/src/main/java/org/neo4j/gds/procedures}/TransactionNodeLookup.java (97%) diff --git a/executor/src/test/java/org/neo4j/gds/executor/MemoryEstimationExecutorTest.java b/executor/src/test/java/org/neo4j/gds/executor/MemoryEstimationExecutorTest.java index c71680cb5e7..e8231333235 100644 --- a/executor/src/test/java/org/neo4j/gds/executor/MemoryEstimationExecutorTest.java +++ b/executor/src/test/java/org/neo4j/gds/executor/MemoryEstimationExecutorTest.java @@ -25,12 +25,12 @@ import org.neo4j.gds.BaseTest; import org.neo4j.gds.GdsCypher; import org.neo4j.gds.NodeProjections; -import org.neo4j.gds.ProcedureCallContextReturnColumns; import org.neo4j.gds.RelationshipProjections; import org.neo4j.gds.api.AlgorithmMetaDataSetter; import org.neo4j.gds.api.CloseableResourceRegistry; import org.neo4j.gds.api.DatabaseId; import org.neo4j.gds.api.NodeLookup; +import org.neo4j.gds.api.ProcedureReturnColumns; import org.neo4j.gds.catalog.GraphProjectProc; import org.neo4j.gds.compat.GraphDatabaseApiProxy; import org.neo4j.gds.compat.Neo4jProxy; @@ -75,7 +75,7 @@ void setup() throws Exception { .builder() .databaseId(DatabaseId.of(db.databaseName())) .dependencyResolver(GraphDatabaseApiProxy.dependencyResolver(db)) - .returnColumns(ProcedureCallContextReturnColumns.EMPTY) + .returnColumns(ProcedureReturnColumns.EMPTY) .log(Neo4jProxy.testLog()) .taskRegistryFactory(EmptyTaskRegistryFactory.INSTANCE) .userLogRegistryFactory(EmptyUserLogRegistryFactory.INSTANCE) diff --git a/executor/src/test/java/org/neo4j/gds/executor/ProcedureExecutorTest.java b/executor/src/test/java/org/neo4j/gds/executor/ProcedureExecutorTest.java index 302972b7589..eca331341a2 100644 --- a/executor/src/test/java/org/neo4j/gds/executor/ProcedureExecutorTest.java +++ b/executor/src/test/java/org/neo4j/gds/executor/ProcedureExecutorTest.java @@ -22,11 +22,11 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.neo4j.gds.ProcedureCallContextReturnColumns; import org.neo4j.gds.api.AlgorithmMetaDataSetter; import org.neo4j.gds.api.CloseableResourceRegistry; import org.neo4j.gds.api.GraphStore; import org.neo4j.gds.api.NodeLookup; +import org.neo4j.gds.api.ProcedureReturnColumns; import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.config.GraphProjectConfig; import org.neo4j.gds.core.loading.GraphStoreCatalog; @@ -133,7 +133,7 @@ private ExecutionContext executionContext(TaskStore taskStore) { .builder() .databaseId(graphStore.databaseInfo().databaseId()) .log(Neo4jProxy.testLog()) - .returnColumns(ProcedureCallContextReturnColumns.EMPTY) + .returnColumns(ProcedureReturnColumns.EMPTY) .taskRegistryFactory(jobId -> new TaskRegistry("", taskStore, jobId)) .username("") .terminationMonitor(TerminationMonitor.EMPTY) diff --git a/proc/common/src/main/java/org/neo4j/gds/BaseProc.java b/proc/common/src/main/java/org/neo4j/gds/BaseProc.java index 090577b0d15..f7b01010cbb 100644 --- a/proc/common/src/main/java/org/neo4j/gds/BaseProc.java +++ b/proc/common/src/main/java/org/neo4j/gds/BaseProc.java @@ -35,6 +35,7 @@ import org.neo4j.gds.procedures.GraphDataScienceProcedures; import org.neo4j.gds.procedures.ProcedureCallContextReturnColumns; import org.neo4j.gds.procedures.TransactionCloseableResourceRegistry; +import org.neo4j.gds.procedures.TransactionNodeLookup; import org.neo4j.gds.procedures.integration.TransactionTerminationMonitor; import org.neo4j.gds.transaction.DatabaseTransactionContext; import org.neo4j.gds.transaction.EmptyTransactionContext; diff --git a/proc/test/build.gradle b/proc/test/build.gradle index 632c339d9d2..ca2e86ab929 100644 --- a/proc/test/build.gradle +++ b/proc/test/build.gradle @@ -34,6 +34,7 @@ dependencies { implementation project(':neo4j-api') implementation project(':opengds-procedure-facade') implementation project(':open-licensing') + implementation project(':open-model-catalog') implementation project(':pregel') implementation project(':procedure-integration') implementation project(':progress-tracking') diff --git a/proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java b/proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java deleted file mode 100644 index d8072c04a59..00000000000 --- a/proc/test/src/main/java/org/neo4j/gds/FakeSecurityContext.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.gds; - -import org.neo4j.internal.kernel.api.connectioninfo.ClientConnectionInfo; -import org.neo4j.internal.kernel.api.security.AbstractSecurityLog; -import org.neo4j.internal.kernel.api.security.AccessMode; -import org.neo4j.internal.kernel.api.security.AdminAccessMode; -import org.neo4j.internal.kernel.api.security.AdminActionOnResource; -import org.neo4j.internal.kernel.api.security.AuthSubject; -import org.neo4j.internal.kernel.api.security.DatabaseAccessMode; -import org.neo4j.internal.kernel.api.security.PermissionState; -import org.neo4j.internal.kernel.api.security.SecurityAuthorizationHandler; -import org.neo4j.internal.kernel.api.security.SecurityContext; - -import java.util.Set; - -/** - * Let's build this out as needed. - * It needs to be just good enough for what we need through ProcedureRunner, nothing more - */ -class FakeSecurityContext extends SecurityContext { - FakeSecurityContext() { - super(null, null, null, null); - } - - @Override - public AccessMode mode() { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public DatabaseAccessMode databaseAccessMode() { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public String database() { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public PermissionState allowExecuteAdminProcedure(int procedureId) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public PermissionState allowsAdminAction(AdminActionOnResource action) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public Set roles() { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public SecurityContext authorize(IdLookup idLookup, String dbName, AbstractSecurityLog securityLog) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public SecurityContext withMode(AccessMode mode) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public SecurityContext withMode(AdminAccessMode adminAccessMode) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public void assertCredentialsNotExpired(SecurityAuthorizationHandler handler) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public String description() { - throw new UnsupportedOperationException("TODO"); - } - - @Override - protected String defaultString(String name) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public AuthSubject subject() { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public ClientConnectionInfo connectionInfo() { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public boolean impersonating() { - throw new UnsupportedOperationException("TODO"); - } -} diff --git a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java index 9cee83bf5cc..7b989f8c58f 100644 --- a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java +++ b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java @@ -32,12 +32,18 @@ import org.neo4j.gds.configuration.LimitsConfiguration; import org.neo4j.gds.core.Username; import org.neo4j.gds.core.loading.GraphStoreCatalogService; +import org.neo4j.gds.core.model.OpenModelCatalog; import org.neo4j.gds.core.utils.progress.TaskRegistryFactory; import org.neo4j.gds.core.utils.warnings.EmptyUserLogRegistryFactory; import org.neo4j.gds.core.utils.warnings.UserLogRegistryFactory; import org.neo4j.gds.core.write.ExporterContext; import org.neo4j.gds.core.write.NativeExportBuildersProvider; import org.neo4j.gds.metrics.MetricsFacade; +import org.neo4j.gds.metrics.PassthroughExecutionMetricRegistrar; +import org.neo4j.gds.metrics.algorithms.AlgorithmMetricsService; +import org.neo4j.gds.metrics.procedures.DeprecatedProceduresMetricService; +import org.neo4j.gds.modelcatalogservices.ModelCatalogServiceProvider; +import org.neo4j.gds.procedures.AlgorithmFacadeBuilderFactory; import org.neo4j.gds.procedures.CatalogProcedureFacadeFactory; import org.neo4j.gds.procedures.GraphDataScienceProcedures; import org.neo4j.gds.procedures.TaskRegistryFactoryService; @@ -47,6 +53,8 @@ import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Transaction; import org.neo4j.internal.kernel.api.procs.ProcedureCallContext; +import org.neo4j.internal.kernel.api.security.AuthSubject; +import org.neo4j.internal.kernel.api.security.AuthenticationResult; import org.neo4j.internal.kernel.api.security.SecurityContext; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.impl.coreapi.InternalTransaction; @@ -184,7 +192,22 @@ public TaskRegistryFactory getTaskRegistryFactory(DatabaseId databaseId, User us new UserLogServices() ); - var securityContext = new FakeSecurityContext(); + var securityContext = new SecurityContext(new AuthSubject() { + @Override + public AuthenticationResult getAuthenticationResult() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public boolean hasUsername(String username) { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public String executingUser() { + return username.username(); + } + }, null, null, null); var exporterContext = new ExporterContext() { @Override @@ -203,6 +226,16 @@ public SecurityContext securityContext() { } }; + var modelCatalog = new OpenModelCatalog(); + + var algorithmFacadeBuilderFactory = new AlgorithmFacadeBuilderFactory( + gdsLog, + graphStoreCatalogService, + false, + new AlgorithmMetricsService(new PassthroughExecutionMetricRegistrar()), + new ModelCatalogServiceProvider(modelCatalog) + ); + return GraphDataScienceProcedures.create( gdsLog, DefaultsConfiguration.Instance, @@ -220,7 +253,9 @@ public SecurityContext securityContext() { securityContext, exporterContext, graphDatabaseService, - procedureTransaction + procedureTransaction, + algorithmFacadeBuilderFactory, + DeprecatedProceduresMetricService.PASSTHROUGH ); } } diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactory.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilder.java similarity index 99% rename from procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactory.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilder.java index b9d72431db5..4e00f71bc16 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactory.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilder.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.procedures.integration; +package org.neo4j.gds.procedures; import org.neo4j.gds.algorithms.centrality.CentralityAlgorithmsEstimateBusinessFacade; import org.neo4j.gds.algorithms.centrality.CentralityAlgorithmsFacade; @@ -65,7 +65,7 @@ import org.neo4j.gds.procedures.embeddings.NodeEmbeddingsProcedureFacade; import org.neo4j.gds.procedures.misc.MiscAlgorithmsProcedureFacade; -class AlgorithmFacadeFactory { +class AlgorithmFacadeBuilder { // Request scoped parameters private final ConfigurationCreator configurationCreator; private final NodeLookup nodeLookup; @@ -82,7 +82,7 @@ class AlgorithmFacadeFactory { private final StatsModeAlgorithmRunner statsModeAlgorithmRunner; private final WriteModeAlgorithmRunner writeModeAlgorithmRunner; - AlgorithmFacadeFactory( + AlgorithmFacadeBuilder( ConfigurationCreator configurationCreator, NodeLookup nodeLookup, ProcedureReturnColumns procedureReturnColumns, diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilderFactory.java similarity index 91% rename from procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilderFactory.java index 52c58306c7f..05551d1647c 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/AlgorithmFacadeFactoryProvider.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/AlgorithmFacadeBuilderFactory.java @@ -17,11 +17,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds.procedures.integration; +package org.neo4j.gds.procedures; -import org.neo4j.gds.procedures.ProcedureCallContextReturnColumns; -import org.neo4j.gds.procedures.TransactionCloseableResourceRegistry; -import org.neo4j.gds.TransactionNodeLookup; import org.neo4j.gds.algorithms.AlgorithmMemoryValidationService; import org.neo4j.gds.algorithms.estimation.AlgorithmEstimator; import org.neo4j.gds.algorithms.mutateservices.MutateNodePropertyService; @@ -42,10 +39,10 @@ import org.neo4j.gds.procedures.algorithms.runners.WriteModeAlgorithmRunner; import org.neo4j.gds.procedures.algorithms.stubs.GenericStub; import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.internal.kernel.api.procs.ProcedureCallContext; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.procedure.Context; -class AlgorithmFacadeFactoryProvider { +public class AlgorithmFacadeBuilderFactory { // dull utilities private final FictitiousGraphStoreEstimationService fictitiousGraphStoreEstimationService = new FictitiousGraphStoreEstimationService(); @@ -58,7 +55,7 @@ class AlgorithmFacadeFactoryProvider { private final AlgorithmMetricsService algorithmMetricsService; private final ModelCatalogServiceProvider modelCatalogServiceProvider; - AlgorithmFacadeFactoryProvider( + public AlgorithmFacadeBuilderFactory( Log log, GraphStoreCatalogService graphStoreCatalogService, boolean useMaxMemoryEstimation, @@ -73,15 +70,15 @@ class AlgorithmFacadeFactoryProvider { this.modelCatalogServiceProvider = modelCatalogServiceProvider; } - AlgorithmFacadeFactory createAlgorithmFacadeFactory( - Context context, + AlgorithmFacadeBuilder create( ConfigurationCreator configurationCreator, RequestScopedDependencies requestScopedDependencies, KernelTransaction kernelTransaction, GraphDatabaseService graphDatabaseService, DatabaseGraphStoreEstimationService databaseGraphStoreEstimationService, ApplicationsFacade applicationsFacade, - GenericStub genericStub + GenericStub genericStub, + ProcedureCallContext procedureCallContext ) { /* * GDS services derived from Procedure Context. @@ -92,7 +89,7 @@ AlgorithmFacadeFactory createAlgorithmFacadeFactory( var algorithmMemoryValidationService = new AlgorithmMemoryValidationService(log, useMaxMemoryEstimation); var mutateNodePropertyService = new MutateNodePropertyService(log); var nodeLookup = new TransactionNodeLookup(kernelTransaction); - var procedureReturnColumns = new ProcedureCallContextReturnColumns(context.procedureCallContext()); + var procedureReturnColumns = new ProcedureCallContextReturnColumns(procedureCallContext); // Second layer var writeNodePropertyService = new WriteNodePropertyService(log, requestScopedDependencies); @@ -119,7 +116,7 @@ AlgorithmFacadeFactory createAlgorithmFacadeFactory( var writeModeAlgorithmRunner = new WriteModeAlgorithmRunner(configurationCreator); // procedure facade - return new AlgorithmFacadeFactory( + return new AlgorithmFacadeBuilder( configurationCreator, nodeLookup, procedureReturnColumns, diff --git a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java index 62eeb50b321..40d05339934 100644 --- a/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/GraphDataScienceProcedures.java @@ -36,13 +36,8 @@ import org.neo4j.gds.metrics.procedures.DeprecatedProceduresMetricService; import org.neo4j.gds.metrics.projections.ProjectionMetricsService; import org.neo4j.gds.procedures.algorithms.AlgorithmsProcedureFacade; -import org.neo4j.gds.procedures.algorithms.centrality.CentralityProcedureFacade; import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationCreator; import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationParser; -import org.neo4j.gds.procedures.algorithms.runners.EstimationModeRunner; -import org.neo4j.gds.procedures.algorithms.runners.StatsModeAlgorithmRunner; -import org.neo4j.gds.procedures.algorithms.runners.StreamModeAlgorithmRunner; -import org.neo4j.gds.procedures.algorithms.runners.WriteModeAlgorithmRunner; import org.neo4j.gds.procedures.algorithms.stubs.GenericStub; import org.neo4j.gds.procedures.catalog.CatalogProcedureFacade; import org.neo4j.gds.procedures.community.CommunityProcedureFacade; @@ -113,7 +108,9 @@ public static GraphDataScienceProcedures create( SecurityContext securityContext, ExporterContext exporterContext, GraphDatabaseService graphDatabaseService, - Transaction transaction + Transaction transaction, + AlgorithmFacadeBuilderFactory algorithmFacadeBuilderFactory, + DeprecatedProceduresMetricService deprecatedProceduresMetricService ) { var configurationParser = new ConfigurationParser(defaultsConfiguration, limitsConfiguration); var configurationCreator = new ConfigurationCreator( @@ -162,24 +159,38 @@ public static GraphDataScienceProcedures create( exporterContext ); - var closeableResourceRegistry = new TransactionCloseableResourceRegistry(kernelTransaction); - - var centralityProcedureFacade = CentralityProcedureFacade.create( - genericStub, + var algorithmFacadeBuilder = algorithmFacadeBuilderFactory.create( + configurationCreator, + requestScopedDependencies, + kernelTransaction, + graphDatabaseService, + databaseGraphStoreEstimationService, applicationsFacade, - new ProcedureCallContextReturnColumns(procedureCallContext), - new EstimationModeRunner(configurationCreator), - new StatsModeAlgorithmRunner(configurationCreator), - new StreamModeAlgorithmRunner(closeableResourceRegistry, configurationCreator), - new WriteModeAlgorithmRunner(configurationCreator) + genericStub, + procedureCallContext ); + var centralityProcedureFacade = algorithmFacadeBuilder.createCentralityProcedureFacade(); + var oldCentralityProcedureFacade = algorithmFacadeBuilder.createOldCentralityProcedureFacade(); + var communityProcedureFacade = algorithmFacadeBuilder.createCommunityProcedureFacade(); + var miscAlgorithmsProcedureFacade = algorithmFacadeBuilder.createMiscellaneousProcedureFacade(); + var nodeEmbeddingsProcedureFacade = algorithmFacadeBuilder.createNodeEmbeddingsProcedureFacade(); + var pathFindingProcedureFacade = algorithmFacadeBuilder.createPathFindingProcedureFacade(); + var similarityProcedureFacade = algorithmFacadeBuilder.createSimilarityProcedureFacade(); + var pipelinesProcedureFacade = new PipelinesProcedureFacade(requestScopedDependencies.getUser()); return new GraphDataScienceProceduresBuilder(log) .with(catalogProcedureFacade) .with(centralityProcedureFacade) + .with(oldCentralityProcedureFacade) + .with(communityProcedureFacade) + .with(miscAlgorithmsProcedureFacade) + .with(nodeEmbeddingsProcedureFacade) + .with(pathFindingProcedureFacade) .with(pipelinesProcedureFacade) + .with(similarityProcedureFacade) + .with(deprecatedProceduresMetricService) .build(); } diff --git a/proc/common/src/main/java/org/neo4j/gds/TransactionNodeLookup.java b/procedures/facade/src/main/java/org/neo4j/gds/procedures/TransactionNodeLookup.java similarity index 97% rename from proc/common/src/main/java/org/neo4j/gds/TransactionNodeLookup.java rename to procedures/facade/src/main/java/org/neo4j/gds/procedures/TransactionNodeLookup.java index ca1d3ffb6a0..fc011ccd36e 100644 --- a/proc/common/src/main/java/org/neo4j/gds/TransactionNodeLookup.java +++ b/procedures/facade/src/main/java/org/neo4j/gds/procedures/TransactionNodeLookup.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.gds; +package org.neo4j.gds.procedures; import org.neo4j.gds.api.NodeLookup; import org.neo4j.graphdb.Node; diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProvider.java index 11f197736d3..86ff662b267 100644 --- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProvider.java +++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/GraphDataScienceProvider.java @@ -20,9 +20,6 @@ package org.neo4j.gds.procedures.integration; import org.neo4j.function.ThrowingFunction; -import org.neo4j.gds.algorithms.similarity.WriteRelationshipService; -import org.neo4j.gds.applications.ApplicationsFacade; -import org.neo4j.gds.applications.algorithms.machinery.AlgorithmEstimationTemplate; import org.neo4j.gds.applications.algorithms.machinery.AlgorithmProcessingTemplate; import org.neo4j.gds.applications.algorithms.machinery.DefaultAlgorithmProcessingTemplate; import org.neo4j.gds.applications.algorithms.machinery.DefaultMemoryGuard; @@ -34,21 +31,20 @@ import org.neo4j.gds.core.write.ExporterContext; import org.neo4j.gds.logging.Log; import org.neo4j.gds.mem.MemoryGauge; -import org.neo4j.gds.memest.DatabaseGraphStoreEstimationService; import org.neo4j.gds.metrics.algorithms.AlgorithmMetricsService; import org.neo4j.gds.metrics.procedures.DeprecatedProceduresMetricService; import org.neo4j.gds.metrics.projections.ProjectionMetricsService; +import org.neo4j.gds.procedures.AlgorithmFacadeBuilderFactory; +import org.neo4j.gds.procedures.CatalogProcedureFacadeFactory; +import org.neo4j.gds.procedures.DatabaseIdAccessor; +import org.neo4j.gds.procedures.ExporterBuildersProviderService; import org.neo4j.gds.procedures.GraphDataScienceProcedures; -import org.neo4j.gds.procedures.GraphDataScienceProceduresBuilder; import org.neo4j.gds.procedures.KernelTransactionAccessor; +import org.neo4j.gds.procedures.ProcedureTransactionAccessor; import org.neo4j.gds.procedures.TaskRegistryFactoryService; import org.neo4j.gds.procedures.TerminationFlagAccessor; -import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationCreator; -import org.neo4j.gds.procedures.algorithms.configuration.ConfigurationParser; -import org.neo4j.gds.procedures.algorithms.stubs.GenericStub; -import org.neo4j.gds.services.DatabaseIdAccessor; -import org.neo4j.gds.services.UserAccessor; -import org.neo4j.gds.services.UserLogServices; +import org.neo4j.gds.procedures.UserAccessor; +import org.neo4j.gds.procedures.UserLogServices; import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.procedure.Context; @@ -62,19 +58,18 @@ public class GraphDataScienceProvider implements ThrowingFunction> algorithmProcessingTemplateDecorator; private final Optional> catalogBusinessFacadeDecorator; - private final CatalogFacadeProvider catalogFacadeProvider; - private final ConfigurationParser configurationParser; + private final CatalogProcedureFacadeFactory catalogProcedureFacadeFactory; private final DeprecatedProceduresMetricService deprecatedProceduresMetricService; private final ExporterBuildersProviderService exporterBuildersProviderService; private final GraphStoreCatalogService graphStoreCatalogService; @@ -88,12 +83,11 @@ public class GraphDataScienceProvider implements ThrowingFunction> algorithmProcessingTemplateDecorator, Optional> catalogBusinessFacadeDecorator, - CatalogFacadeProvider catalogFacadeProvider, - ConfigurationParser configurationParser, + CatalogProcedureFacadeFactory catalogProcedureFacadeFactory, DeprecatedProceduresMetricService deprecatedProceduresMetricService, ExporterBuildersProviderService exporterBuildersProviderService, GraphStoreCatalogService graphStoreCatalogService, @@ -106,12 +100,11 @@ public class GraphDataScienceProvider implements ThrowingFunction