From bafaf7a23a7733d15bef715b90b245e673283ccb Mon Sep 17 00:00:00 2001 From: Dmitriy Tverdiakov Date: Thu, 25 Aug 2022 23:01:38 +0100 Subject: [PATCH] Move bookmark manager configuration to session --- .../org/neo4j/driver/BookmarkManager.java | 4 +- .../org/neo4j/driver/BookmarkManagers.java | 4 +- .../main/java/org/neo4j/driver/Config.java | 27 ----- .../java/org/neo4j/driver/SessionConfig.java | 40 ++++--- .../neo4j/driver/internal/DriverFactory.java | 7 +- .../neo4j/driver/internal/InternalDriver.java | 12 +- .../neo4j/driver/internal/SessionFactory.java | 3 +- .../driver/internal/SessionFactoryImpl.java | 5 +- .../driver/internal/DriverFactoryTest.java | 6 +- .../driver/internal/InternalDriverTest.java | 4 +- .../internal/SessionFactoryImplTest.java | 9 +- .../org/testkit/backend/TestkitState.java | 17 +++ .../requests/BookmarkManagerClose.java | 69 ++++++++++++ .../messages/requests/NewBookmarkManager.java | 104 ++++++++++++++++++ .../backend/messages/requests/NewDriver.java | 35 ------ .../backend/messages/requests/NewSession.java | 7 +- .../requests/TestkitBookmarksConsumer.java | 2 + .../requests/TestkitBookmarksSupplier.java | 6 +- .../messages/requests/TestkitRequest.java | 4 +- .../messages/responses/BookmarkManager.java | 39 +++++++ .../responses/BookmarksConsumerRequest.java | 1 + .../responses/BookmarksSupplierRequest.java | 1 + 22 files changed, 290 insertions(+), 116 deletions(-) create mode 100644 testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/BookmarkManagerClose.java create mode 100644 testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewBookmarkManager.java create mode 100644 testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarkManager.java diff --git a/driver/src/main/java/org/neo4j/driver/BookmarkManager.java b/driver/src/main/java/org/neo4j/driver/BookmarkManager.java index b314c4eb71..b382d7121f 100644 --- a/driver/src/main/java/org/neo4j/driver/BookmarkManager.java +++ b/driver/src/main/java/org/neo4j/driver/BookmarkManager.java @@ -20,6 +20,7 @@ import java.io.Serializable; import java.util.Set; +import org.neo4j.driver.util.Experimental; /** * Keeps track of database bookmarks and is used by the driver to ensure causal consistency between sessions and query executions. @@ -28,8 +29,9 @@ *

* Implementations must avoid calling driver. * - * @see org.neo4j.driver.Config.ConfigBuilder#withBookmarkManager(BookmarkManager) + * @see org.neo4j.driver.SessionConfig.Builder#withBookmarkManager(BookmarkManager) */ +@Experimental public interface BookmarkManager extends Serializable { /** * Updates database bookmarks by deleting the given previous bookmarks and adding the new bookmarks. diff --git a/driver/src/main/java/org/neo4j/driver/BookmarkManagers.java b/driver/src/main/java/org/neo4j/driver/BookmarkManagers.java index eea4881ee1..c0d4eadd2b 100644 --- a/driver/src/main/java/org/neo4j/driver/BookmarkManagers.java +++ b/driver/src/main/java/org/neo4j/driver/BookmarkManagers.java @@ -19,14 +19,16 @@ package org.neo4j.driver; import org.neo4j.driver.internal.Neo4jBookmarkManager; +import org.neo4j.driver.util.Experimental; /** * Setups new instances of {@link BookmarkManager}. */ +@Experimental public final class BookmarkManagers { private BookmarkManagers() {} /** - * Setups a new instance of bookmark manager that can be used in {@link org.neo4j.driver.Config.ConfigBuilder#withBookmarkManager(BookmarkManager)}. + * Setups a new instance of bookmark manager that can be used in {@link org.neo4j.driver.SessionConfig.Builder#withBookmarkManager(BookmarkManager)}. * * @param config the bookmark manager configuration * @return the bookmark manager diff --git a/driver/src/main/java/org/neo4j/driver/Config.java b/driver/src/main/java/org/neo4j/driver/Config.java index e107bc0979..a017a6c38b 100644 --- a/driver/src/main/java/org/neo4j/driver/Config.java +++ b/driver/src/main/java/org/neo4j/driver/Config.java @@ -30,7 +30,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import org.neo4j.driver.internal.SecuritySettings; @@ -99,7 +98,6 @@ public final class Config implements Serializable { private final int eventLoopThreads; private final String userAgent; private final MetricsAdapter metricsAdapter; - private final BookmarkManager bookmarkManager; private Config(ConfigBuilder builder) { this.logging = builder.logging; @@ -121,8 +119,6 @@ private Config(ConfigBuilder builder) { this.eventLoopThreads = builder.eventLoopThreads; this.metricsAdapter = builder.metricsAdapter; - - this.bookmarkManager = builder.bookmarkManager; } /** @@ -256,15 +252,6 @@ public String userAgent() { return userAgent; } - /** - * A {@link BookmarkManager} implementation for the driver to use. - * - * @return bookmark implementation - */ - public Optional bookmarkManager() { - return Optional.ofNullable(bookmarkManager); - } - /** * Used to build new config instances */ @@ -285,7 +272,6 @@ public static final class ConfigBuilder { private MetricsAdapter metricsAdapter = MetricsAdapter.DEV_NULL; private long fetchSize = FetchSizeUtil.DEFAULT_FETCH_SIZE; private int eventLoopThreads = 0; - private BookmarkManager bookmarkManager; private ConfigBuilder() {} @@ -659,19 +645,6 @@ public ConfigBuilder withUserAgent(String userAgent) { return this; } - /** - * Sets a {@link BookmarkManager} implementation for the driver to use. - *

- * By default, bookmark manager is effectively disabled. - * - * @param bookmarkManager bookmark manager implementation. Providing {@code null} effectively disables bookmark manager. - * @return this builder. - */ - public ConfigBuilder withBookmarkManager(BookmarkManager bookmarkManager) { - this.bookmarkManager = bookmarkManager; - return this; - } - /** * Extracts the driver version from the driver jar MANIFEST.MF file. */ diff --git a/driver/src/main/java/org/neo4j/driver/SessionConfig.java b/driver/src/main/java/org/neo4j/driver/SessionConfig.java index 139c6f1195..f43d747fdc 100644 --- a/driver/src/main/java/org/neo4j/driver/SessionConfig.java +++ b/driver/src/main/java/org/neo4j/driver/SessionConfig.java @@ -29,6 +29,7 @@ import org.neo4j.driver.async.AsyncSession; import org.neo4j.driver.reactive.ReactiveSession; import org.neo4j.driver.reactive.RxSession; +import org.neo4j.driver.util.Experimental; import org.reactivestreams.Subscription; /** @@ -45,7 +46,7 @@ public final class SessionConfig implements Serializable { private final String database; private final Long fetchSize; private final String impersonatedUser; - private final boolean ignoreBookmarkManager; + private final BookmarkManager bookmarkManager; private SessionConfig(Builder builder) { this.bookmarks = builder.bookmarks; @@ -53,7 +54,7 @@ private SessionConfig(Builder builder) { this.database = builder.database; this.fetchSize = builder.fetchSize; this.impersonatedUser = builder.impersonatedUser; - this.ignoreBookmarkManager = builder.ignoreBookmarkManager; + this.bookmarkManager = builder.bookmarkManager; } /** @@ -133,12 +134,13 @@ public Optional impersonatedUser() { } /** - * Determines if {@link BookmarkManager} configured at driver level should be ignored. + * A {@link BookmarkManager} implementation for the session to use. * - * @return {@code true} if bookmark manager should be ignored and not otherwise. + * @return bookmark implementation */ - public boolean ignoreBookmarkManager() { - return ignoreBookmarkManager; + @Experimental + public Optional bookmarkManager() { + return Optional.ofNullable(bookmarkManager); } @Override @@ -155,19 +157,22 @@ public boolean equals(Object o) { && Objects.equals(database, that.database) && Objects.equals(fetchSize, that.fetchSize) && Objects.equals(impersonatedUser, that.impersonatedUser) - && Objects.equals(ignoreBookmarkManager, that.ignoreBookmarkManager); + && Objects.equals(bookmarkManager, that.bookmarkManager); } @Override public int hashCode() { - return Objects.hash(bookmarks, defaultAccessMode, database, impersonatedUser, ignoreBookmarkManager); + return Objects.hash(bookmarks, defaultAccessMode, database, impersonatedUser, bookmarkManager); } @Override public String toString() { - return "SessionParameters{" + "bookmarks=" + bookmarks + ", defaultAccessMode=" + defaultAccessMode - + ", database='" + database + '\'' + ", fetchSize=" + fetchSize + "impersonatedUser=" + impersonatedUser - + '}'; + return String.format( + """ + SessionParameters{bookmarks=%s, defaultAccessMode=%s, database='%s', fetchSize=%d, impersonatedUser=%s, \ + bookmarkManager=%s}\ + """, + bookmarks, defaultAccessMode, database, fetchSize, impersonatedUser, bookmarkManager); } /** @@ -179,7 +184,7 @@ public static final class Builder { private AccessMode defaultAccessMode = AccessMode.WRITE; private String database = null; private String impersonatedUser = null; - private boolean ignoreBookmarkManager = false; + private BookmarkManager bookmarkManager; private Builder() {} @@ -306,13 +311,16 @@ public Builder withImpersonatedUser(String impersonatedUser) { } /** - * Ignore {@link BookmarkManager} configured at driver level using {@link org.neo4j.driver.Config.ConfigBuilder#withBookmarkManager(BookmarkManager)}. + * Sets a {@link BookmarkManager} implementation for the session to use. + *

+ * By default, bookmark manager is effectively disabled. * - * @param ignore ignore if {@code true}, use otherwise. + * @param bookmarkManager bookmark manager implementation. Providing {@code null} effectively disables bookmark manager. * @return this builder. */ - public Builder withIgnoredBookmarkManager(boolean ignore) { - this.ignoreBookmarkManager = ignore; + @Experimental + public Builder withBookmarkManager(BookmarkManager bookmarkManager) { + this.bookmarkManager = bookmarkManager; return this; } diff --git a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java index 8ec8e41b63..2e9dc95c1a 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java +++ b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java @@ -260,12 +260,7 @@ protected InternalDriver createRoutingDriver( */ protected InternalDriver createDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, MetricsProvider metricsProvider, Config config) { - return new InternalDriver( - securityPlan, - sessionFactory, - metricsProvider, - config.logging(), - config.bookmarkManager().orElse(null)); + return new InternalDriver(securityPlan, sessionFactory, metricsProvider, config.logging()); } /** diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java b/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java index 27dcdb3b1e..5e047c3219 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java @@ -22,7 +22,6 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.atomic.AtomicBoolean; -import org.neo4j.driver.BookmarkManager; import org.neo4j.driver.Driver; import org.neo4j.driver.Logger; import org.neo4j.driver.Logging; @@ -48,22 +47,18 @@ public class InternalDriver implements Driver { private final SessionFactory sessionFactory; private final Logger log; - private AtomicBoolean closed = new AtomicBoolean(false); + private final AtomicBoolean closed = new AtomicBoolean(false); private final MetricsProvider metricsProvider; - private final BookmarkManager bookmarkManager; - InternalDriver( SecurityPlan securityPlan, SessionFactory sessionFactory, MetricsProvider metricsProvider, - Logging logging, - BookmarkManager bookmarkManager) { + Logging logging) { this.securityPlan = securityPlan; this.sessionFactory = sessionFactory; this.metricsProvider = metricsProvider; this.log = logging.getLog(getClass()); - this.bookmarkManager = bookmarkManager != null ? bookmarkManager : new NoOpBookmarkManager(); } @Override @@ -169,8 +164,7 @@ private static RuntimeException driverCloseException() { public NetworkSession newSession(SessionConfig config) { assertOpen(); - var bookmarkManager = config.ignoreBookmarkManager() ? new NoOpBookmarkManager() : this.bookmarkManager; - NetworkSession session = sessionFactory.newInstance(config, bookmarkManager); + NetworkSession session = sessionFactory.newInstance(config); if (closed.get()) { // session does not immediately acquire connection, it is fine to just throw throw driverCloseException(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/SessionFactory.java b/driver/src/main/java/org/neo4j/driver/internal/SessionFactory.java index 8eef20c633..f2407f0f1a 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/SessionFactory.java +++ b/driver/src/main/java/org/neo4j/driver/internal/SessionFactory.java @@ -19,12 +19,11 @@ package org.neo4j.driver.internal; import java.util.concurrent.CompletionStage; -import org.neo4j.driver.BookmarkManager; import org.neo4j.driver.SessionConfig; import org.neo4j.driver.internal.async.NetworkSession; public interface SessionFactory { - NetworkSession newInstance(SessionConfig sessionConfig, BookmarkManager bookmarkManager); + NetworkSession newInstance(SessionConfig sessionConfig); CompletionStage verifyConnectivity(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java b/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java index 29156dc6c3..aa31e2b5a8 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java @@ -51,8 +51,7 @@ public class SessionFactoryImpl implements SessionFactory { } @Override - public NetworkSession newInstance(SessionConfig sessionConfig, BookmarkManager bookmarkManager) { - Objects.requireNonNull(bookmarkManager, "bookmarkManager may not be null"); + public NetworkSession newInstance(SessionConfig sessionConfig) { return createSession( connectionProvider, retryLogic, @@ -62,7 +61,7 @@ public NetworkSession newInstance(SessionConfig sessionConfig, BookmarkManager b parseFetchSize(sessionConfig), sessionConfig.impersonatedUser().orElse(null), logging, - bookmarkManager); + sessionConfig.bookmarkManager().orElse(new NoOpBookmarkManager())); } private Set toDistinctSet(Iterable bookmarks) { diff --git a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java index 26f89be2e1..9a026b8337 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java @@ -110,9 +110,7 @@ void usesStandardSessionFactoryWhenNothingConfigured(String uri) { createDriver(uri, factory, config); SessionFactory capturedFactory = factory.capturedSessionFactory; - assertThat( - capturedFactory.newInstance(SessionConfig.defaultConfig(), new NoOpBookmarkManager()), - instanceOf(NetworkSession.class)); + assertThat(capturedFactory.newInstance(SessionConfig.defaultConfig()), instanceOf(NetworkSession.class)); } @ParameterizedTest @@ -125,7 +123,7 @@ void usesLeakLoggingSessionFactoryWhenConfigured(String uri) { SessionFactory capturedFactory = factory.capturedSessionFactory; assertThat( - capturedFactory.newInstance(SessionConfig.defaultConfig(), new NoOpBookmarkManager()), + capturedFactory.newInstance(SessionConfig.defaultConfig()), instanceOf(LeakLoggingNetworkSession.class)); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java index 1cbf0bb2bc..44fefb1077 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java @@ -113,7 +113,7 @@ void shouldReturnMetricsIfMetricsEnabled() { private static InternalDriver newDriver(SessionFactory sessionFactory) { return new InternalDriver( - SecurityPlanImpl.insecure(), sessionFactory, DevNullMetricsProvider.INSTANCE, DEV_NULL_LOGGING, null); + SecurityPlanImpl.insecure(), sessionFactory, DevNullMetricsProvider.INSTANCE, DEV_NULL_LOGGING); } private static SessionFactory sessionFactoryMock() { @@ -130,6 +130,6 @@ private static InternalDriver newDriver(boolean isMetricsEnabled) { } MetricsProvider metricsProvider = DriverFactory.getOrCreateMetricsProvider(config, Clock.SYSTEM); - return new InternalDriver(SecurityPlanImpl.insecure(), sessionFactory, metricsProvider, DEV_NULL_LOGGING, null); + return new InternalDriver(SecurityPlanImpl.insecure(), sessionFactory, metricsProvider, DEV_NULL_LOGGING); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/SessionFactoryImplTest.java b/driver/src/test/java/org/neo4j/driver/internal/SessionFactoryImplTest.java index c776e5ef1e..8fe6c36812 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/SessionFactoryImplTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/SessionFactoryImplTest.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test; import org.neo4j.driver.AccessMode; -import org.neo4j.driver.BookmarkManager; import org.neo4j.driver.Config; import org.neo4j.driver.internal.async.LeakLoggingNetworkSession; import org.neo4j.driver.internal.async.NetworkSession; @@ -40,11 +39,11 @@ void createsNetworkSessions() { SessionFactory factory = newSessionFactory(config); NetworkSession readSession = factory.newInstance( - builder().withDefaultAccessMode(AccessMode.READ).build(), mock(BookmarkManager.class)); + builder().withDefaultAccessMode(AccessMode.READ).build()); assertThat(readSession, instanceOf(NetworkSession.class)); NetworkSession writeSession = factory.newInstance( - builder().withDefaultAccessMode(AccessMode.WRITE).build(), mock(BookmarkManager.class)); + builder().withDefaultAccessMode(AccessMode.WRITE).build()); assertThat(writeSession, instanceOf(NetworkSession.class)); } @@ -57,11 +56,11 @@ void createsLeakLoggingNetworkSessions() { SessionFactory factory = newSessionFactory(config); NetworkSession readSession = factory.newInstance( - builder().withDefaultAccessMode(AccessMode.READ).build(), mock(BookmarkManager.class)); + builder().withDefaultAccessMode(AccessMode.READ).build()); assertThat(readSession, instanceOf(LeakLoggingNetworkSession.class)); NetworkSession writeSession = factory.newInstance( - builder().withDefaultAccessMode(AccessMode.WRITE).build(), mock(BookmarkManager.class)); + builder().withDefaultAccessMode(AccessMode.WRITE).build()); assertThat(writeSession, instanceOf(LeakLoggingNetworkSession.class)); } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java index 4ad0e758ee..4dbac4bdc0 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java @@ -40,6 +40,7 @@ import neo4j.org.testkit.backend.holder.TransactionHolder; import neo4j.org.testkit.backend.messages.requests.TestkitCallbackResult; import neo4j.org.testkit.backend.messages.responses.TestkitResponse; +import org.neo4j.driver.BookmarkManager; import org.neo4j.driver.internal.cluster.RoutingTableRegistry; import reactor.core.publisher.Mono; @@ -48,6 +49,7 @@ public class TestkitState { private static final String SESSION_NOT_FOUND_MESSAGE = "Could not find session"; private static final String TRANSACTION_NOT_FOUND_MESSAGE = "Could not find transaction"; private static final String RESULT_NOT_FOUND_MESSAGE = "Could not find result"; + private static final String BOOKMARK_MANAGER_NOT_FOUND_MESSAGE = "Could not find bookmark manager"; private final Map driverIdToDriverHolder = new HashMap<>(); @@ -66,6 +68,7 @@ public class TestkitState { private final Map transactionIdToAsyncTransactionHolder = new HashMap<>(); private final Map transactionIdToRxTransactionHolder = new HashMap<>(); private final Map transactionIdToReactiveTransactionHolder = new HashMap<>(); + private final Map bookmarkManagerIdToBookmarkManager = new HashMap<>(); @Getter private final Map errors = new HashMap<>(); @@ -190,6 +193,20 @@ public Mono getReactiveResultHolder(String id) { return getRx(id, resultIdToReactiveResultHolder, RESULT_NOT_FOUND_MESSAGE); } + public void addBookmarkManager(String id, BookmarkManager bookmarkManager) { + bookmarkManagerIdToBookmarkManager.put(id, bookmarkManager); + } + + public BookmarkManager getBookmarkManager(String id) { + return get(id, bookmarkManagerIdToBookmarkManager, BOOKMARK_MANAGER_NOT_FOUND_MESSAGE); + } + + public void removeBookmarkManager(String id) { + if (bookmarkManagerIdToBookmarkManager.remove(id) == null) { + throw new RuntimeException(BOOKMARK_MANAGER_NOT_FOUND_MESSAGE); + } + } + private String add(T value, Map idToT) { String id = newId(); idToT.put(id, value); diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/BookmarkManagerClose.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/BookmarkManagerClose.java new file mode 100644 index 0000000000..55a8376532 --- /dev/null +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/BookmarkManagerClose.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package neo4j.org.testkit.backend.messages.requests; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import lombok.Getter; +import lombok.Setter; +import neo4j.org.testkit.backend.TestkitState; +import neo4j.org.testkit.backend.messages.responses.BookmarkManager; +import neo4j.org.testkit.backend.messages.responses.TestkitResponse; +import reactor.core.publisher.Mono; + +@Setter +@Getter +public class BookmarkManagerClose implements TestkitRequest { + private BookmarkManagerCloseBody data; + + @Override + public TestkitResponse process(TestkitState testkitState) { + return removeBookmarkManagerAndCreateResponse(testkitState); + } + + @Override + public CompletionStage processAsync(TestkitState testkitState) { + return CompletableFuture.completedFuture(removeBookmarkManagerAndCreateResponse(testkitState)); + } + + @Override + public Mono processRx(TestkitState testkitState) { + return Mono.just(removeBookmarkManagerAndCreateResponse(testkitState)); + } + + @Override + public Mono processReactive(TestkitState testkitState) { + return Mono.just(removeBookmarkManagerAndCreateResponse(testkitState)); + } + + private BookmarkManager removeBookmarkManagerAndCreateResponse(TestkitState testkitState) { + var id = data.getId(); + testkitState.removeBookmarkManager(id); + + return BookmarkManager.builder() + .data(BookmarkManager.BookmarkManagerBody.builder().id(id).build()) + .build(); + } + + @Setter + @Getter + public static class BookmarkManagerCloseBody { + private String id; + } +} diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewBookmarkManager.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewBookmarkManager.java new file mode 100644 index 0000000000..8a4481c4b5 --- /dev/null +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewBookmarkManager.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package neo4j.org.testkit.backend.messages.requests; + +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.stream.Collectors; +import lombok.Getter; +import lombok.Setter; +import neo4j.org.testkit.backend.TestkitState; +import neo4j.org.testkit.backend.messages.responses.BookmarkManager; +import neo4j.org.testkit.backend.messages.responses.TestkitCallback; +import neo4j.org.testkit.backend.messages.responses.TestkitResponse; +import org.neo4j.driver.Bookmark; +import org.neo4j.driver.BookmarkManagers; +import reactor.core.publisher.Mono; + +@Setter +@Getter +public class NewBookmarkManager implements TestkitRequest { + private NewBookmarkManagerBody data; + + @Override + public TestkitResponse process(TestkitState testkitState) { + return createBookmarkManagerAndResponse(testkitState); + } + + @Override + public CompletionStage processAsync(TestkitState testkitState) { + return CompletableFuture.completedFuture(createBookmarkManagerAndResponse(testkitState)); + } + + @Override + public Mono processRx(TestkitState testkitState) { + return Mono.just(createBookmarkManagerAndResponse(testkitState)); + } + + @Override + public Mono processReactive(TestkitState testkitState) { + return Mono.just(createBookmarkManagerAndResponse(testkitState)); + } + + private BookmarkManager createBookmarkManagerAndResponse(TestkitState testkitState) { + var id = testkitState.newId(); + var initialBookmarks = + Optional.ofNullable(data.getInitialBookmarks()).orElseGet(Collections::emptyMap).entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> e.getValue().stream().map(Bookmark::from).collect(Collectors.toSet()))); + var managerConfigBuilder = + org.neo4j.driver.BookmarkManagerConfig.builder().withInitialBookmarks(initialBookmarks); + if (data.isBookmarksSupplierRegistered()) { + managerConfigBuilder.withBookmarksSupplier( + new TestkitBookmarksSupplier(id, testkitState, this::dispatchTestkitCallback)); + } + if (data.isBookmarksConsumerRegistered()) { + managerConfigBuilder.withBookmarksConsumer( + new TestkitBookmarksConsumer(id, testkitState, this::dispatchTestkitCallback)); + } + var manager = BookmarkManagers.defaultManager(managerConfigBuilder.build()); + + testkitState.addBookmarkManager(id, manager); + + return BookmarkManager.builder() + .data(BookmarkManager.BookmarkManagerBody.builder().id(id).build()) + .build(); + } + + private CompletionStage dispatchTestkitCallback( + TestkitState testkitState, TestkitCallback response) { + CompletableFuture future = new CompletableFuture<>(); + testkitState.getCallbackIdToFuture().put(response.getCallbackId(), future); + testkitState.getResponseWriter().accept(response); + return future; + } + + @Setter + @Getter + public static class NewBookmarkManagerBody { + private Map> initialBookmarks; + private boolean bookmarksSupplierRegistered; + private boolean bookmarksConsumerRegistered; + } +} diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java index 7e7befe0a9..7b4bb52afa 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java @@ -24,12 +24,9 @@ import java.net.UnknownHostException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; @@ -47,8 +44,6 @@ import neo4j.org.testkit.backend.messages.responses.TestkitResponse; import org.neo4j.driver.AuthToken; import org.neo4j.driver.AuthTokens; -import org.neo4j.driver.Bookmark; -import org.neo4j.driver.BookmarkManagers; import org.neo4j.driver.Config; import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.DefaultDomainNameResolver; @@ -117,27 +112,6 @@ public TestkitResponse process(TestkitState testkitState) { Optional.ofNullable(data.maxConnectionPoolSize).ifPresent(configBuilder::withMaxConnectionPoolSize); Optional.ofNullable(data.connectionAcquisitionTimeoutMs) .ifPresent(timeout -> configBuilder.withConnectionAcquisitionTimeout(timeout, TimeUnit.MILLISECONDS)); - Optional.ofNullable(data.bookmarkManager).ifPresent(managerConfig -> { - var initialBookmarks = Optional.ofNullable(managerConfig.getInitialBookmarks()) - .orElseGet(Collections::emptyMap) - .entrySet() - .stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - e -> e.getValue().stream().map(Bookmark::from).collect(Collectors.toSet()))); - var managerConfigBuilder = - org.neo4j.driver.BookmarkManagerConfig.builder().withInitialBookmarks(initialBookmarks); - if (managerConfig.isBookmarksSupplierRegistered()) { - managerConfigBuilder = managerConfigBuilder.withBookmarksSupplier( - new TestkitBookmarksSupplier(testkitState, this::dispatchTestkitCallback)); - } - if (managerConfig.isBookmarksConsumerRegistered()) { - managerConfigBuilder = managerConfigBuilder.withBookmarksConsumer( - new TestkitBookmarksConsumer(testkitState, this::dispatchTestkitCallback)); - } - var manager = BookmarkManagers.defaultManager(managerConfigBuilder.build()); - configBuilder.withBookmarkManager(manager); - }); configBuilder.withDriverMetrics(); org.neo4j.driver.Driver driver; Config config = configBuilder.build(); @@ -312,15 +286,6 @@ public static class NewDriverBody { private Long connectionAcquisitionTimeoutMs; private boolean encrypted; private List trustedCertificates; - private BookmarkManagerConfig bookmarkManager; - } - - @Setter - @Getter - public static class BookmarkManagerConfig { - private Map> initialBookmarks; - private boolean bookmarksSupplierRegistered; - private boolean bookmarksConsumerRegistered; } @RequiredArgsConstructor diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewSession.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewSession.java index 82b9edb2b3..a4523ab94f 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewSession.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewSession.java @@ -83,12 +83,15 @@ protected TestkitResponse createSessionStateAndResponse( Optional.ofNullable(data.database).ifPresent(builder::withDatabase); Optional.ofNullable(data.impersonatedUser).ifPresent(builder::withImpersonatedUser); - Optional.ofNullable(data.ignoreBookmarkManager).ifPresent(builder::withIgnoredBookmarkManager); if (data.getFetchSize() != 0) { builder.withFetchSize(data.getFetchSize()); } + Optional.ofNullable(data.bookmarkManagerId) + .map(testkitState::getBookmarkManager) + .ifPresent(builder::withBookmarkManager); + T sessionStateHolder = sessionStateProducer.apply(driverHolder, builder.build()); String newId = addSessionHolder.apply(sessionStateHolder); @@ -125,6 +128,6 @@ public static class NewSessionBody { private String database; private String impersonatedUser; private int fetchSize; - private Boolean ignoreBookmarkManager; + private String bookmarkManagerId; } } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksConsumer.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksConsumer.java index d5e2c41939..ed9e2da25f 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksConsumer.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksConsumer.java @@ -31,6 +31,7 @@ @RequiredArgsConstructor class TestkitBookmarksConsumer implements BiConsumer> { + private final String bookmarkManagerId; private final TestkitState testkitState; private final BiFunction> dispatchFunction; @@ -39,6 +40,7 @@ public void accept(String database, Set bookmarks) { var callbackId = testkitState.newId(); var body = BookmarksConsumerRequest.BookmarksConsumerRequestBody.builder() .id(callbackId) + .bookmarkManagerId(bookmarkManagerId) .database(database) .bookmarks(bookmarks.stream().map(Bookmark::value).collect(Collectors.toUnmodifiableSet())) .build(); diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksSupplier.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksSupplier.java index 9c43d0ddb4..b1a5015985 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksSupplier.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitBookmarksSupplier.java @@ -32,6 +32,7 @@ @RequiredArgsConstructor class TestkitBookmarksSupplier implements BookmarksSupplier { + private final String bookmarkManagerId; private final TestkitState testkitState; private final BiFunction> dispatchFunction; @@ -48,8 +49,9 @@ public Set getAllBookmarks() { private Set getBookmarksFromTestkit(String database) { var callbackId = testkitState.newId(); - var bodyBuilder = - BookmarksSupplierRequest.BookmarksSupplierRequestBody.builder().id(callbackId); + var bodyBuilder = BookmarksSupplierRequest.BookmarksSupplierRequestBody.builder() + .id(callbackId) + .bookmarkManagerId(bookmarkManagerId); if (database != null) { bodyBuilder = bodyBuilder.database(database); } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java index df40cf56d0..73db952865 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java @@ -59,7 +59,9 @@ @JsonSubTypes.Type(ResultSingle.class), @JsonSubTypes.Type(StartSubTest.class), @JsonSubTypes.Type(BookmarksSupplierCompleted.class), - @JsonSubTypes.Type(BookmarksConsumerCompleted.class) + @JsonSubTypes.Type(BookmarksConsumerCompleted.class), + @JsonSubTypes.Type(NewBookmarkManager.class), + @JsonSubTypes.Type(BookmarkManagerClose.class) }) public interface TestkitRequest { TestkitResponse process(TestkitState testkitState); diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarkManager.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarkManager.java new file mode 100644 index 0000000000..e126692a64 --- /dev/null +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarkManager.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package neo4j.org.testkit.backend.messages.responses; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class BookmarkManager implements TestkitResponse { + private final BookmarkManagerBody data; + + @Override + public String testkitName() { + return "BookmarkManager"; + } + + @Getter + @Builder + public static class BookmarkManagerBody { + private final String id; + } +} diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksConsumerRequest.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksConsumerRequest.java index e631376a0e..b480628936 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksConsumerRequest.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksConsumerRequest.java @@ -41,6 +41,7 @@ public String getCallbackId() { @Builder public static class BookmarksConsumerRequestBody { private String id; + private String bookmarkManagerId; private String database; private Set bookmarks; } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksSupplierRequest.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksSupplierRequest.java index e6c9f8c1e2..90e73ce51d 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksSupplierRequest.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/BookmarksSupplierRequest.java @@ -40,6 +40,7 @@ public String getCallbackId() { @Builder public static class BookmarksSupplierRequestBody { private String id; + private String bookmarkManagerId; private String database; } }