From c521c510e46eb52611ea0586cd2b093f36d540d2 Mon Sep 17 00:00:00 2001 From: injectives <11927660+injectives@users.noreply.github.com> Date: Thu, 12 May 2022 17:14:11 +0100 Subject: [PATCH] Update bookmarks API (#1211) * Update bookmarks API `Bookmark` objects should represent singular bookmark values. Multiple bookmarks will be represented as a set of bookmarks (`Set`). The main API updates are highlighted below. `Bookmark` updates: - `value()` - new method - `values()` - deprecated - `isEmpty()` - deprecated `Session` and `AsyncSession` updates: - `Set lastBookmarks()` - new method - `Bookmark lastBookmark()` - deprecated `ReactiveSession` updates: - `Set lastBookmarks()` - new method - `Bookmark lastBookmark()` - deprecated (has not been released) * Update Session Javadoc * Update Session Javadoc --- driver/clirr-ignored-differences.xml | 24 ++++++ .../main/java/org/neo4j/driver/Bookmark.java | 26 +++++- .../main/java/org/neo4j/driver/Session.java | 25 ++++-- .../java/org/neo4j/driver/SessionConfig.java | 35 +++++--- .../org/neo4j/driver/async/AsyncSession.java | 22 +++-- ...okmarkHolder.java => BookmarksHolder.java} | 13 +-- ...older.java => DefaultBookmarksHolder.java} | 22 +++-- .../driver/internal/InternalBookmark.java | 6 ++ .../driver/internal/InternalSession.java | 35 +++++--- ...lder.java => ReadOnlyBookmarksHolder.java} | 14 +-- .../driver/internal/SessionFactoryImpl.java | 46 ++++++++-- .../internal/async/ConnectionContext.java | 3 +- .../async/ImmutableConnectionContext.java | 17 ++-- .../internal/async/InternalAsyncSession.java | 50 ++++++----- .../async/LeakLoggingNetworkSession.java | 6 +- .../driver/internal/async/NetworkSession.java | 41 ++++----- .../internal/async/UnmanagedTransaction.java | 22 ++--- .../cluster/ClusterCompositionProvider.java | 4 +- .../MultiDatabasesRoutingProcedureRunner.java | 9 +- .../driver/internal/cluster/Rediscovery.java | 5 +- .../internal/cluster/RediscoveryImpl.java | 38 ++++----- .../RouteMessageRoutingProcedureRunner.java | 5 +- ...ngProcedureClusterCompositionProvider.java | 5 +- .../cluster/RoutingProcedureRunner.java | 5 +- .../cluster/RoutingTableHandlerImpl.java | 2 +- .../cluster/RoutingTableRegistryImpl.java | 2 +- .../SingleDatabaseRoutingProcedureRunner.java | 17 ++-- .../internal/handlers/PullHandlers.java | 33 ++++--- ...SessionPullResponseCompletionListener.java | 10 +-- .../internal/messaging/BoltProtocol.java | 22 ++--- .../messaging/encode/RouteMessageEncoder.java | 4 +- .../encode/RouteV44MessageEncoder.java | 3 +- .../messaging/request/BeginMessage.java | 9 +- .../messaging/request/RouteMessage.java | 16 ++-- .../request/RunWithMetadataMessage.java | 9 +- .../request/TransactionMetadataBuilder.java | 11 +-- .../internal/messaging/v3/BoltProtocolV3.java | 19 +++-- .../internal/messaging/v4/BoltProtocolV4.java | 8 +- .../messaging/v41/BoltProtocolV41.java | 8 +- .../reactive/AbstractReactiveSession.java | 5 +- .../reactive/InternalReactiveSession.java | 9 ++ .../internal/reactive/InternalRxSession.java | 3 +- .../internal/util/MetadataExtractor.java | 8 +- .../driver/reactive/ReactiveSession.java | 11 ++- .../org/neo4j/driver/reactive/RxSession.java | 9 +- .../java/org/neo4j/driver/ParametersTest.java | 4 +- .../internal/DefaultBookmarkHolderTest.java | 41 ++++----- .../driver/internal/InternalBookmarkTest.java | 12 +-- .../async/InternalAsyncSessionTest.java | 5 +- .../async/LeakLoggingNetworkSessionTest.java | 4 +- .../internal/async/NetworkSessionTest.java | 38 +++++---- .../async/UnmanagedTransactionTest.java | 61 ++++++------- .../AbstractRoutingProcedureRunnerTest.java | 10 +-- ...tiDatabasesRoutingProcedureRunnerTest.java | 20 ++--- .../internal/cluster/RediscoveryTest.java | 48 ++++++----- .../internal/cluster/RediscoveryUtil.java | 7 +- ...outeMessageRoutingProcedureRunnerTest.java | 5 +- ...ocedureClusterCompositionProviderTest.java | 66 +++++++------- .../cluster/RoutingTableHandlerTest.java | 3 +- .../cluster/RoutingTableRegistryImplTest.java | 8 +- ...gleDatabaseRoutingProcedureRunnerTest.java | 20 ++--- .../RoutingTableAndConnectionPoolTest.java | 4 +- ...ionPullResponseCompletionListenerTest.java | 16 ++-- ...ionPullResponseCompletionListenerTest.java | 19 ++--- .../encode/BeginMessageEncoderTest.java | 9 +- .../encode/RouteMessageEncoderTest.java | 7 +- .../RunWithMetadataMessageEncoderTest.java | 9 +- .../TransactionMetadataBuilderTest.java | 19 +++-- .../messaging/v3/BoltProtocolV3Test.java | 80 ++++++++--------- .../messaging/v3/MessageWriterV3Test.java | 14 +-- .../messaging/v4/BoltProtocolV4Test.java | 83 +++++++++--------- .../messaging/v4/MessageWriterV4Test.java | 14 +-- .../messaging/v41/BoltProtocolV41Test.java | 85 ++++++++++--------- .../messaging/v41/MessageWriterV41Test.java | 14 +-- .../messaging/v42/BoltProtocolV42Test.java | 85 ++++++++++--------- .../messaging/v42/MessageWriterV42Test.java | 14 +-- .../messaging/v43/BoltProtocolV43Test.java | 85 ++++++++++--------- .../messaging/v43/MessageWriterV43Test.java | 16 ++-- .../messaging/v44/BoltProtocolV44Test.java | 85 ++++++++++--------- .../messaging/v44/MessageWriterV44Test.java | 16 ++-- .../messaging/v5/BoltProtocolV5Test.java | 83 +++++++++--------- .../messaging/v5/MessageWriterV5Test.java | 16 ++-- .../reactive/InternalReactiveSessionTest.java | 17 +++- .../reactive/InternalRxSessionTest.java | 17 +++- .../neo4j/driver/util/SessionExtension.java | 28 +++++- .../java/org/neo4j/driver/util/TestUtil.java | 22 ++--- .../TestkitRequestResponseMapperHandler.java | 2 + .../backend/messages/TestkitModule.java | 3 - .../requests/SessionLastBookmarks.java | 18 ++-- .../backend/messages/responses/Bookmarks.java | 4 +- .../serializer/TestkitBookmarkSerializer.java | 51 ----------- 91 files changed, 1114 insertions(+), 869 deletions(-) rename driver/src/main/java/org/neo4j/driver/internal/{BookmarkHolder.java => BookmarksHolder.java} (78%) rename driver/src/main/java/org/neo4j/driver/internal/{DefaultBookmarkHolder.java => DefaultBookmarksHolder.java} (66%) rename driver/src/main/java/org/neo4j/driver/internal/{ReadOnlyBookmarkHolder.java => ReadOnlyBookmarksHolder.java} (75%) delete mode 100644 testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/serializer/TestkitBookmarkSerializer.java diff --git a/driver/clirr-ignored-differences.xml b/driver/clirr-ignored-differences.xml index cfa68b6054..53c2bfd808 100644 --- a/driver/clirr-ignored-differences.xml +++ b/driver/clirr-ignored-differences.xml @@ -304,4 +304,28 @@ org.neo4j.driver.Value parameters(java.util.Map) + + org/neo4j/driver/Bookmark + 7012 + org.neo4j.driver.Bookmark from(java.lang.String) + + + + org/neo4j/driver/Bookmark + 7012 + java.lang.String value() + + + + org/neo4j/driver/Session + 7012 + java.util.Set lastBookmarks() + + + + org/neo4j/driver/async/AsyncSession + 7012 + java.util.Set lastBookmarks() + + diff --git a/driver/src/main/java/org/neo4j/driver/Bookmark.java b/driver/src/main/java/org/neo4j/driver/Bookmark.java index 65c91e39a9..6d6a350659 100644 --- a/driver/src/main/java/org/neo4j/driver/Bookmark.java +++ b/driver/src/main/java/org/neo4j/driver/Bookmark.java @@ -18,6 +18,7 @@ */ package org.neo4j.driver; +import java.util.Collections; import java.util.Set; import org.neo4j.driver.internal.InternalBookmark; @@ -35,17 +36,39 @@ */ public interface Bookmark { + /** + * Returns a string that this bookmark instance identifies. + * + * @return a string that this bookmark instance identifies. + */ + String value(); + /** * Returns a read-only set of bookmark strings that this bookmark instance identifies. + * * @return a read-only set of bookmark strings that this bookmark instance identifies. */ + @Deprecated Set values(); /** - * Reconstruct bookmark from \bookmarks string values. + * Reconstruct bookmark from bookmark string value. + * + * @param value value obtained from a previous bookmark. + * @return A bookmark. + */ + static Bookmark from( String value ) + { + return InternalBookmark.parse( Collections.singleton( value ) ); + } + + /** + * Reconstruct bookmark from bookmarks string values. + * * @param values values obtained from a previous bookmark. * @return A bookmark. */ + @Deprecated static Bookmark from( Set values ) { return InternalBookmark.parse( values ); @@ -55,5 +78,6 @@ static Bookmark from( Set values ) * Return true if the bookmark is empty. * @return true if the bookmark is empty. */ + @Deprecated boolean isEmpty(); } diff --git a/driver/src/main/java/org/neo4j/driver/Session.java b/driver/src/main/java/org/neo4j/driver/Session.java index 1d4b7ad248..6b57ccf91f 100644 --- a/driver/src/main/java/org/neo4j/driver/Session.java +++ b/driver/src/main/java/org/neo4j/driver/Session.java @@ -19,6 +19,7 @@ package org.neo4j.driver; import java.util.Map; +import java.util.Set; import java.util.function.Consumer; import org.neo4j.driver.async.AsyncSession; @@ -317,18 +318,28 @@ default void executeWriteWithoutResult( Consumer contextCons Result run(Query query, TransactionConfig config ); /** - * Return the bookmark received following the last completed - * {@linkplain Transaction transaction}. If no bookmark was received - * or if this transaction was rolled back, the bookmark value will - * be null. + * Return the last bookmark of this session. + *

+ * When no new bookmark is received, the initial bookmarks are returned as a composite {@link Bookmark} containing all initial bookmarks. This may happen + * when no work has been done using the session. If no initial bookmarks have been provided, an empty {@link Bookmark} is returned. * - * @return a reference to a previous transaction + * @return the last bookmark. */ + @Deprecated Bookmark lastBookmark(); /** - * Signal that you are done using this session. In the default driver usage, closing and accessing sessions is - * very low cost. + * Return a set of last bookmarks. + *

+ * When no new bookmark is received, the initial bookmarks are returned. This may happen when no work has been done using the session. Multivalued {@link + * Bookmark} instances will be mapped to distinct {@link Bookmark} instances. If no initial bookmarks have been provided, an empty set is returned. + * + * @return the immutable set of last bookmarks. + */ + Set lastBookmarks(); + + /** + * Signal that you are done using this session. In the default driver usage, closing and accessing sessions is very low cost. */ @Override void close(); diff --git a/driver/src/main/java/org/neo4j/driver/SessionConfig.java b/driver/src/main/java/org/neo4j/driver/SessionConfig.java index 4286ad28ef..e8ec48acb2 100644 --- a/driver/src/main/java/org/neo4j/driver/SessionConfig.java +++ b/driver/src/main/java/org/neo4j/driver/SessionConfig.java @@ -26,6 +26,7 @@ import java.util.Optional; import org.neo4j.driver.async.AsyncSession; +import org.neo4j.driver.reactive.ReactiveSession; import org.neo4j.driver.reactive.RxSession; import static java.util.Objects.requireNonNull; @@ -186,14 +187,12 @@ private Builder() /** * Set the initial bookmarks to be used in a session. *

- * First transaction in a session will ensure that server hosting is at least as up-to-date as the - * latest transaction referenced by the supplied bookmarks. - * The bookmarks can be obtained via {@link Session#lastBookmark()}, {@link AsyncSession#lastBookmark()}, - * and/or {@link RxSession#lastBookmark()}. + * First transaction in a session will ensure that server hosting is at least as up-to-date as the latest transaction referenced by the supplied + * bookmarks. The bookmarks can be obtained via {@link Session#lastBookmarks()}, {@link AsyncSession#lastBookmarks()}, and/or {@link + * ReactiveSession#lastBookmarks()}. * - * @param bookmarks a series of initial bookmarks. - * Both {@code null} value and empty array - * are permitted, and indicate that the bookmarks do not exist or are unknown. + * @param bookmarks a series of initial bookmarks. Both {@code null} value and empty array are permitted, and indicate that the bookmarks do not exist + * or are unknown. * @return this builder. */ public Builder withBookmarks( Bookmark... bookmarks ) @@ -210,14 +209,22 @@ public Builder withBookmarks( Bookmark... bookmarks ) } /** - * Set the initial bookmarks to be used in a session. - * First transaction in a session will ensure that server hosting is at least as up-to-date as the - * latest transaction referenced by the supplied bookmarks. - * The bookmarks can be obtained via {@link Session#lastBookmark()}, {@link AsyncSession#lastBookmark()}, - * and/or {@link RxSession#lastBookmark()}. + * Set the initial bookmarks to be used in a session. First transaction in a session will ensure that server hosting is at least as up-to-date as the + * latest transaction referenced by the supplied bookmarks. The bookmarks can be obtained via {@link Session#lastBookmarks()}, {@link + * AsyncSession#lastBookmarks()}, and/or {@link ReactiveSession#lastBookmarks()}. + *

+ * Multiple immutable sets of bookmarks may be joined in the following way: + *

+         * {@code
+         * Set bookmarks = new HashSet<>();
+         * bookmarks.addAll( session1.lastBookmarks() );
+         * bookmarks.addAll( session2.lastBookmarks() );
+         * bookmarks.addAll( session3.lastBookmarks() );
+         * }
+         * 
* - * @param bookmarks initial references to some previous transactions. Both {@code null} value and empty iterable - * are permitted, and indicate that the bookmarks do not exist or are unknown. + * @param bookmarks initial references to some previous transactions. Both {@code null} value and empty iterable are permitted, and indicate that the + * bookmarks do not exist or are unknown. * @return this builder */ public Builder withBookmarks( Iterable bookmarks ) diff --git a/driver/src/main/java/org/neo4j/driver/async/AsyncSession.java b/driver/src/main/java/org/neo4j/driver/async/AsyncSession.java index 2b40688005..4d13fd9962 100644 --- a/driver/src/main/java/org/neo4j/driver/async/AsyncSession.java +++ b/driver/src/main/java/org/neo4j/driver/async/AsyncSession.java @@ -19,6 +19,7 @@ package org.neo4j.driver.async; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.Executor; @@ -382,15 +383,26 @@ default CompletionStage executeWriteAsync( AsyncTransactionCallback runAsync( Query query, TransactionConfig config ); /** - * Return the bookmark received following the last completed - * {@linkplain Transaction transaction}. If no bookmark was received - * or if this transaction was rolled back, the bookmark value will - * be null. + * Return the last bookmark of this session. + *

+ * When no new bookmark is received, the initial bookmarks are returned as a composite {@link Bookmark} containing all initial bookmarks. This may happen + * when no work has been done using the session. If no initial bookmarks have been provided, an empty {@link Bookmark} is returned. * - * @return a reference to a previous transaction + * @return the last bookmark. */ + @Deprecated Bookmark lastBookmark(); + /** + * Return a set of last bookmarks. + *

+ * When no new bookmark is received, the initial bookmarks are returned. This may happen when no work has been done using the session. Multivalued {@link + * Bookmark} instances will be mapped to distinct {@link Bookmark} instances. If no initial bookmarks have been provided, an empty set is returned. + * + * @return the immutable set of last bookmarks. + */ + Set lastBookmarks(); + /** * Signal that you are done using this session. In the default driver usage, closing and accessing sessions is * very low cost. diff --git a/driver/src/main/java/org/neo4j/driver/internal/BookmarkHolder.java b/driver/src/main/java/org/neo4j/driver/internal/BookmarksHolder.java similarity index 78% rename from driver/src/main/java/org/neo4j/driver/internal/BookmarkHolder.java rename to driver/src/main/java/org/neo4j/driver/internal/BookmarksHolder.java index d048d0948f..bdeae1e8f4 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/BookmarkHolder.java +++ b/driver/src/main/java/org/neo4j/driver/internal/BookmarksHolder.java @@ -18,20 +18,23 @@ */ package org.neo4j.driver.internal; +import java.util.Collections; +import java.util.Set; + import org.neo4j.driver.Bookmark; -public interface BookmarkHolder +public interface BookmarksHolder { - Bookmark getBookmark(); + Set getBookmarks(); void setBookmark( Bookmark bookmark ); - BookmarkHolder NO_OP = new BookmarkHolder() + BookmarksHolder NO_OP = new BookmarksHolder() { @Override - public Bookmark getBookmark() + public Set getBookmarks() { - return InternalBookmark.empty(); + return Collections.emptySet(); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/DefaultBookmarkHolder.java b/driver/src/main/java/org/neo4j/driver/internal/DefaultBookmarksHolder.java similarity index 66% rename from driver/src/main/java/org/neo4j/driver/internal/DefaultBookmarkHolder.java rename to driver/src/main/java/org/neo4j/driver/internal/DefaultBookmarksHolder.java index 61f333bc32..2e294d8341 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/DefaultBookmarkHolder.java +++ b/driver/src/main/java/org/neo4j/driver/internal/DefaultBookmarksHolder.java @@ -18,29 +18,33 @@ */ package org.neo4j.driver.internal; +import java.util.Collections; +import java.util.Set; + import org.neo4j.driver.Bookmark; /** * @since 2.0 */ -public class DefaultBookmarkHolder implements BookmarkHolder +public class DefaultBookmarksHolder implements BookmarksHolder { - private volatile Bookmark bookmark; + private volatile Set bookmarks; - public DefaultBookmarkHolder() + // for testing only + public DefaultBookmarksHolder() { - this( InternalBookmark.empty() ); + this( Collections.emptySet() ); } - public DefaultBookmarkHolder( Bookmark bookmark ) + public DefaultBookmarksHolder( Set bookmarks ) { - this.bookmark = bookmark; + this.bookmarks = bookmarks; } @Override - public Bookmark getBookmark() + public Set getBookmarks() { - return bookmark; + return bookmarks; } @Override @@ -48,7 +52,7 @@ public void setBookmark( Bookmark bookmark ) { if ( bookmark != null && !bookmark.isEmpty() ) { - this.bookmark = bookmark; + bookmarks = Collections.singleton( bookmark ); } } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalBookmark.java b/driver/src/main/java/org/neo4j/driver/internal/InternalBookmark.java index c4ac5cbab7..cc920e0bec 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalBookmark.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalBookmark.java @@ -117,6 +117,12 @@ public boolean isEmpty() return values.isEmpty(); } + @Override + public String value() + { + return values.isEmpty() ? null : values.iterator().next(); + } + @Override public Set values() { diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java b/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java index 33008f71c4..c6378e50a8 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java @@ -19,6 +19,7 @@ package org.neo4j.driver.internal; import java.util.Map; +import java.util.Set; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; @@ -140,7 +141,13 @@ public T executeWrite( TransactionCallback callback, TransactionConfig co @Override public Bookmark lastBookmark() { - return session.lastBookmark(); + return InternalBookmark.from( session.lastBookmarks() ); + } + + @Override + public Set lastBookmarks() + { + return session.lastBookmarks(); } private T transaction( AccessMode mode, TransactionWork work, TransactionConfig config ) @@ -149,19 +156,21 @@ private T transaction( AccessMode mode, TransactionWork work, Transaction // caller thread will also be the one who sleeps between retries; // it is unsafe to execute retries in the event loop threads because this can cause a deadlock // event loop thread will bock and wait for itself to read some data - return session.retryLogic().retry( () -> { - try ( Transaction tx = beginTransaction( mode, config ) ) - { - - T result = work.execute( tx ); - if ( tx.isOpen() ) + return session.retryLogic().retry( + () -> { - // commit tx if a user has not explicitly committed or rolled back the transaction - tx.commit(); - } - return result; - } - } ); + try ( Transaction tx = beginTransaction( mode, config ) ) + { + + T result = work.execute( tx ); + if ( tx.isOpen() ) + { + // commit tx if a user has not explicitly committed or rolled back the transaction + tx.commit(); + } + return result; + } + } ); } private Transaction beginTransaction( AccessMode mode, TransactionConfig config ) diff --git a/driver/src/main/java/org/neo4j/driver/internal/ReadOnlyBookmarkHolder.java b/driver/src/main/java/org/neo4j/driver/internal/ReadOnlyBookmarksHolder.java similarity index 75% rename from driver/src/main/java/org/neo4j/driver/internal/ReadOnlyBookmarkHolder.java rename to driver/src/main/java/org/neo4j/driver/internal/ReadOnlyBookmarksHolder.java index c828f07aee..39cb18d51b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/ReadOnlyBookmarkHolder.java +++ b/driver/src/main/java/org/neo4j/driver/internal/ReadOnlyBookmarksHolder.java @@ -18,24 +18,26 @@ */ package org.neo4j.driver.internal; +import java.util.Set; + import org.neo4j.driver.Bookmark; /** * @since 2.0 */ -public class ReadOnlyBookmarkHolder implements BookmarkHolder +public class ReadOnlyBookmarksHolder implements BookmarksHolder { - private final Bookmark bookmark; + private final Set bookmarks; - public ReadOnlyBookmarkHolder( Bookmark bookmark ) + public ReadOnlyBookmarksHolder( Set bookmarks ) { - this.bookmark = bookmark; + this.bookmarks = bookmarks; } @Override - public Bookmark getBookmark() + public Set getBookmarks() { - return bookmark; + return bookmarks; } @Override 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 8a9e85634e..1f4b866692 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java @@ -18,10 +18,14 @@ */ package org.neo4j.driver.internal; +import java.util.Collections; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; import java.util.concurrent.CompletionStage; import org.neo4j.driver.AccessMode; +import org.neo4j.driver.Bookmark; import org.neo4j.driver.Config; import org.neo4j.driver.Logging; import org.neo4j.driver.SessionConfig; @@ -50,12 +54,40 @@ public class SessionFactoryImpl implements SessionFactory @Override public NetworkSession newInstance( SessionConfig sessionConfig ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( InternalBookmark.from( sessionConfig.bookmarks() ) ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( toDistinctSet( sessionConfig.bookmarks() ) ); return createSession( connectionProvider, retryLogic, parseDatabaseName( sessionConfig ), - sessionConfig.defaultAccessMode(), bookmarkHolder, parseFetchSize( sessionConfig ), + sessionConfig.defaultAccessMode(), bookmarksHolder, parseFetchSize( sessionConfig ), sessionConfig.impersonatedUser().orElse( null ), logging ); } + private Set toDistinctSet( Iterable bookmarks ) + { + Set set = new HashSet<>(); + if ( bookmarks != null ) + { + for ( Bookmark bookmark : bookmarks ) + { + if ( bookmark != null ) + { + Set values = bookmark.values(); + int size = values.size(); + if ( size == 1 ) + { + set.add( bookmark ); + } + else if ( size > 1 ) + { + for ( String value : values ) + { + set.add( Bookmark.from( value ) ); + } + } + } + } + } + return Collections.unmodifiableSet( set ); + } + private long parseFetchSize( SessionConfig sessionConfig ) { return sessionConfig.fetchSize().orElse( defaultFetchSize ); @@ -64,8 +96,8 @@ private long parseFetchSize( SessionConfig sessionConfig ) private DatabaseName parseDatabaseName( SessionConfig sessionConfig ) { return sessionConfig.database() - .flatMap( name -> Optional.of( DatabaseNameUtil.database( name ) ) ) - .orElse( DatabaseNameUtil.defaultDatabase() ); + .flatMap( name -> Optional.of( DatabaseNameUtil.database( name ) ) ) + .orElse( DatabaseNameUtil.defaultDatabase() ); } @Override @@ -99,10 +131,10 @@ public ConnectionProvider getConnectionProvider() } private NetworkSession createSession( ConnectionProvider connectionProvider, RetryLogic retryLogic, DatabaseName databaseName, AccessMode mode, - BookmarkHolder bookmarkHolder, long fetchSize, String impersonatedUser, Logging logging ) + BookmarksHolder bookmarksHolder, long fetchSize, String impersonatedUser, Logging logging ) { return leakedSessionsLoggingEnabled - ? new LeakLoggingNetworkSession( connectionProvider, retryLogic, databaseName, mode, bookmarkHolder, impersonatedUser, fetchSize, logging ) - : new NetworkSession( connectionProvider, retryLogic, databaseName, mode, bookmarkHolder, impersonatedUser, fetchSize, logging ); + ? new LeakLoggingNetworkSession( connectionProvider, retryLogic, databaseName, mode, bookmarksHolder, impersonatedUser, fetchSize, logging ) + : new NetworkSession( connectionProvider, retryLogic, databaseName, mode, bookmarksHolder, impersonatedUser, fetchSize, logging ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java b/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java index 31efe28b90..f9e8d5a4a8 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java @@ -18,6 +18,7 @@ */ package org.neo4j.driver.internal.async; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; @@ -37,7 +38,7 @@ public interface ConnectionContext AccessMode mode(); - Bookmark rediscoveryBookmark(); + Set rediscoveryBookmarks(); String impersonatedUser(); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/ImmutableConnectionContext.java b/driver/src/main/java/org/neo4j/driver/internal/async/ImmutableConnectionContext.java index ccaa86c389..c92f7eb546 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/ImmutableConnectionContext.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/ImmutableConnectionContext.java @@ -18,6 +18,8 @@ */ package org.neo4j.driver.internal.async; +import java.util.Collections; +import java.util.Set; import java.util.concurrent.CompletableFuture; import org.neo4j.driver.AccessMode; @@ -27,24 +29,23 @@ import static org.neo4j.driver.internal.DatabaseNameUtil.defaultDatabase; import static org.neo4j.driver.internal.DatabaseNameUtil.systemDatabase; -import static org.neo4j.driver.internal.InternalBookmark.empty; /** * A {@link Connection} shall fulfil this {@link ImmutableConnectionContext} when acquired from a connection provider. */ public class ImmutableConnectionContext implements ConnectionContext { - private static final ConnectionContext SINGLE_DB_CONTEXT = new ImmutableConnectionContext( defaultDatabase(), empty(), AccessMode.READ ); - private static final ConnectionContext MULTI_DB_CONTEXT = new ImmutableConnectionContext( systemDatabase(), empty(), AccessMode.READ ); + private static final ConnectionContext SINGLE_DB_CONTEXT = new ImmutableConnectionContext( defaultDatabase(), Collections.emptySet(), AccessMode.READ ); + private static final ConnectionContext MULTI_DB_CONTEXT = new ImmutableConnectionContext( systemDatabase(), Collections.emptySet(), AccessMode.READ ); private final CompletableFuture databaseNameFuture; private final AccessMode mode; - private final Bookmark rediscoveryBookmark; + private final Set rediscoveryBookmarks; - public ImmutableConnectionContext( DatabaseName databaseName, Bookmark bookmark, AccessMode mode ) + public ImmutableConnectionContext( DatabaseName databaseName, Set bookmarks, AccessMode mode ) { this.databaseNameFuture = CompletableFuture.completedFuture( databaseName ); - this.rediscoveryBookmark = bookmark; + this.rediscoveryBookmarks = bookmarks; this.mode = mode; } @@ -61,9 +62,9 @@ public AccessMode mode() } @Override - public Bookmark rediscoveryBookmark() + public Set rediscoveryBookmarks() { - return rediscoveryBookmark; + return rediscoveryBookmarks; } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java b/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java index 23c12fded6..a32f20138e 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java @@ -18,7 +18,9 @@ */ package org.neo4j.driver.internal.async; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -31,6 +33,7 @@ import org.neo4j.driver.async.AsyncTransactionCallback; import org.neo4j.driver.async.AsyncTransactionWork; import org.neo4j.driver.async.ResultCursor; +import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.util.Futures; import static java.util.Collections.emptyMap; @@ -127,29 +130,38 @@ public CompletionStage executeWriteAsync( AsyncTransactionCallback CompletionStage transactionAsync( AccessMode mode, AsyncTransactionWork> work, TransactionConfig config ) + @Override + public Set lastBookmarks() { - return session.retryLogic().retryAsync( () -> { - CompletableFuture resultFuture = new CompletableFuture<>(); - CompletionStage txFuture = session.beginTransactionAsync( mode, config ); - - txFuture.whenComplete( ( tx, completionError ) -> { - Throwable error = Futures.completionExceptionCause( completionError ); - if ( error != null ) - { - resultFuture.completeExceptionally( error ); - } - else - { - executeWork( resultFuture, tx, work ); - } - } ); + return new HashSet<>( session.lastBookmarks() ); + } - return resultFuture; - } ); + private CompletionStage transactionAsync( AccessMode mode, AsyncTransactionWork> work, TransactionConfig config ) + { + return session.retryLogic().retryAsync( () -> + { + CompletableFuture resultFuture = new CompletableFuture<>(); + CompletionStage txFuture = session.beginTransactionAsync( mode, config ); + + txFuture.whenComplete( + ( tx, completionError ) -> + { + Throwable error = Futures.completionExceptionCause( completionError ); + if ( error != null ) + { + resultFuture.completeExceptionally( error ); + } + else + { + executeWork( resultFuture, tx, work ); + } + } ); + + return resultFuture; + } ); } private void executeWork(CompletableFuture resultFuture, UnmanagedTransaction tx, AsyncTransactionWork> work ) diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java b/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java index 952c17e243..0b23b5f554 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java @@ -20,7 +20,7 @@ import org.neo4j.driver.AccessMode; import org.neo4j.driver.Logging; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.spi.ConnectionProvider; @@ -33,9 +33,9 @@ public class LeakLoggingNetworkSession extends NetworkSession private final String stackTrace; public LeakLoggingNetworkSession( ConnectionProvider connectionProvider, RetryLogic retryLogic, DatabaseName databaseName, AccessMode mode, - BookmarkHolder bookmarkHolder, String impersonatedUser, long fetchSize, Logging logging ) + BookmarksHolder bookmarksHolder, String impersonatedUser, long fetchSize, Logging logging ) { - super( connectionProvider, retryLogic, databaseName, mode, bookmarkHolder, impersonatedUser, fetchSize, logging ); + super( connectionProvider, retryLogic, databaseName, mode, bookmarksHolder, impersonatedUser, fetchSize, logging ); this.stackTrace = captureStackTrace(); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java b/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java index 197e774a13..71f1ef094a 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java @@ -18,6 +18,7 @@ */ package org.neo4j.driver.internal.async; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; @@ -32,7 +33,7 @@ import org.neo4j.driver.async.ResultCursor; import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.exceptions.TransactionNestingException; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; import org.neo4j.driver.internal.FailableCursor; import org.neo4j.driver.internal.ImpersonationUtil; @@ -56,7 +57,7 @@ public class NetworkSession private final RetryLogic retryLogic; protected final Logger log; - private final BookmarkHolder bookmarkHolder; + private final BookmarksHolder bookmarksHolder; private final long fetchSize; private volatile CompletionStage transactionStage = completedWithNull(); private volatile CompletionStage connectionStage = completedWithNull(); @@ -65,17 +66,17 @@ public class NetworkSession private final AtomicBoolean open = new AtomicBoolean( true ); public NetworkSession( ConnectionProvider connectionProvider, RetryLogic retryLogic, DatabaseName databaseName, AccessMode mode, - BookmarkHolder bookmarkHolder, String impersonatedUser, long fetchSize, Logging logging ) + BookmarksHolder bookmarksHolder, String impersonatedUser, long fetchSize, Logging logging ) { this.connectionProvider = connectionProvider; this.mode = mode; this.retryLogic = retryLogic; this.log = new PrefixedLogger( "[" + hashCode() + "]", logging.getLog( getClass() ) ); - this.bookmarkHolder = bookmarkHolder; + this.bookmarksHolder = bookmarksHolder; CompletableFuture databaseNameFuture = databaseName.databaseName() .map( ignored -> CompletableFuture.completedFuture( databaseName ) ) .orElse( new CompletableFuture<>() ); - this.connectionContext = new NetworkSessionConnectionContext( databaseNameFuture, bookmarkHolder.getBookmark(), impersonatedUser ); + this.connectionContext = new NetworkSessionConnectionContext( databaseNameFuture, bookmarksHolder.getBookmarks(), impersonatedUser ); this.fetchSize = fetchSize; } @@ -111,10 +112,10 @@ public CompletionStage beginTransactionAsync( AccessMode m .thenCompose( ignore -> acquireConnection( mode ) ) .thenApply( connection -> ImpersonationUtil.ensureImpersonationSupport( connection, connection.impersonatedUser() ) ) .thenCompose( connection -> - { - UnmanagedTransaction tx = new UnmanagedTransaction( connection, bookmarkHolder, fetchSize ); - return tx.beginAsync( bookmarkHolder.getBookmark(), config ); - } ); + { + UnmanagedTransaction tx = new UnmanagedTransaction( connection, bookmarksHolder, fetchSize ); + return tx.beginAsync( bookmarksHolder.getBookmarks(), config ); + } ); // update the reference to the only known transaction CompletionStage currentTransactionStage = transactionStage; @@ -140,9 +141,9 @@ public RetryLogic retryLogic() return retryLogic; } - public Bookmark lastBookmark() + public Set lastBookmarks() { - return bookmarkHolder.getBookmark(); + return bookmarksHolder.getBookmarks(); } public CompletionStage releaseConnectionAsync() @@ -219,7 +220,7 @@ private CompletionStage buildResultCursorFactory( Query que { ResultCursorFactory factory = connection .protocol() - .runInAutoCommitTransaction( connection, query, bookmarkHolder, config, fetchSize ); + .runInAutoCommitTransaction( connection, query, bookmarksHolder, config, fetchSize ); return completedFuture( factory ); } catch ( Throwable e ) @@ -338,16 +339,16 @@ private static class NetworkSessionConnectionContext implements ConnectionContex private final CompletableFuture databaseNameFuture; private AccessMode mode; - // This bookmark is only used for rediscovery. - // It has to be the initial bookmark given at the creation of the session. - // As only that bookmark could carry extra system bookmarks - private final Bookmark rediscoveryBookmark; + // These bookmarks are only used for rediscovery. + // They have to be the initial bookmarks given at the creation of the session. + // As only those bookmarks could carry extra system bookmarks + private final Set rediscoveryBookmarks; private final String impersonatedUser; - private NetworkSessionConnectionContext( CompletableFuture databaseNameFuture, Bookmark bookmark, String impersonatedUser ) + private NetworkSessionConnectionContext( CompletableFuture databaseNameFuture, Set bookmarks, String impersonatedUser ) { this.databaseNameFuture = databaseNameFuture; - this.rediscoveryBookmark = bookmark; + this.rediscoveryBookmarks = bookmarks; this.impersonatedUser = impersonatedUser; } @@ -370,9 +371,9 @@ public AccessMode mode() } @Override - public Bookmark rediscoveryBookmark() + public Set rediscoveryBookmarks() { - return rediscoveryBookmark; + return rediscoveryBookmarks; } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java b/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java index fbd7a985c7..a05cc884c1 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.EnumSet; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; @@ -30,13 +31,12 @@ import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; -import org.neo4j.driver.Session; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.async.ResultCursor; import org.neo4j.driver.exceptions.AuthorizationExpiredException; import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.exceptions.ConnectionReadTimeoutException; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.cursor.AsyncResultCursor; import org.neo4j.driver.internal.cursor.RxResultCursor; import org.neo4j.driver.internal.messaging.BoltProtocol; @@ -59,7 +59,7 @@ private enum State ACTIVE, /** - * This transaction has been terminated either because of explicit {@link Session#reset()} or because of a fatal connection error. + * This transaction has been terminated either because of a fatal connection error. */ TERMINATED, @@ -84,7 +84,7 @@ private enum State private final Connection connection; private final BoltProtocol protocol; - private final BookmarkHolder bookmarkHolder; + private final BookmarksHolder bookmarksHolder; private final ResultCursorsHolder resultCursors; private final long fetchSize; private final Lock lock = new ReentrantLock(); @@ -93,23 +93,23 @@ private enum State private CompletableFuture rollbackFuture; private Throwable causeOfTermination; - public UnmanagedTransaction( Connection connection, BookmarkHolder bookmarkHolder, long fetchSize ) + public UnmanagedTransaction( Connection connection, BookmarksHolder bookmarksHolder, long fetchSize ) { - this( connection, bookmarkHolder, fetchSize, new ResultCursorsHolder() ); + this( connection, bookmarksHolder, fetchSize, new ResultCursorsHolder() ); } - protected UnmanagedTransaction( Connection connection, BookmarkHolder bookmarkHolder, long fetchSize, ResultCursorsHolder resultCursors ) + protected UnmanagedTransaction( Connection connection, BookmarksHolder bookmarksHolder, long fetchSize, ResultCursorsHolder resultCursors ) { this.connection = connection; this.protocol = connection.protocol(); - this.bookmarkHolder = bookmarkHolder; + this.bookmarksHolder = bookmarksHolder; this.resultCursors = resultCursors; this.fetchSize = fetchSize; } - public CompletionStage beginAsync( Bookmark initialBookmark, TransactionConfig config ) + public CompletionStage beginAsync( Set initialBookmarks, TransactionConfig config ) { - return protocol.beginTransaction( connection, initialBookmark, config ) + return protocol.beginTransaction( connection, initialBookmarks, config ) .handle( ( ignore, beginError ) -> { if ( beginError != null ) @@ -240,7 +240,7 @@ private CompletionStage doCommitAsync( Throwable cursorFailure ) cursorFailure != causeOfTermination ? causeOfTermination : null ) : null ); - return exception != null ? failedFuture( exception ) : protocol.commitTransaction( connection ).thenAccept( bookmarkHolder::setBookmark ); + return exception != null ? failedFuture( exception ) : protocol.commitTransaction( connection ).thenAccept( bookmarksHolder::setBookmark ); } private CompletionStage doRollbackAsync() diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/ClusterCompositionProvider.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/ClusterCompositionProvider.java index e71f800cd5..ef51c38115 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/ClusterCompositionProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/ClusterCompositionProvider.java @@ -18,6 +18,7 @@ */ package org.neo4j.driver.internal.cluster; +import java.util.Set; import java.util.concurrent.CompletionStage; import org.neo4j.driver.Bookmark; @@ -26,5 +27,6 @@ public interface ClusterCompositionProvider { - CompletionStage getClusterComposition( Connection connection, DatabaseName databaseName, Bookmark bookmark, String impersonatedUser ); + CompletionStage getClusterComposition( Connection connection, DatabaseName databaseName, Set bookmarks, + String impersonatedUser ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunner.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunner.java index 71f09cfc08..03d1884dbf 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunner.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunner.java @@ -19,14 +19,15 @@ package org.neo4j.driver.internal.cluster; import java.util.HashMap; +import java.util.Set; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.ReadOnlyBookmarkHolder; +import org.neo4j.driver.internal.ReadOnlyBookmarksHolder; import org.neo4j.driver.internal.async.connection.DirectConnection; import org.neo4j.driver.internal.messaging.BoltProtocolVersion; import org.neo4j.driver.internal.spi.Connection; @@ -50,9 +51,9 @@ public MultiDatabasesRoutingProcedureRunner( RoutingContext context ) } @Override - BookmarkHolder bookmarkHolder( Bookmark bookmark ) + BookmarksHolder bookmarksHolder( Set bookmarks ) { - return new ReadOnlyBookmarkHolder( bookmark ); + return new ReadOnlyBookmarksHolder( bookmarks ); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java index abd5ddc784..692147cb0d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java @@ -20,6 +20,7 @@ import java.net.UnknownHostException; import java.util.List; +import java.util.Set; import java.util.concurrent.CompletionStage; import org.neo4j.driver.Bookmark; @@ -38,11 +39,11 @@ public interface Rediscovery * * @param routingTable the routing table for cluster composition lookup * @param connectionPool the connection pool for connection acquisition - * @param bookmark the bookmark that is presented to the server + * @param bookmarks the bookmarks that are presented to the server * @param impersonatedUser the impersonated user for cluster composition lookup, should be {@code null} for non-impersonated requests * @return cluster composition lookup result */ - CompletionStage lookupClusterComposition( RoutingTable routingTable, ConnectionPool connectionPool, Bookmark bookmark, + CompletionStage lookupClusterComposition( RoutingTable routingTable, ConnectionPool connectionPool, Set bookmarks, String impersonatedUser ); List resolve() throws UnknownHostException; diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java index 692afa3063..10251c7905 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java @@ -89,19 +89,19 @@ public RediscoveryImpl( BoltServerAddress initialRouter, ClusterCompositionProvi */ @Override public CompletionStage lookupClusterComposition( RoutingTable routingTable, ConnectionPool connectionPool, - Bookmark bookmark, String impersonatedUser ) + Set bookmarks, String impersonatedUser ) { CompletableFuture result = new CompletableFuture<>(); // if we failed discovery, we will chain all errors into this one. ServiceUnavailableException baseError = new ServiceUnavailableException( String.format( NO_ROUTERS_AVAILABLE, routingTable.database().description() ) ); - lookupClusterComposition( routingTable, connectionPool, result, bookmark, impersonatedUser, baseError ); + lookupClusterComposition( routingTable, connectionPool, result, bookmarks, impersonatedUser, baseError ); return result; } private void lookupClusterComposition( RoutingTable routingTable, ConnectionPool pool, CompletableFuture result, - Bookmark bookmark, String impersonatedUser, Throwable baseError ) + Set bookmarks, String impersonatedUser, Throwable baseError ) { - lookup( routingTable, pool, bookmark, impersonatedUser, baseError ) + lookup( routingTable, pool, bookmarks, impersonatedUser, baseError ) .whenComplete( ( compositionLookupResult, completionError ) -> { @@ -121,29 +121,29 @@ else if ( compositionLookupResult != null ) } ); } - private CompletionStage lookup( RoutingTable routingTable, ConnectionPool connectionPool, Bookmark bookmark, + private CompletionStage lookup( RoutingTable routingTable, ConnectionPool connectionPool, Set bookmarks, String impersonatedUser, Throwable baseError ) { CompletionStage compositionStage; if ( routingTable.preferInitialRouter() ) { - compositionStage = lookupOnInitialRouterThenOnKnownRouters( routingTable, connectionPool, bookmark, impersonatedUser, baseError ); + compositionStage = lookupOnInitialRouterThenOnKnownRouters( routingTable, connectionPool, bookmarks, impersonatedUser, baseError ); } else { - compositionStage = lookupOnKnownRoutersThenOnInitialRouter( routingTable, connectionPool, bookmark, impersonatedUser, baseError ); + compositionStage = lookupOnKnownRoutersThenOnInitialRouter( routingTable, connectionPool, bookmarks, impersonatedUser, baseError ); } return compositionStage; } private CompletionStage lookupOnKnownRoutersThenOnInitialRouter( RoutingTable routingTable, ConnectionPool connectionPool, - Bookmark bookmark, String impersonatedUser, + Set bookmarks, String impersonatedUser, Throwable baseError ) { Set seenServers = new HashSet<>(); - return lookupOnKnownRouters( routingTable, connectionPool, seenServers, bookmark, impersonatedUser, baseError ) + return lookupOnKnownRouters( routingTable, connectionPool, seenServers, bookmarks, impersonatedUser, baseError ) .thenCompose( compositionLookupResult -> { @@ -152,16 +152,16 @@ private CompletionStage lookupOnKnownRoutersThen return completedFuture( compositionLookupResult ); } - return lookupOnInitialRouter( routingTable, connectionPool, seenServers, bookmark, impersonatedUser, baseError ); + return lookupOnInitialRouter( routingTable, connectionPool, seenServers, bookmarks, impersonatedUser, baseError ); } ); } private CompletionStage lookupOnInitialRouterThenOnKnownRouters( RoutingTable routingTable, ConnectionPool connectionPool, - Bookmark bookmark, String impersonatedUser, + Set bookmarks, String impersonatedUser, Throwable baseError ) { Set seenServers = emptySet(); - return lookupOnInitialRouter( routingTable, connectionPool, seenServers, bookmark, impersonatedUser, baseError ) + return lookupOnInitialRouter( routingTable, connectionPool, seenServers, bookmarks, impersonatedUser, baseError ) .thenCompose( compositionLookupResult -> { @@ -170,12 +170,12 @@ private CompletionStage lookupOnInitialRouterThe return completedFuture( compositionLookupResult ); } - return lookupOnKnownRouters( routingTable, connectionPool, new HashSet<>(), bookmark, impersonatedUser, baseError ); + return lookupOnKnownRouters( routingTable, connectionPool, new HashSet<>(), bookmarks, impersonatedUser, baseError ); } ); } private CompletionStage lookupOnKnownRouters( RoutingTable routingTable, ConnectionPool connectionPool, - Set seenServers, Bookmark bookmark, + Set seenServers, Set bookmarks, String impersonatedUser, Throwable baseError ) { CompletableFuture result = completedWithNull(); @@ -191,7 +191,7 @@ private CompletionStage lookupOnKnownRouters( Ro } else { - return lookupOnRouter( address, true, routingTable, connectionPool, seenServers, bookmark, impersonatedUser, baseError ); + return lookupOnRouter( address, true, routingTable, connectionPool, seenServers, bookmarks, impersonatedUser, baseError ); } } ); } @@ -199,7 +199,7 @@ private CompletionStage lookupOnKnownRouters( Ro } private CompletionStage lookupOnInitialRouter( RoutingTable routingTable, ConnectionPool connectionPool, - Set seenServers, Bookmark bookmark, + Set seenServers, Set bookmarks, String impersonatedUser, Throwable baseError ) { List resolvedRouters; @@ -224,14 +224,14 @@ private CompletionStage lookupOnInitialRouter( R { return completedFuture( composition ); } - return lookupOnRouter( address, false, routingTable, connectionPool, null, bookmark, impersonatedUser, baseError ); + return lookupOnRouter( address, false, routingTable, connectionPool, null, bookmarks, impersonatedUser, baseError ); } ); } return result.thenApply( composition -> composition != null ? new ClusterCompositionLookupResult( composition, resolvedRouterSet ) : null ); } private CompletionStage lookupOnRouter( BoltServerAddress routerAddress, boolean resolveAddress, RoutingTable routingTable, - ConnectionPool connectionPool, Set seenServers, Bookmark bookmark, + ConnectionPool connectionPool, Set seenServers, Set bookmarks, String impersonatedUser, Throwable baseError ) { CompletableFuture addressFuture = CompletableFuture.completedFuture( routerAddress ); @@ -241,7 +241,7 @@ private CompletionStage lookupOnRouter( BoltServerAddress ro .thenApply( address -> addAndReturn( seenServers, address ) ) .thenCompose( connectionPool::acquire ) .thenApply( connection -> ImpersonationUtil.ensureImpersonationSupport( connection, impersonatedUser ) ) - .thenCompose( connection -> provider.getClusterComposition( connection, routingTable.database(), bookmark, impersonatedUser ) ) + .thenCompose( connection -> provider.getClusterComposition( connection, routingTable.database(), bookmarks, impersonatedUser ) ) .handle( ( response, error ) -> { Throwable cause = Futures.completionExceptionCause( error ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunner.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunner.java index 095944b069..479d646cc6 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunner.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunner.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.function.Supplier; @@ -66,12 +67,12 @@ protected RouteMessageRoutingProcedureRunner( RoutingContext routingContext, Sup } @Override - public CompletionStage run( Connection connection, DatabaseName databaseName, Bookmark bookmark, String impersonatedUser ) + public CompletionStage run( Connection connection, DatabaseName databaseName, Set bookmarks, String impersonatedUser ) { CompletableFuture> completableFuture = createCompletableFuture.get(); DirectConnection directConnection = toDirectConnection( connection, databaseName, impersonatedUser ); - directConnection.writeAndFlush( new RouteMessage( routingContext, bookmark, databaseName.databaseName().orElse( null ), impersonatedUser ), + directConnection.writeAndFlush( new RouteMessage( routingContext, bookmarks, databaseName.databaseName().orElse( null ), impersonatedUser ), new RouteMessageResponseHandler( completableFuture ) ); return completableFuture .thenApply( routingTable -> new RoutingProcedureResponse( getQuery( databaseName ), singletonList( toRecord( routingTable ) ) ) ) diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProvider.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProvider.java index 84ae9577cb..72f7d42b75 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProvider.java @@ -19,6 +19,7 @@ package org.neo4j.driver.internal.cluster; import java.util.List; +import java.util.Set; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; @@ -61,7 +62,7 @@ public RoutingProcedureClusterCompositionProvider( Clock clock, RoutingContext r } @Override - public CompletionStage getClusterComposition( Connection connection, DatabaseName databaseName, Bookmark bookmark, + public CompletionStage getClusterComposition( Connection connection, DatabaseName databaseName, Set bookmarks, String impersonatedUser ) { RoutingProcedureRunner runner; @@ -79,7 +80,7 @@ else if ( supportsMultiDatabase( connection ) ) runner = singleDatabaseRoutingProcedureRunner; } - return runner.run( connection, databaseName, bookmark, impersonatedUser ) + return runner.run( connection, databaseName, bookmarks, impersonatedUser ) .thenApply( this::processRoutingResponse ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureRunner.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureRunner.java index c91be6fb7a..ee4ded9831 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureRunner.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingProcedureRunner.java @@ -18,6 +18,7 @@ */ package org.neo4j.driver.internal.cluster; +import java.util.Set; import java.util.concurrent.CompletionStage; import org.neo4j.driver.Bookmark; @@ -34,9 +35,9 @@ public interface RoutingProcedureRunner * * @param connection The connection which will be used to call the server * @param databaseName The database name - * @param bookmark The bookmark used to query the routing information + * @param bookmarks The bookmarks used to query the routing information * @param impersonatedUser The impersonated user, should be {@code null} for non-impersonated requests * @return The routing table */ - CompletionStage run( Connection connection, DatabaseName databaseName, Bookmark bookmark, String impersonatedUser ); + CompletionStage run( Connection connection, DatabaseName databaseName, Set bookmarks, String impersonatedUser ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java index 99c6dbfdf5..f483e48004 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java @@ -88,7 +88,7 @@ else if ( routingTable.isStaleFor( context.mode() ) ) CompletableFuture resultFuture = new CompletableFuture<>(); refreshRoutingTableFuture = resultFuture; - rediscovery.lookupClusterComposition( routingTable, connectionPool, context.rediscoveryBookmark(), null ) + rediscovery.lookupClusterComposition( routingTable, connectionPool, context.rediscoveryBookmarks(), null ) .whenComplete( ( composition, completionError ) -> { Throwable error = Futures.completionExceptionCause( completionError ); diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImpl.java index 06544a0a05..11c086d877 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImpl.java @@ -117,7 +117,7 @@ private CompletionStage ensureDatabaseNameIsComplet databaseNameStage = databaseNameFuture; ClusterRoutingTable routingTable = new ClusterRoutingTable( DatabaseNameUtil.defaultDatabase(), clock ); - rediscovery.lookupClusterComposition( routingTable, connectionPool, context.rediscoveryBookmark(), impersonatedUser ) + rediscovery.lookupClusterComposition( routingTable, connectionPool, context.rediscoveryBookmarks(), impersonatedUser ) .thenCompose( compositionLookupResult -> { diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunner.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunner.java index 585f19f1c5..21fec56718 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunner.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunner.java @@ -19,6 +19,7 @@ package org.neo4j.driver.internal.cluster; import java.util.List; +import java.util.Set; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; @@ -30,7 +31,7 @@ import org.neo4j.driver.async.ResultCursor; import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.exceptions.FatalDiscoveryException; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; import org.neo4j.driver.internal.async.connection.DirectConnection; import org.neo4j.driver.internal.messaging.BoltProtocolVersion; @@ -58,12 +59,12 @@ public SingleDatabaseRoutingProcedureRunner( RoutingContext context ) } @Override - public CompletionStage run( Connection connection, DatabaseName databaseName, Bookmark bookmark, String impersonatedUser ) + public CompletionStage run( Connection connection, DatabaseName databaseName, Set bookmarks, String impersonatedUser ) { DirectConnection delegate = connection( connection ); Query procedure = procedureQuery( connection.protocol().version(), databaseName ); - BookmarkHolder bookmarkHolder = bookmarkHolder( bookmark ); - return runProcedure( delegate, procedure, bookmarkHolder ) + BookmarksHolder bookmarksHolder = bookmarksHolder( bookmarks ); + return runProcedure( delegate, procedure, bookmarksHolder ) .thenCompose( records -> releaseConnection( delegate, records ) ) .handle( ( records, error ) -> processProcedureResponse( procedure, records, error ) ); } @@ -84,15 +85,15 @@ Query procedureQuery( BoltProtocolVersion protocolVersion, DatabaseName database return new Query( GET_ROUTING_TABLE, parameters( ROUTING_CONTEXT, context.toMap() ) ); } - BookmarkHolder bookmarkHolder( Bookmark ignored ) + BookmarksHolder bookmarksHolder( Set ignored ) { - return BookmarkHolder.NO_OP; + return BookmarksHolder.NO_OP; } - CompletionStage> runProcedure(Connection connection, Query procedure, BookmarkHolder bookmarkHolder ) + CompletionStage> runProcedure( Connection connection, Query procedure, BookmarksHolder bookmarksHolder ) { return connection.protocol() - .runInAutoCommitTransaction( connection, procedure, bookmarkHolder, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) + .runInAutoCommitTransaction( connection, procedure, bookmarksHolder, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) .asyncResult().thenCompose( ResultCursor::listAsync ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/handlers/PullHandlers.java b/driver/src/main/java/org/neo4j/driver/internal/handlers/PullHandlers.java index 5c6396be38..48412b1170 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/handlers/PullHandlers.java +++ b/driver/src/main/java/org/neo4j/driver/internal/handlers/PullHandlers.java @@ -19,7 +19,7 @@ package org.neo4j.driver.internal.handlers; import org.neo4j.driver.Query; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.handlers.pulln.AutoPullResponseHandler; import org.neo4j.driver.internal.handlers.pulln.BasicPullResponseHandler; @@ -30,34 +30,33 @@ public class PullHandlers { - public static PullAllResponseHandler newBoltV3PullAllHandler(Query query, RunResponseHandler runHandler, Connection connection, - BookmarkHolder bookmarkHolder, UnmanagedTransaction tx ) + public static PullAllResponseHandler newBoltV3PullAllHandler( Query query, RunResponseHandler runHandler, Connection connection, + BookmarksHolder bookmarksHolder, UnmanagedTransaction tx ) { - PullResponseCompletionListener completionListener = createPullResponseCompletionListener( connection, bookmarkHolder, tx ); + PullResponseCompletionListener completionListener = createPullResponseCompletionListener( connection, bookmarksHolder, tx ); - return new LegacyPullAllResponseHandler(query, runHandler, connection, BoltProtocolV3.METADATA_EXTRACTOR, completionListener ); + return new LegacyPullAllResponseHandler( query, runHandler, connection, BoltProtocolV3.METADATA_EXTRACTOR, completionListener ); } - public static PullAllResponseHandler newBoltV4AutoPullHandler(Query query, RunResponseHandler runHandler, Connection connection, - BookmarkHolder bookmarkHolder, UnmanagedTransaction tx, long fetchSize ) + public static PullAllResponseHandler newBoltV4AutoPullHandler( Query query, RunResponseHandler runHandler, Connection connection, + BookmarksHolder bookmarksHolder, UnmanagedTransaction tx, long fetchSize ) { - PullResponseCompletionListener completionListener = createPullResponseCompletionListener( connection, bookmarkHolder, tx ); + PullResponseCompletionListener completionListener = createPullResponseCompletionListener( connection, bookmarksHolder, tx ); - return new AutoPullResponseHandler(query, runHandler, connection, BoltProtocolV3.METADATA_EXTRACTOR, completionListener, fetchSize ); + return new AutoPullResponseHandler( query, runHandler, connection, BoltProtocolV3.METADATA_EXTRACTOR, completionListener, fetchSize ); } - - public static PullResponseHandler newBoltV4BasicPullHandler(Query query, RunResponseHandler runHandler, Connection connection, - BookmarkHolder bookmarkHolder, UnmanagedTransaction tx ) + public static PullResponseHandler newBoltV4BasicPullHandler( Query query, RunResponseHandler runHandler, Connection connection, + BookmarksHolder bookmarksHolder, UnmanagedTransaction tx ) { - PullResponseCompletionListener completionListener = createPullResponseCompletionListener( connection, bookmarkHolder, tx ); + PullResponseCompletionListener completionListener = createPullResponseCompletionListener( connection, bookmarksHolder, tx ); - return new BasicPullResponseHandler(query, runHandler, connection, BoltProtocolV3.METADATA_EXTRACTOR, completionListener ); + return new BasicPullResponseHandler( query, runHandler, connection, BoltProtocolV3.METADATA_EXTRACTOR, completionListener ); } - private static PullResponseCompletionListener createPullResponseCompletionListener( Connection connection, BookmarkHolder bookmarkHolder, - UnmanagedTransaction tx ) + private static PullResponseCompletionListener createPullResponseCompletionListener( Connection connection, BookmarksHolder bookmarksHolder, + UnmanagedTransaction tx ) { - return tx != null ? new TransactionPullResponseCompletionListener( tx ) : new SessionPullResponseCompletionListener( connection, bookmarkHolder ); + return tx != null ? new TransactionPullResponseCompletionListener( tx ) : new SessionPullResponseCompletionListener( connection, bookmarksHolder ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListener.java b/driver/src/main/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListener.java index 5ff2d63dc0..c6a4ae652d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListener.java @@ -23,7 +23,7 @@ import org.neo4j.driver.Value; import org.neo4j.driver.exceptions.AuthorizationExpiredException; import org.neo4j.driver.exceptions.ConnectionReadTimeoutException; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.util.MetadataExtractor; @@ -31,20 +31,20 @@ public class SessionPullResponseCompletionListener implements PullResponseCompletionListener { - private final BookmarkHolder bookmarkHolder; + private final BookmarksHolder bookmarksHolder; private final Connection connection; - public SessionPullResponseCompletionListener( Connection connection, BookmarkHolder bookmarkHolder ) + public SessionPullResponseCompletionListener( Connection connection, BookmarksHolder bookmarksHolder ) { this.connection = requireNonNull( connection ); - this.bookmarkHolder = requireNonNull( bookmarkHolder ); + this.bookmarksHolder = requireNonNull( bookmarksHolder ); } @Override public void afterSuccess( Map metadata ) { releaseConnection(); - bookmarkHolder.setBookmark( MetadataExtractor.extractBookmarks( metadata ) ); + bookmarksHolder.setBookmark( MetadataExtractor.extractBookmarks( metadata ) ); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/BoltProtocol.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/BoltProtocol.java index 1a47804d91..09f7c5c544 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/BoltProtocol.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/BoltProtocol.java @@ -21,6 +21,7 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelPromise; +import java.util.Set; import java.util.concurrent.CompletionStage; import org.neo4j.driver.AuthToken; @@ -30,8 +31,7 @@ import org.neo4j.driver.Transaction; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.exceptions.ClientException; -import org.neo4j.driver.internal.BookmarkHolder; -import org.neo4j.driver.internal.InternalBookmark; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.cluster.RoutingContext; import org.neo4j.driver.internal.cursor.ResultCursorFactory; @@ -75,11 +75,11 @@ public interface BoltProtocol * Begin an unmanaged transaction. * * @param connection the connection to use. - * @param bookmark the bookmarks. Never null, should be {@link InternalBookmark#empty()} when absent. - * @param config the transaction configuration. Never null, should be {@link TransactionConfig#empty()} when absent. + * @param bookmarks the bookmarks. Never null, should be empty when there are no bookmarks. + * @param config the transaction configuration. Never null, should be {@link TransactionConfig#empty()} when absent. * @return a completion stage completed when transaction is started or completed exceptionally when there was a failure. */ - CompletionStage beginTransaction( Connection connection, Bookmark bookmark, TransactionConfig config ); + CompletionStage beginTransaction( Connection connection, Set bookmarks, TransactionConfig config ); /** * Commit the unmanaged transaction. @@ -100,14 +100,14 @@ public interface BoltProtocol /** * Execute the given query in an auto-commit transaction, i.e. {@link Session#run(Query)}. * - * @param connection the network connection to use. - * @param query the cypher to execute. - * @param bookmarkHolder the bookmarksHolder that keeps track of the current bookmark and can be updated with a new bookmark. - * @param config the transaction config for the implicitly started auto-commit transaction. - * @param fetchSize the record fetch size for PULL message. + * @param connection the network connection to use. + * @param query the cypher to execute. + * @param bookmarksHolder the bookmarksHolder that keeps track of the current bookmarks and can be updated with a new bookmark. + * @param config the transaction config for the implicitly started auto-commit transaction. + * @param fetchSize the record fetch size for PULL message. * @return stage with cursor. */ - ResultCursorFactory runInAutoCommitTransaction( Connection connection, Query query, BookmarkHolder bookmarkHolder, TransactionConfig config, + ResultCursorFactory runInAutoCommitTransaction( Connection connection, Query query, BookmarksHolder bookmarksHolder, TransactionConfig config, long fetchSize ); /** diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoder.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoder.java index 64848d913c..6fddb780f3 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoder.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoder.java @@ -19,8 +19,8 @@ package org.neo4j.driver.internal.messaging.encode; import java.io.IOException; -import java.util.Collections; +import org.neo4j.driver.Bookmark; import org.neo4j.driver.internal.messaging.Message; import org.neo4j.driver.internal.messaging.MessageEncoder; import org.neo4j.driver.internal.messaging.ValuePacker; @@ -41,7 +41,7 @@ public void encode( Message message, ValuePacker packer ) throws IOException RouteMessage routeMessage = (RouteMessage) message; packer.packStructHeader( 3, message.signature() ); packer.pack( routeMessage.getRoutingContext() ); - packer.pack( routeMessage.getBookmark().isPresent() ? value( routeMessage.getBookmark().get().values() ) : value( Collections.emptyList() ) ); + packer.pack( value( routeMessage.getBookmarks().stream().map( Bookmark::value ) ) ); packer.pack( routeMessage.getDatabaseName() ); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteV44MessageEncoder.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteV44MessageEncoder.java index e15d5511c0..003556a86c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteV44MessageEncoder.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/encode/RouteV44MessageEncoder.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.Map; +import org.neo4j.driver.Bookmark; import org.neo4j.driver.Value; import org.neo4j.driver.internal.messaging.Message; import org.neo4j.driver.internal.messaging.MessageEncoder; @@ -43,7 +44,7 @@ public void encode( Message message, ValuePacker packer ) throws IOException RouteMessage routeMessage = (RouteMessage) message; packer.packStructHeader( 3, message.signature() ); packer.pack( routeMessage.getRoutingContext() ); - packer.pack( routeMessage.getBookmark().isPresent() ? value( routeMessage.getBookmark().get().values() ) : value( Collections.emptyList() ) ); + packer.pack( value( routeMessage.getBookmarks().stream().map( Bookmark::value ) ) ); Map params; if ( routeMessage.getImpersonatedUser() != null && routeMessage.getDatabaseName() == null ) diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/BeginMessage.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/BeginMessage.java index 0e82cd61da..8f7f5e6608 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/BeginMessage.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/BeginMessage.java @@ -21,6 +21,7 @@ import java.time.Duration; import java.util.Map; import java.util.Objects; +import java.util.Set; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; @@ -34,15 +35,15 @@ public class BeginMessage extends MessageWithMetadata { public static final byte SIGNATURE = 0x11; - public BeginMessage( Bookmark bookmark, TransactionConfig config, DatabaseName databaseName, AccessMode mode, String impersonatedUser ) + public BeginMessage( Set bookmarks, TransactionConfig config, DatabaseName databaseName, AccessMode mode, String impersonatedUser ) { - this( bookmark, config.timeout(), config.metadata(), mode, databaseName, impersonatedUser ); + this( bookmarks, config.timeout(), config.metadata(), mode, databaseName, impersonatedUser ); } - public BeginMessage( Bookmark bookmark, Duration txTimeout, Map txMetadata, AccessMode mode, DatabaseName databaseName, + public BeginMessage( Set bookmarks, Duration txTimeout, Map txMetadata, AccessMode mode, DatabaseName databaseName, String impersonatedUser ) { - super( buildMetadata( txTimeout, txMetadata, databaseName, mode, bookmark, impersonatedUser ) ); + super( buildMetadata( txTimeout, txMetadata, databaseName, mode, bookmarks, impersonatedUser ) ); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RouteMessage.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RouteMessage.java index 440f3c81f3..258218d391 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RouteMessage.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RouteMessage.java @@ -20,7 +20,7 @@ import java.util.Map; import java.util.Objects; -import java.util.Optional; +import java.util.Set; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Value; @@ -38,7 +38,7 @@ public class RouteMessage implements Message { public final static byte SIGNATURE = 0x66; private final Map routingContext; - private final Bookmark bookmark; + private final Set bookmarks; private final String databaseName; private final String impersonatedUser; @@ -46,14 +46,14 @@ public class RouteMessage implements Message * Constructor * * @param routingContext The routing context used to define the routing table. Multi-datacenter deployments is one of its use cases. - * @param bookmark The bookmark used when getting the routing table. + * @param bookmarks The bookmarks used when getting the routing table. * @param databaseName The name of the database to get the routing table for. * @param impersonatedUser The name of the impersonated user to get the routing table for, should be {@code null} for non-impersonated requests */ - public RouteMessage( Map routingContext, Bookmark bookmark, String databaseName, String impersonatedUser ) + public RouteMessage( Map routingContext, Set bookmarks, String databaseName, String impersonatedUser ) { this.routingContext = unmodifiableMap( routingContext ); - this.bookmark = bookmark; + this.bookmarks = bookmarks; this.databaseName = databaseName; this.impersonatedUser = impersonatedUser; } @@ -63,9 +63,9 @@ public Map getRoutingContext() return routingContext; } - public Optional getBookmark() + public Set getBookmarks() { - return Optional.ofNullable( bookmark ); + return bookmarks; } public String getDatabaseName() @@ -87,7 +87,7 @@ public byte signature() @Override public String toString() { - return String.format( "ROUTE %s %s %s %s", routingContext, bookmark, databaseName, impersonatedUser ); + return String.format( "ROUTE %s %s %s %s", routingContext, bookmarks, databaseName, impersonatedUser ); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RunWithMetadataMessage.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RunWithMetadataMessage.java index 91c6712634..9fc00f94cf 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RunWithMetadataMessage.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/RunWithMetadataMessage.java @@ -21,6 +21,7 @@ import java.time.Duration; import java.util.Map; import java.util.Objects; +import java.util.Set; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; @@ -41,15 +42,15 @@ public class RunWithMetadataMessage extends MessageWithMetadata private final Map parameters; public static RunWithMetadataMessage autoCommitTxRunMessage( Query query, TransactionConfig config, DatabaseName databaseName, AccessMode mode, - Bookmark bookmark, String impersonatedUser ) + Set bookmarks, String impersonatedUser ) { - return autoCommitTxRunMessage( query, config.timeout(), config.metadata(), databaseName, mode, bookmark, impersonatedUser ); + return autoCommitTxRunMessage( query, config.timeout(), config.metadata(), databaseName, mode, bookmarks, impersonatedUser ); } public static RunWithMetadataMessage autoCommitTxRunMessage( Query query, Duration txTimeout, Map txMetadata, DatabaseName databaseName, - AccessMode mode, Bookmark bookmark, String impersonatedUser ) + AccessMode mode, Set bookmarks, String impersonatedUser ) { - Map metadata = buildMetadata( txTimeout, txMetadata, databaseName, mode, bookmark, impersonatedUser ); + Map metadata = buildMetadata( txTimeout, txMetadata, databaseName, mode, bookmarks, impersonatedUser ); return new RunWithMetadataMessage( query.text(), query.parameters().asMap( ofValue() ), metadata ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilder.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilder.java index 7a4ba34b9c..78fa141243 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilder.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilder.java @@ -20,6 +20,7 @@ import java.time.Duration; import java.util.Map; +import java.util.Set; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; @@ -41,16 +42,16 @@ public class TransactionMetadataBuilder private static final String MODE_READ_VALUE = "r"; private static final String IMPERSONATED_USER_KEY = "imp_user"; - public static Map buildMetadata( Duration txTimeout, Map txMetadata, AccessMode mode, Bookmark bookmark, + public static Map buildMetadata( Duration txTimeout, Map txMetadata, AccessMode mode, Set bookmarks, String impersonatedUser ) { - return buildMetadata( txTimeout, txMetadata, defaultDatabase(), mode, bookmark, impersonatedUser ); + return buildMetadata( txTimeout, txMetadata, defaultDatabase(), mode, bookmarks, impersonatedUser ); } public static Map buildMetadata( Duration txTimeout, Map txMetadata, DatabaseName databaseName, AccessMode mode, - Bookmark bookmark, String impersonatedUser ) + Set bookmarks, String impersonatedUser ) { - boolean bookmarksPresent = bookmark != null && !bookmark.isEmpty(); + boolean bookmarksPresent = !bookmarks.isEmpty(); boolean txTimeoutPresent = txTimeout != null; boolean txMetadataPresent = txMetadata != null && !txMetadata.isEmpty(); boolean accessModePresent = mode == AccessMode.READ; @@ -66,7 +67,7 @@ public static Map buildMetadata( Duration txTimeout, Map beginTransaction( Connection connection, Bookmark bookmark, TransactionConfig config ) + public CompletionStage beginTransaction( Connection connection, Set bookmarks, TransactionConfig config ) { try { @@ -122,7 +123,7 @@ public CompletionStage beginTransaction( Connection connection, Bookmark b } CompletableFuture beginTxFuture = new CompletableFuture<>(); - BeginMessage beginMessage = new BeginMessage( bookmark, config, connection.databaseName(), connection.mode(), connection.impersonatedUser() ); + BeginMessage beginMessage = new BeginMessage( bookmarks, config, connection.databaseName(), connection.mode(), connection.impersonatedUser() ); connection.writeAndFlush( beginMessage, new BeginTxResponseHandler( beginTxFuture ) ); return beginTxFuture; } @@ -144,29 +145,29 @@ public CompletionStage rollbackTransaction( Connection connection ) } @Override - public ResultCursorFactory runInAutoCommitTransaction( Connection connection, Query query, BookmarkHolder bookmarkHolder, + public ResultCursorFactory runInAutoCommitTransaction( Connection connection, Query query, BookmarksHolder bookmarksHolder, TransactionConfig config, long fetchSize ) { verifyDatabaseNameBeforeTransaction( connection.databaseName() ); RunWithMetadataMessage runMessage = - autoCommitTxRunMessage( query, config, connection.databaseName(), connection.mode(), bookmarkHolder.getBookmark(), + autoCommitTxRunMessage( query, config, connection.databaseName(), connection.mode(), bookmarksHolder.getBookmarks(), connection.impersonatedUser() ); - return buildResultCursorFactory( connection, query, bookmarkHolder, null, runMessage, fetchSize ); + return buildResultCursorFactory( connection, query, bookmarksHolder, null, runMessage, fetchSize ); } @Override public ResultCursorFactory runInUnmanagedTransaction( Connection connection, Query query, UnmanagedTransaction tx, long fetchSize ) { RunWithMetadataMessage runMessage = unmanagedTxRunMessage( query ); - return buildResultCursorFactory( connection, query, BookmarkHolder.NO_OP, tx, runMessage, fetchSize ); + return buildResultCursorFactory( connection, query, BookmarksHolder.NO_OP, tx, runMessage, fetchSize ); } - protected ResultCursorFactory buildResultCursorFactory( Connection connection, Query query, BookmarkHolder bookmarkHolder, + protected ResultCursorFactory buildResultCursorFactory( Connection connection, Query query, BookmarksHolder bookmarksHolder, UnmanagedTransaction tx, RunWithMetadataMessage runMessage, long ignored ) { CompletableFuture runFuture = new CompletableFuture<>(); RunResponseHandler runHandler = new RunResponseHandler( runFuture, METADATA_EXTRACTOR, connection, tx ); - PullAllResponseHandler pullHandler = newBoltV3PullAllHandler( query, runHandler, connection, bookmarkHolder, tx ); + PullAllResponseHandler pullHandler = newBoltV3PullAllHandler( query, runHandler, connection, bookmarksHolder, tx ); return new AsyncResultCursorOnlyFactory( connection, runMessage, runHandler, runFuture, pullHandler ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4.java index 11c89363d4..32813d299d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4.java @@ -21,7 +21,7 @@ import java.util.concurrent.CompletableFuture; import org.neo4j.driver.Query; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.cursor.ResultCursorFactory; @@ -51,14 +51,14 @@ public MessageFormat createMessageFormat() } @Override - protected ResultCursorFactory buildResultCursorFactory( Connection connection, Query query, BookmarkHolder bookmarkHolder, + protected ResultCursorFactory buildResultCursorFactory( Connection connection, Query query, BookmarksHolder bookmarksHolder, UnmanagedTransaction tx, RunWithMetadataMessage runMessage, long fetchSize ) { CompletableFuture runFuture = new CompletableFuture<>(); RunResponseHandler runHandler = new RunResponseHandler( runFuture, METADATA_EXTRACTOR, connection, tx ); - PullAllResponseHandler pullAllHandler = newBoltV4AutoPullHandler( query, runHandler, connection, bookmarkHolder, tx, fetchSize ); - PullResponseHandler pullHandler = newBoltV4BasicPullHandler( query, runHandler, connection, bookmarkHolder, tx ); + PullAllResponseHandler pullAllHandler = newBoltV4AutoPullHandler( query, runHandler, connection, bookmarksHolder, tx, fetchSize ); + PullResponseHandler pullHandler = newBoltV4BasicPullHandler( query, runHandler, connection, bookmarksHolder, tx ); return new ResultCursorFactoryImpl( connection, runMessage, runHandler, runFuture, pullHandler, pullAllHandler ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41.java b/driver/src/main/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41.java index cd86cfbe9f..c55e1f5d42 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41.java +++ b/driver/src/main/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41.java @@ -21,7 +21,7 @@ import java.util.concurrent.CompletableFuture; import org.neo4j.driver.Query; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.cursor.ResultCursorFactory; @@ -52,14 +52,14 @@ public MessageFormat createMessageFormat() } @Override - protected ResultCursorFactory buildResultCursorFactory( Connection connection, Query query, BookmarkHolder bookmarkHolder, + protected ResultCursorFactory buildResultCursorFactory( Connection connection, Query query, BookmarksHolder bookmarksHolder, UnmanagedTransaction tx, RunWithMetadataMessage runMessage, long fetchSize ) { CompletableFuture runFuture = new CompletableFuture<>(); RunResponseHandler runHandler = new RunResponseHandler( runFuture, METADATA_EXTRACTOR, connection, tx ); - PullAllResponseHandler pullAllHandler = newBoltV4AutoPullHandler( query, runHandler, connection, bookmarkHolder, tx, fetchSize ); - PullResponseHandler pullHandler = newBoltV4BasicPullHandler( query, runHandler, connection, bookmarkHolder, tx ); + PullAllResponseHandler pullAllHandler = newBoltV4AutoPullHandler( query, runHandler, connection, bookmarksHolder, tx, fetchSize ); + PullResponseHandler pullHandler = newBoltV4BasicPullHandler( query, runHandler, connection, bookmarksHolder, tx ); return new ResultCursorFactoryImpl( connection, runMessage, runHandler, runFuture, pullHandler, pullAllHandler ); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java b/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java index 31af51c9a6..eb687e9195 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java @@ -21,6 +21,7 @@ import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -124,9 +125,9 @@ private void releaseConnectionBeforeReturning( CompletableFuture returnFu } } - public Bookmark lastBookmark() + public Set lastBookmarks() { - return session.lastBookmark(); + return session.lastBookmarks(); } public Publisher close() diff --git a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java index 156f421cb5..c598204c60 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java @@ -21,9 +21,12 @@ import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.CompletionStage; import org.neo4j.driver.AccessMode; +import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.internal.async.NetworkSession; @@ -107,4 +110,10 @@ public Publisher run( Query query, TransactionConfig config ) } ) .map( InternalReactiveResult::new ); } + + @Override + public Set lastBookmarks() + { + return new HashSet<>( session.lastBookmarks() ); + } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java index 67e4330f49..d25f8ede5c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java @@ -28,6 +28,7 @@ import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.exceptions.TransactionNestingException; +import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.cursor.RxResultCursor; @@ -141,7 +142,7 @@ private void releaseConnectionBeforeReturning( CompletableFuture returnFu @Override public Bookmark lastBookmark() { - return session.lastBookmark(); + return InternalBookmark.from( session.lastBookmarks() ); } @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/util/MetadataExtractor.java b/driver/src/main/java/org/neo4j/driver/internal/util/MetadataExtractor.java index 8c788d1293..ac985654cc 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/util/MetadataExtractor.java +++ b/driver/src/main/java/org/neo4j/driver/internal/util/MetadataExtractor.java @@ -129,11 +129,9 @@ public static DatabaseInfo extractDatabaseInfo( Map metadata ) public static Bookmark extractBookmarks( Map metadata ) { Value bookmarkValue = metadata.get( "bookmark" ); - if ( bookmarkValue != null && !bookmarkValue.isNull() && bookmarkValue.hasType( TYPE_SYSTEM.STRING() ) ) - { - return InternalBookmark.parse( bookmarkValue.asString() ); - } - return InternalBookmark.empty(); + return bookmarkValue != null && !bookmarkValue.isNull() && bookmarkValue.hasType( TYPE_SYSTEM.STRING() ) + ? InternalBookmark.parse( bookmarkValue.asString() ) + : InternalBookmark.empty(); } public static Value extractServer( Map metadata ) diff --git a/driver/src/main/java/org/neo4j/driver/reactive/ReactiveSession.java b/driver/src/main/java/org/neo4j/driver/reactive/ReactiveSession.java index 0344bf62cd..0a09c14ecd 100644 --- a/driver/src/main/java/org/neo4j/driver/reactive/ReactiveSession.java +++ b/driver/src/main/java/org/neo4j/driver/reactive/ReactiveSession.java @@ -21,6 +21,7 @@ import org.reactivestreams.Publisher; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletionStage; import org.neo4j.driver.AccessMode; @@ -230,12 +231,14 @@ default Publisher run( String query, Map paramete Publisher run( Query query, TransactionConfig config ); /** - * Return the bookmark received following the last completed query within this session. The last completed query can be run in a {@linkplain - * ReactiveTransaction transaction} started using {@linkplain #beginTransaction() beginTransaction} or directly via {@link #run(Query) run}. + * Return a set of last bookmarks. + *

+ * When no new bookmark is received, the initial bookmarks are returned. This may happen when no work has been done using the session. Multivalued {@link + * Bookmark} instances will be mapped to distinct {@link Bookmark} instances. If no initial bookmarks have been provided, an empty set is returned. * - * @return a reference to a previous transaction. + * @return the immutable set of last bookmarks. */ - Bookmark lastBookmark(); + Set lastBookmarks(); /** * Signal that you are done using this session. In the default driver usage, closing and accessing sessions is very low cost. diff --git a/driver/src/main/java/org/neo4j/driver/reactive/RxSession.java b/driver/src/main/java/org/neo4j/driver/reactive/RxSession.java index 33ceb55d9b..c30e44b16b 100644 --- a/driver/src/main/java/org/neo4j/driver/reactive/RxSession.java +++ b/driver/src/main/java/org/neo4j/driver/reactive/RxSession.java @@ -226,11 +226,12 @@ default Publisher beginTransaction() RxResult run(Query query, TransactionConfig config ); /** - * Return the bookmark received following the last completed query within this session. - * The last completed query can be run in a {@linkplain RxTransaction transaction} - * started using {@linkplain #beginTransaction() beginTransaction} or directly via {@link #run(Query) run}. + * Return the last bookmark of this session. + *

+ * When no new bookmark is received, the initial bookmarks are returned as a composite {@link Bookmark} containing all initial bookmarks. This may happen + * when no work has been done using the session. If no initial bookmarks have been provided, an empty {@link Bookmark} is returned. * - * @return a reference to a previous transaction. + * @return the last bookmark. */ Bookmark lastBookmark(); diff --git a/driver/src/test/java/org/neo4j/driver/ParametersTest.java b/driver/src/test/java/org/neo4j/driver/ParametersTest.java index 9358e7dbbc..703d8fc92d 100644 --- a/driver/src/test/java/org/neo4j/driver/ParametersTest.java +++ b/driver/src/test/java/org/neo4j/driver/ParametersTest.java @@ -25,7 +25,7 @@ import java.util.stream.Stream; import org.neo4j.driver.exceptions.ClientException; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalRecord; import org.neo4j.driver.internal.InternalSession; import org.neo4j.driver.internal.async.NetworkSession; @@ -110,7 +110,7 @@ private Session mockedSession() ConnectionProvider provider = mock( ConnectionProvider.class ); RetryLogic retryLogic = mock( RetryLogic.class ); NetworkSession session = - new NetworkSession( provider, retryLogic, defaultDatabase(), AccessMode.WRITE, new DefaultBookmarkHolder(), null, UNLIMITED_FETCH_SIZE, + new NetworkSession( provider, retryLogic, defaultDatabase(), AccessMode.WRITE, new DefaultBookmarksHolder(), null, UNLIMITED_FETCH_SIZE, DEV_NULL_LOGGING ); return new InternalSession( session ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/DefaultBookmarkHolderTest.java b/driver/src/test/java/org/neo4j/driver/internal/DefaultBookmarkHolderTest.java index 2d4c6c089e..366f74cdc7 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DefaultBookmarkHolderTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DefaultBookmarkHolderTest.java @@ -20,71 +20,72 @@ import org.junit.jupiter.api.Test; +import java.util.Collections; +import java.util.Set; + import org.neo4j.driver.Bookmark; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class DefaultBookmarkHolderTest { @Test void shouldAllowToGetAndSetBookmarks() { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder(); - assertEquals( InternalBookmark.empty(), bookmarkHolder.getBookmark() ); + BookmarksHolder bookmarkHolder = new DefaultBookmarksHolder(); + assertTrue( bookmarkHolder.getBookmarks().isEmpty() ); bookmarkHolder.setBookmark( null ); - assertEquals( InternalBookmark.empty(), bookmarkHolder.getBookmark() ); - - bookmarkHolder.setBookmark( InternalBookmark.empty() ); - assertEquals( InternalBookmark.empty(), bookmarkHolder.getBookmark() ); + assertTrue( bookmarkHolder.getBookmarks().isEmpty() ); Bookmark bookmark1 = InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ); bookmarkHolder.setBookmark( bookmark1 ); - assertEquals( bookmark1, bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( bookmark1 ), bookmarkHolder.getBookmarks() ); bookmarkHolder.setBookmark( null ); - assertEquals( bookmark1, bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( bookmark1 ), bookmarkHolder.getBookmarks() ); bookmarkHolder.setBookmark( InternalBookmark.empty() ); - assertEquals( bookmark1, bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( bookmark1 ), bookmarkHolder.getBookmarks() ); Bookmark bookmark2 = InternalBookmark.parse( "neo4j:bookmark:v1:tx2" ); bookmarkHolder.setBookmark( bookmark2 ); - assertEquals( bookmark2, bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( bookmark2 ), bookmarkHolder.getBookmarks() ); Bookmark bookmark3 = InternalBookmark.parse( "neo4j:bookmark:v1:tx42" ); bookmarkHolder.setBookmark( bookmark3 ); - assertEquals( bookmark3, bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( bookmark3 ), bookmarkHolder.getBookmarks() ); } @Test void bookmarkCanBeSet() { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder(); + BookmarksHolder bookmarkHolder = new DefaultBookmarksHolder(); Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); bookmarkHolder.setBookmark( bookmark ); - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( bookmark ), bookmarkHolder.getBookmarks() ); } @Test void shouldNotOverwriteBookmarkWithNull() { Bookmark initBookmark = InternalBookmark.parse( "Cat" ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initBookmark ); - assertEquals( initBookmark, bookmarkHolder.getBookmark() ); + BookmarksHolder bookmarkHolder = new DefaultBookmarksHolder( Collections.singleton( initBookmark ) ); + assertEquals( Collections.singleton( initBookmark ), bookmarkHolder.getBookmarks() ); bookmarkHolder.setBookmark( null ); - assertEquals( initBookmark, bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( initBookmark ), bookmarkHolder.getBookmarks() ); } @Test void shouldNotOverwriteBookmarkWithEmptyBookmark() { - Bookmark initBookmark = InternalBookmark.parse( "Cat" ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initBookmark ); - assertEquals( initBookmark, bookmarkHolder.getBookmark() ); + Set initBookmark = Collections.singleton( InternalBookmark.parse( "Cat" ) ); + BookmarksHolder bookmarkHolder = new DefaultBookmarksHolder( initBookmark ); + assertEquals( initBookmark, bookmarkHolder.getBookmarks() ); bookmarkHolder.setBookmark( InternalBookmark.empty() ); - assertEquals( initBookmark, bookmarkHolder.getBookmark() ); + assertEquals( initBookmark, bookmarkHolder.getBookmarks() ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalBookmarkTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalBookmarkTest.java index 7c217b204b..8406ea2c02 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalBookmarkTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalBookmarkTest.java @@ -51,35 +51,35 @@ void isEmptyForEmptyBookmark() } @Test - void shouldSetToEmptyForNullBookmark() throws Throwable + void shouldSetToEmptyForNullBookmark() { Bookmark bookmark = InternalBookmark.from( null ); assertEquals( InternalBookmark.empty(), bookmark ); } @Test - void shouldSetToEmptyForEmptyBookmarkIterator() throws Throwable + void shouldSetToEmptyForEmptyBookmarkIterator() { Bookmark bookmark = InternalBookmark.from( emptyList() ); assertEquals( InternalBookmark.empty(), bookmark ); } @Test - void shouldSetToEmptyForNullBookmarkList() throws Throwable + void shouldSetToEmptyForNullBookmarkList() { Bookmark bookmark = InternalBookmark.from( singletonList( null ) ); assertEquals( InternalBookmark.empty(), bookmark ); } @Test - void shouldIgnoreNullAndEmptyInBookmarkList() throws Throwable + void shouldIgnoreNullAndEmptyInBookmarkList() { Bookmark bookmark = InternalBookmark.from( Arrays.asList( InternalBookmark.empty(), null, null ) ); assertEquals( InternalBookmark.empty(), bookmark ); } @Test - void shouldReserveBookmarkValuesCorrectly() throws Throwable + void shouldReserveBookmarkValuesCorrectly() { Bookmark one = parse( "one" ); Bookmark two = parse( "two" ); @@ -157,7 +157,7 @@ void shouldReturnAllBookmarks() } @Test - void valueShouldBeReadOnly() throws Throwable + void valueShouldBeReadOnly() { Bookmark bookmark = InternalBookmark.parse( asSet( "first", "second" ) ); Set values = bookmark.values(); diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java index 36e22112af..95f659d285 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java @@ -25,6 +25,7 @@ import org.junit.jupiter.params.provider.MethodSource; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -241,10 +242,10 @@ void shouldCloseSession() @Test void shouldReturnBookmark() { - session = newSession( connectionProvider, InternalBookmark.parse( "Bookmark1" ) ); + session = newSession( connectionProvider, Collections.singleton( InternalBookmark.parse( "Bookmark1" ) ) ); asyncSession = new InternalAsyncSession( session ); - assertThat( asyncSession.lastBookmark(), equalTo( session.lastBookmark() ) ); + assertThat( asyncSession.lastBookmarks(), equalTo( session.lastBookmarks() ) ); } @ParameterizedTest diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java index d0af1ffe8d..332c8dd388 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java @@ -27,7 +27,7 @@ import org.neo4j.driver.Logger; import org.neo4j.driver.Logging; import org.neo4j.driver.TransactionConfig; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.handlers.pulln.FetchSizeUtil; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionProvider; @@ -98,7 +98,7 @@ private static void finalize( NetworkSession session ) throws Exception private static LeakLoggingNetworkSession newSession( Logging logging, boolean openConnection ) { return new LeakLoggingNetworkSession( connectionProviderMock( openConnection ), new FixedRetryLogic( 0 ), defaultDatabase(), READ, - new DefaultBookmarkHolder(), null, FetchSizeUtil.UNLIMITED_FETCH_SIZE, logging ); + new DefaultBookmarksHolder(), null, FetchSizeUtil.UNLIMITED_FETCH_SIZE, logging ); } private static ConnectionProvider connectionProviderMock( boolean openConnection ) diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java index c8a76056b2..5fb2071966 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java @@ -23,6 +23,9 @@ import org.mockito.ArgumentCaptor; import org.mockito.InOrder; +import java.util.Collections; +import java.util.Set; + import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; @@ -232,12 +235,12 @@ void updatesBookmarkWhenTxIsClosed() when( connection.protocol() ).thenReturn( protocol ); UnmanagedTransaction tx = beginTransaction( session ); - assertThat( session.lastBookmark(), instanceOf( InternalBookmark.class ) ); - Bookmark bookmark = (InternalBookmark) session.lastBookmark(); - assertTrue( bookmark.isEmpty() ); + assertThat( session.lastBookmarks(), instanceOf( Set.class ) ); + Set bookmarks = session.lastBookmarks(); + assertTrue( bookmarks.isEmpty() ); await( tx.commitAsync() ); - assertEquals( bookmarkAfterCommit, session.lastBookmark() ); + assertEquals( Collections.singleton( bookmarkAfterCommit ), session.lastBookmarks() ); } @Test @@ -259,8 +262,8 @@ void releasesConnectionWhenTxIsClosed() @Test void bookmarkIsPropagatedFromSession() { - Bookmark bookmark = InternalBookmark.parse( "Bookmarks" ); - NetworkSession session = newSession( connectionProvider, bookmark ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "Bookmarks" ) ); + NetworkSession session = newSession( connectionProvider, bookmarks ); UnmanagedTransaction tx = beginTransaction( session ); assertNotNull( tx ); @@ -282,13 +285,13 @@ void bookmarkIsPropagatedBetweenTransactions() UnmanagedTransaction tx1 = beginTransaction( session ); await( tx1.commitAsync() ); - assertEquals( bookmark1, session.lastBookmark() ); + assertEquals( Collections.singleton( bookmark1 ), session.lastBookmarks() ); UnmanagedTransaction tx2 = beginTransaction( session ); verifyBeginTx( connection, 2 ); await( tx2.commitAsync() ); - assertEquals( bookmark2, session.lastBookmark() ); + assertEquals( Collections.singleton( bookmark2 ), session.lastBookmarks() ); } @Test @@ -315,17 +318,16 @@ private void accessModeUsedToAcquireConnections( AccessMode mode ) @Test void testPassingNoBookmarkShouldRetainBookmark() { - NetworkSession session = newSession( connectionProvider, InternalBookmark.parse( "X" ) ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "X" ) ); + NetworkSession session = newSession( connectionProvider, bookmarks ); beginTransaction( session ); - assertThat( session.lastBookmark(), equalTo( InternalBookmark.parse( "X" ) ) ); + assertThat( session.lastBookmarks(), equalTo( bookmarks ) ); } @Test - void shouldHaveEmptyLastBookmarkInitially() + void shouldHaveEmptyLastBookmarksInitially() { - assertThat( session.lastBookmark(), instanceOf( InternalBookmark.class ) ); - Bookmark bookmark = (InternalBookmark) session.lastBookmark(); - assertTrue( bookmark.isEmpty() ); + assertTrue( session.lastBookmarks().isEmpty() ); } @Test @@ -371,8 +373,8 @@ void shouldRunAfterBeginTxFailureOnBookmark() when( connectionProvider.acquireConnection( any( ConnectionContext.class ) ) ) .thenReturn( completedFuture( connection1 ) ).thenReturn( completedFuture( connection2 ) ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx42" ); - NetworkSession session = newSession( connectionProvider, bookmark ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx42" ) ); + NetworkSession session = newSession( connectionProvider, bookmarks ); Exception e = assertThrows( Exception.class, () -> beginTransaction( session ) ); assertEquals( error, e ); @@ -397,8 +399,8 @@ void shouldBeginTxAfterBeginTxFailureOnBookmark() when( connectionProvider.acquireConnection( any( ConnectionContext.class ) ) ) .thenReturn( completedFuture( connection1 ) ).thenReturn( completedFuture( connection2 ) ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx42" ); - NetworkSession session = newSession( connectionProvider, bookmark ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx42" ) ); + NetworkSession session = newSession( connectionProvider, bookmarks ); Exception e = assertThrows( Exception.class, () -> beginTransaction( session ) ); assertEquals( error, e ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java index f639565a66..3b703fe37c 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java @@ -24,6 +24,8 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.InOrder; +import java.util.Collections; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; @@ -37,7 +39,7 @@ import org.neo4j.driver.exceptions.AuthorizationExpiredException; import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.exceptions.ConnectionReadTimeoutException; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.FailableCursor; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.messaging.BoltProtocol; @@ -131,7 +133,7 @@ void shouldOnlyQueueMessagesWhenNoBookmarkGiven() { Connection connection = connectionMock(); - beginTx( connection, InternalBookmark.empty() ); + beginTx( connection, Collections.emptySet() ); verifyBeginTx( connection ); verify( connection, never() ).writeAndFlush( any(), any(), any(), any() ); @@ -140,10 +142,10 @@ void shouldOnlyQueueMessagesWhenNoBookmarkGiven() @Test void shouldFlushWhenBookmarkGiven() { - Bookmark bookmark = InternalBookmark.parse( "hi, I'm bookmark" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "hi, I'm bookmark" ) ); Connection connection = connectionMock(); - beginTx( connection, bookmark ); + beginTx( connection, bookmarks ); verifyBeginTx( connection ); verify( connection, never() ).write( any(), any(), any(), any() ); @@ -183,12 +185,12 @@ void shouldReleaseConnectionWhenBeginFails() { RuntimeException error = new RuntimeException( "Wrong bookmark!" ); Connection connection = connectionWithBegin( handler -> handler.onFailure( error ) ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); - Bookmark bookmark = InternalBookmark.parse( "SomeBookmark" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "SomeBookmark" ) ); TransactionConfig txConfig = TransactionConfig.empty(); - RuntimeException e = assertThrows( RuntimeException.class, () -> await( tx.beginAsync( bookmark, txConfig ) ) ); + RuntimeException e = assertThrows( RuntimeException.class, () -> await( tx.beginAsync( bookmarks, txConfig ) ) ); assertEquals( error, e ); verify( connection ).release(); @@ -198,12 +200,12 @@ void shouldReleaseConnectionWhenBeginFails() void shouldNotReleaseConnectionWhenBeginSucceeds() { Connection connection = connectionWithBegin( handler -> handler.onSuccess( emptyMap() ) ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); - Bookmark bookmark = InternalBookmark.parse( "SomeBookmark" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "SomeBookmark" ) ); TransactionConfig txConfig = TransactionConfig.empty(); - await( tx.beginAsync( bookmark, txConfig ) ); + await( tx.beginAsync( bookmarks, txConfig ) ); verify( connection, never() ).release(); } @@ -212,7 +214,7 @@ void shouldNotReleaseConnectionWhenBeginSucceeds() void shouldReleaseConnectionWhenTerminatedAndCommitted() { Connection connection = connectionMock(); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); tx.markTerminated( null ); @@ -228,7 +230,7 @@ void shouldNotCreateCircularExceptionWhenTerminationCauseEqualsToCursorFailure() Connection connection = connectionMock(); ClientException terminationCause = new ClientException( "Custom exception" ); ResultCursorsHolder resultCursorsHolder = mockResultCursorWith( terminationCause ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE, resultCursorsHolder ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE, resultCursorsHolder ); tx.markTerminated( terminationCause ); @@ -243,7 +245,7 @@ void shouldNotCreateCircularExceptionWhenTerminationCauseDifferentFromCursorFail Connection connection = connectionMock(); ClientException terminationCause = new ClientException( "Custom exception" ); ResultCursorsHolder resultCursorsHolder = mockResultCursorWith( new ClientException( "Cursor error" ) ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE, resultCursorsHolder ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE, resultCursorsHolder ); tx.markTerminated( terminationCause ); @@ -260,7 +262,7 @@ void shouldNotCreateCircularExceptionWhenTerminatedWithoutFailure() { Connection connection = connectionMock(); ClientException terminationCause = new ClientException( "Custom exception" ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); tx.markTerminated( terminationCause ); @@ -274,7 +276,7 @@ void shouldNotCreateCircularExceptionWhenTerminatedWithoutFailure() void shouldReleaseConnectionWhenTerminatedAndRolledBack() { Connection connection = connectionMock(); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); tx.markTerminated( null ); await( tx.rollbackAsync() ); @@ -286,7 +288,7 @@ void shouldReleaseConnectionWhenTerminatedAndRolledBack() void shouldReleaseConnectionWhenClose() throws Throwable { Connection connection = connectionMock(); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); await( tx.closeAsync() ); @@ -298,11 +300,12 @@ void shouldReleaseConnectionOnConnectionAuthorizationExpiredExceptionFailure() { AuthorizationExpiredException exception = new AuthorizationExpiredException( "code", "message" ); Connection connection = connectionWithBegin( handler -> handler.onFailure( exception ) ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); - Bookmark bookmark = InternalBookmark.parse( "SomeBookmark" ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "SomeBookmark" ) ); TransactionConfig txConfig = TransactionConfig.empty(); - AuthorizationExpiredException actualException = assertThrows( AuthorizationExpiredException.class, () -> await( tx.beginAsync( bookmark, txConfig ) ) ); + AuthorizationExpiredException actualException = + assertThrows( AuthorizationExpiredException.class, () -> await( tx.beginAsync( bookmarks, txConfig ) ) ); assertSame( exception, actualException ); verify( connection ).terminateAndRelease( AuthorizationExpiredException.DESCRIPTION ); @@ -313,12 +316,12 @@ void shouldReleaseConnectionOnConnectionAuthorizationExpiredExceptionFailure() void shouldReleaseConnectionOnConnectionReadTimeoutExceptionFailure() { Connection connection = connectionWithBegin( handler -> handler.onFailure( ConnectionReadTimeoutException.INSTANCE ) ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); - Bookmark bookmark = InternalBookmark.parse( "SomeBookmark" ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "SomeBookmark" ) ); TransactionConfig txConfig = TransactionConfig.empty(); ConnectionReadTimeoutException actualException = - assertThrows( ConnectionReadTimeoutException.class, () -> await( tx.beginAsync( bookmark, txConfig ) ) ); + assertThrows( ConnectionReadTimeoutException.class, () -> await( tx.beginAsync( bookmarks, txConfig ) ) ); assertSame( ConnectionReadTimeoutException.INSTANCE, actualException ); verify( connection ).terminateAndRelease( ConnectionReadTimeoutException.INSTANCE.getMessage() ); @@ -346,7 +349,7 @@ void shouldReturnExistingStageOnSimilarCompletingAction( boolean protocolCommit, BoltProtocol protocol = mock( BoltProtocol.class ); given( connection.protocol() ).willReturn( protocol ); given( protocolCommit ? protocol.commitTransaction( connection ) : protocol.rollbackTransaction( connection ) ).willReturn( new CompletableFuture<>() ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); CompletionStage initialStage = mapTransactionAction( initialAction, tx ).get(); CompletionStage similarStage = mapTransactionAction( similarAction, tx ).get(); @@ -390,7 +393,7 @@ void shouldReturnFailingStageOnConflictingCompletingAction( boolean protocolComm given( connection.protocol() ).willReturn( protocol ); given( protocolCommit ? protocol.commitTransaction( connection ) : protocol.rollbackTransaction( connection ) ) .willReturn( protocolActionCompleted ? completedFuture( null ) : new CompletableFuture<>() ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); CompletionStage originalActionStage = mapTransactionAction( initialAction, tx ).get(); CompletionStage conflictingActionStage = mapTransactionAction( conflictingAction, tx ).get(); @@ -434,7 +437,7 @@ void shouldReturnCompletedWithNullStageOnClosingInactiveTransactionExceptCommitt given( connection.protocol() ).willReturn( protocol ); given( protocolCommit ? protocol.commitTransaction( connection ) : protocol.rollbackTransaction( connection ) ) .willReturn( completedFuture( null ) ); - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); CompletionStage originalActionStage = mapTransactionAction( originalAction, tx ).get(); CompletionStage closeStage = commitOnClose != null ? tx.closeAsync( commitOnClose ) : tx.closeAsync(); @@ -454,13 +457,13 @@ void shouldReturnCompletedWithNullStageOnClosingInactiveTransactionExceptCommitt private static UnmanagedTransaction beginTx( Connection connection ) { - return beginTx( connection, InternalBookmark.empty() ); + return beginTx( connection, Collections.emptySet() ); } - private static UnmanagedTransaction beginTx( Connection connection, Bookmark initialBookmark ) + private static UnmanagedTransaction beginTx( Connection connection, Set initialBookmarks ) { - UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarkHolder(), UNLIMITED_FETCH_SIZE ); - return await( tx.beginAsync( initialBookmark, TransactionConfig.empty() ) ); + UnmanagedTransaction tx = new UnmanagedTransaction( connection, new DefaultBookmarksHolder(), UNLIMITED_FETCH_SIZE ); + return await( tx.beginAsync( initialBookmarks, TransactionConfig.empty() ) ); } private static Connection connectionWithBegin( Consumer beginBehaviour ) diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/AbstractRoutingProcedureRunnerTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/AbstractRoutingProcedureRunnerTest.java index a24f33e25a..e22746483d 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/AbstractRoutingProcedureRunnerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/AbstractRoutingProcedureRunnerTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import java.util.concurrent.CompletionStage; @@ -37,7 +38,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.neo4j.driver.internal.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.InternalBookmark.empty; import static org.neo4j.driver.internal.util.Futures.completedWithNull; import static org.neo4j.driver.internal.util.Futures.failedFuture; import static org.neo4j.driver.util.TestUtil.await; @@ -50,7 +50,7 @@ void shouldReturnFailedResponseOnClientException() ClientException error = new ClientException( "Hi" ); SingleDatabaseRoutingProcedureRunner runner = singleDatabaseRoutingProcedureRunner( RoutingContext.EMPTY, failedFuture( error ) ); - RoutingProcedureResponse response = await( runner.run( connection(), defaultDatabase(), empty(), null ) ); + RoutingProcedureResponse response = await( runner.run( connection(), defaultDatabase(), Collections.emptySet(), null ) ); assertFalse( response.isSuccess() ); assertEquals( error, response.error() ); @@ -62,7 +62,7 @@ void shouldReturnFailedStageOnError() Exception error = new Exception( "Hi" ); SingleDatabaseRoutingProcedureRunner runner = singleDatabaseRoutingProcedureRunner( RoutingContext.EMPTY, failedFuture( error ) ); - Exception e = assertThrows( Exception.class, () -> await( runner.run( connection(), defaultDatabase(), empty(), null ) ) ); + Exception e = assertThrows( Exception.class, () -> await( runner.run( connection(), defaultDatabase(), Collections.emptySet(), null ) ) ); assertEquals( error, e ); } @@ -72,7 +72,7 @@ void shouldReleaseConnectionOnSuccess() SingleDatabaseRoutingProcedureRunner runner = singleDatabaseRoutingProcedureRunner( RoutingContext.EMPTY ); Connection connection = connection(); - RoutingProcedureResponse response = await( runner.run( connection, defaultDatabase(), empty(), null ) ); + RoutingProcedureResponse response = await( runner.run( connection, defaultDatabase(), Collections.emptySet(), null ) ); assertTrue( response.isSuccess() ); verify( connection ).release(); @@ -86,7 +86,7 @@ void shouldPropagateReleaseError() RuntimeException releaseError = new RuntimeException( "Release failed" ); Connection connection = connection( failedFuture( releaseError ) ); - RuntimeException e = assertThrows( RuntimeException.class, () -> await( runner.run( connection, defaultDatabase(), empty(), null ) ) ); + RuntimeException e = assertThrows( RuntimeException.class, () -> await( runner.run( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertEquals( releaseError, e ); verify( connection ).release(); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunnerTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunnerTest.java index 7abbe76252..1e83c5817e 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunnerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/MultiDatabasesRoutingProcedureRunnerTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.params.provider.ValueSource; import java.net.URI; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.CompletionStage; @@ -30,8 +31,8 @@ import org.neo4j.driver.Query; import org.neo4j.driver.Record; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; -import org.neo4j.driver.internal.ReadOnlyBookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; +import org.neo4j.driver.internal.ReadOnlyBookmarksHolder; import org.neo4j.driver.internal.spi.Connection; import static java.util.Collections.EMPTY_MAP; @@ -47,7 +48,6 @@ import static org.neo4j.driver.internal.DatabaseNameUtil.SYSTEM_DATABASE_NAME; import static org.neo4j.driver.internal.DatabaseNameUtil.database; import static org.neo4j.driver.internal.DatabaseNameUtil.systemDatabase; -import static org.neo4j.driver.internal.InternalBookmark.empty; import static org.neo4j.driver.internal.cluster.MultiDatabasesRoutingProcedureRunner.DATABASE_NAME; import static org.neo4j.driver.internal.cluster.MultiDatabasesRoutingProcedureRunner.MULTI_DB_GET_ROUTING_TABLE; import static org.neo4j.driver.internal.cluster.SingleDatabaseRoutingProcedureRunner.ROUTING_CONTEXT; @@ -60,12 +60,12 @@ class MultiDatabasesRoutingProcedureRunnerTest extends AbstractRoutingProcedureR void shouldCallGetRoutingTableWithEmptyMapOnSystemDatabaseForDatabase( String db ) { TestRoutingProcedureRunner runner = new TestRoutingProcedureRunner( RoutingContext.EMPTY ); - RoutingProcedureResponse response = await( runner.run( connection(), database( db ), empty(), null ) ); + RoutingProcedureResponse response = await( runner.run( connection(), database( db ), Collections.emptySet(), null ) ); assertTrue( response.isSuccess() ); assertEquals( 1, response.records().size() ); - assertThat( runner.bookmarkHolder, instanceOf( ReadOnlyBookmarkHolder.class ) ); + assertThat( runner.bookmarksHolder, instanceOf( ReadOnlyBookmarksHolder.class ) ); assertThat( runner.connection.databaseName(), equalTo( systemDatabase() ) ); assertThat( runner.connection.mode(), equalTo( AccessMode.READ ) ); @@ -81,12 +81,12 @@ void shouldCallGetRoutingTableWithParamOnSystemDatabaseForDatabase( String db ) RoutingContext context = new RoutingContext( uri ); TestRoutingProcedureRunner runner = new TestRoutingProcedureRunner( context ); - RoutingProcedureResponse response = await( runner.run( connection(), database( db ), empty(), null ) ); + RoutingProcedureResponse response = await( runner.run( connection(), database( db ), Collections.emptySet(), null ) ); assertTrue( response.isSuccess() ); assertEquals( 1, response.records().size() ); - assertThat( runner.bookmarkHolder, instanceOf( ReadOnlyBookmarkHolder.class ) ); + assertThat( runner.bookmarksHolder, instanceOf( ReadOnlyBookmarksHolder.class ) ); assertThat( runner.connection.databaseName(), equalTo( systemDatabase() ) ); assertThat( runner.connection.mode(), equalTo( AccessMode.READ ) ); @@ -118,7 +118,7 @@ private static class TestRoutingProcedureRunner extends MultiDatabasesRoutingPro final CompletionStage> runProcedureResult; private Connection connection; private Query procedure; - private BookmarkHolder bookmarkHolder; + private BookmarksHolder bookmarksHolder; TestRoutingProcedureRunner( RoutingContext context ) { @@ -132,11 +132,11 @@ private static class TestRoutingProcedureRunner extends MultiDatabasesRoutingPro } @Override - CompletionStage> runProcedure(Connection connection, Query procedure, BookmarkHolder bookmarkHolder ) + CompletionStage> runProcedure( Connection connection, Query procedure, BookmarksHolder bookmarksHolder ) { this.connection = connection; this.procedure = procedure; - this.bookmarkHolder = bookmarkHolder; + this.bookmarksHolder = bookmarksHolder; return runProcedureResult; } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java index f3a8131e0c..b90d2be967 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java @@ -27,9 +27,11 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.neo4j.driver.Logger; import org.neo4j.driver.Logging; @@ -44,14 +46,12 @@ import org.neo4j.driver.internal.DatabaseName; import org.neo4j.driver.internal.DefaultDomainNameResolver; import org.neo4j.driver.internal.DomainNameResolver; -import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.internal.util.FakeClock; import org.neo4j.driver.internal.util.ImmediateSchedulingEventExecutor; import org.neo4j.driver.net.ServerAddressResolver; -import static java.util.Arrays.asList; import static java.util.Collections.emptySet; import static java.util.Collections.singletonMap; import static java.util.concurrent.CompletableFuture.completedFuture; @@ -69,7 +69,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.neo4j.driver.internal.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.InternalBookmark.empty; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; import static org.neo4j.driver.internal.util.ClusterCompositionUtil.A; import static org.neo4j.driver.internal.util.ClusterCompositionUtil.B; @@ -97,7 +96,8 @@ void shouldUseFirstRouterInTable() Rediscovery rediscovery = newRediscovery( A, compositionProvider, mock( ServerAddressResolver.class ) ); RoutingTable table = routingTableMock( B ); - ClusterComposition actualComposition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition actualComposition = + await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( expectedComposition, actualComposition ); verify( table, never() ).forget( B ); @@ -118,7 +118,8 @@ void shouldSkipFailingRouters() Rediscovery rediscovery = newRediscovery( A, compositionProvider, mock( ServerAddressResolver.class ) ); RoutingTable table = routingTableMock( A, B, C ); - ClusterComposition actualComposition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition actualComposition = + await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( expectedComposition, actualComposition ); verify( table ).forget( A ); @@ -141,7 +142,7 @@ void shouldFailImmediatelyOnAuthError() RoutingTable table = routingTableMock( A, B, C ); AuthenticationException error = assertThrows( AuthenticationException.class, - () -> await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ) ); + () -> await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ) ); assertEquals( authError, error ); verify( table ).forget( A ); } @@ -160,7 +161,8 @@ void shouldUseAnotherRouterOnAuthorizationExpiredException() Rediscovery rediscovery = newRediscovery( A, compositionProvider, mock( ServerAddressResolver.class ) ); RoutingTable table = routingTableMock( A, B, C ); - ClusterComposition actualComposition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition actualComposition = + await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( expectedComposition, actualComposition ); verify( table ).forget( A ); @@ -183,7 +185,7 @@ void shouldFailImmediatelyOnBookmarkErrors( String code ) RoutingTable table = routingTableMock( A, B, C ); ClientException actualError = assertThrows( ClientException.class, - () -> await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ) ); + () -> await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ) ); assertEquals( error, actualError ); verify( table ).forget( A ); } @@ -202,7 +204,7 @@ void shouldFailImmediatelyOnClosedPoolError() RoutingTable table = routingTableMock( A, B, C ); IllegalStateException actualError = assertThrows( IllegalStateException.class, - () -> await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ) ); + () -> await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ) ); assertEquals( error, actualError ); verify( table ).forget( A ); } @@ -224,7 +226,8 @@ void shouldFallbackToInitialRouterWhenKnownRoutersFail() Rediscovery rediscovery = newRediscovery( initialRouter, compositionProvider, resolver ); RoutingTable table = routingTableMock( B, C ); - ClusterComposition actualComposition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition actualComposition = + await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( expectedComposition, actualComposition ); verify( table ).forget( B ); @@ -251,7 +254,7 @@ void shouldFailImmediatelyWhenClusterCompositionProviderReturnsFailure() RoutingTable table = routingTableMock( B, C ); // When - ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( validComposition, composition ); ArgumentCaptor warningMessageCaptor = ArgumentCaptor.forClass( String.class ); @@ -284,7 +287,8 @@ void shouldResolveInitialRouterAddress() Rediscovery rediscovery = newRediscovery( initialRouter, compositionProvider, resolver ); RoutingTable table = routingTableMock( B, C ); - ClusterComposition actualComposition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition actualComposition = + await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( expectedComposition, actualComposition ); verify( table ).forget( B ); @@ -313,7 +317,8 @@ void shouldResolveInitialRouterAddressUsingCustomResolver() Rediscovery rediscovery = newRediscovery( A, compositionProvider, resolver ); RoutingTable table = routingTableMock( B, C ); - ClusterComposition actualComposition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition actualComposition = + await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( expectedComposition, actualComposition ); verify( table ).forget( B ); @@ -336,7 +341,8 @@ void shouldPropagateFailureWhenResolverFails() Rediscovery rediscovery = newRediscovery( A, compositionProvider, resolver ); RoutingTable table = routingTableMock(); - RuntimeException error = assertThrows( RuntimeException.class, () -> await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ) ); + RuntimeException error = + assertThrows( RuntimeException.class, () -> await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ) ); assertEquals( "Resolver fails!", error.getMessage() ); verify( resolver ).resolve( A ); @@ -359,7 +365,8 @@ void shouldRecordAllErrorsWhenNoRouterRespond() RoutingTable table = routingTableMock( A, B, C ); ServiceUnavailableException e = - assertThrows( ServiceUnavailableException.class, () -> await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ) ); + assertThrows( ServiceUnavailableException.class, + () -> await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ) ); assertThat( e.getMessage(), containsString( "Could not perform discovery" ) ); assertThat( e.getSuppressed().length, equalTo( 3 ) ); assertThat( e.getSuppressed()[0].getCause(), equalTo( first ) ); @@ -385,7 +392,7 @@ void shouldUseInitialRouterAfterDiscoveryReturnsNoWriters() RoutingTable table = new ClusterRoutingTable( defaultDatabase(), new FakeClock() ); table.update( noWritersComposition ); - ClusterComposition composition2 = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition composition2 = await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( validComposition, composition2 ); } @@ -404,7 +411,7 @@ void shouldUseInitialRouterToStartWith() Rediscovery rediscovery = newRediscovery( initialRouter, compositionProvider, resolver ); RoutingTable table = routingTableMock( true, B, C, D ); - ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( validComposition, composition ); } @@ -425,7 +432,7 @@ void shouldUseKnownRoutersWhenInitialRouterFails() Rediscovery rediscovery = newRediscovery( initialRouter, compositionProvider, resolver ); RoutingTable table = routingTableMock( true, D, E ); - ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ).getClusterComposition(); + ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ).getClusterComposition(); assertEquals( validComposition, composition ); verify( table ).forget( initialRouter ); verify( table ).forget( D ); @@ -447,7 +454,8 @@ void shouldNotLogWhenSingleRetryAttemptFails() RoutingTable table = routingTableMock( A ); ServiceUnavailableException e = - assertThrows( ServiceUnavailableException.class, () -> await( rediscovery.lookupClusterComposition( table, pool, empty(), null ) ) ); + assertThrows( ServiceUnavailableException.class, + () -> await( rediscovery.lookupClusterComposition( table, pool, Collections.emptySet(), null ) ) ); assertThat( e.getMessage(), containsString( "Could not perform discovery" ) ); // rediscovery should not log about retries and should not schedule any retries @@ -491,7 +499,7 @@ private static ClusterCompositionProvider compositionProviderMock( Map responsesByAddress ) { ClusterCompositionProvider provider = mock( ClusterCompositionProvider.class ); - when( provider.getClusterComposition( any( Connection.class ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( provider.getClusterComposition( any( Connection.class ), any( DatabaseName.class ), any( Set.class ), any() ) ) .then( invocation -> { Connection connection = invocation.getArgument( 0 ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryUtil.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryUtil.java index 06454c5126..753651271a 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryUtil.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryUtil.java @@ -18,8 +18,9 @@ */ package org.neo4j.driver.internal.cluster; +import java.util.Collections; + import org.neo4j.driver.AccessMode; -import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.ConnectionContext; import org.neo4j.driver.internal.async.ImmutableConnectionContext; @@ -30,11 +31,11 @@ public class RediscoveryUtil { public static ConnectionContext contextWithDatabase( String databaseName ) { - return new ImmutableConnectionContext( database( databaseName ), InternalBookmark.empty(), AccessMode.WRITE ); + return new ImmutableConnectionContext( database( databaseName ), Collections.emptySet(), AccessMode.WRITE ); } public static ConnectionContext contextWithMode( AccessMode mode ) { - return new ImmutableConnectionContext( defaultDatabase(), InternalBookmark.empty(), mode ); + return new ImmutableConnectionContext( defaultDatabase(), Collections.emptySet(), mode ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunnerTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunnerTest.java index 484394e615..2ac90f16ab 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunnerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RouteMessageRoutingProcedureRunnerTest.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -119,14 +120,14 @@ void shouldReturnFailureWhenSomethingHappensGettingTheRoutingTable() } private void verifyMessageWasWrittenAndFlushed( Connection connection, CompletableFuture> completableFuture, - RoutingContext routingContext, Bookmark bookmark, DatabaseName databaseName ) + RoutingContext routingContext, Set bookmarks, DatabaseName databaseName ) { Map context = routingContext.toMap() .entrySet() .stream() .collect( Collectors.toMap( Map.Entry::getKey, entry -> Values.value( entry.getValue() ) ) ); - verify( connection ).writeAndFlush( eq( new RouteMessage( context, bookmark, databaseName.databaseName().orElse( null ), null ) ), + verify( connection ).writeAndFlush( eq( new RouteMessage( context, bookmarks, databaseName.databaseName().orElse( null ), null ) ), eq( new RouteMessageResponseHandler( completableFuture ) ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProviderTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProviderTest.java index 5b6b175b37..7d1530b16f 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProviderTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingProcedureClusterCompositionProviderTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -32,7 +33,6 @@ import org.neo4j.driver.exceptions.ServiceUnavailableException; import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.InternalRecord; import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3; import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4; @@ -54,7 +54,6 @@ import static org.mockito.Mockito.when; import static org.neo4j.driver.Values.value; import static org.neo4j.driver.internal.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.InternalBookmark.empty; import static org.neo4j.driver.internal.util.Futures.completedWithNull; import static org.neo4j.driver.internal.util.Futures.failedFuture; import static org.neo4j.driver.util.TestUtil.await; @@ -71,12 +70,12 @@ void shouldProtocolErrorWhenNoRecord() newClusterCompositionProvider( mockedRunner, connection ); RoutingProcedureResponse noRecordsResponse = newRoutingResponse(); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( noRecordsResponse ) ); // When & Then ProtocolException error = assertThrows( ProtocolException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( error.getMessage(), containsString( "records received '0' is too few or too many." ) ); } @@ -91,12 +90,12 @@ void shouldProtocolErrorWhenMoreThanOneRecord() Record aRecord = new InternalRecord( asList( "key1", "key2" ), new Value[]{new StringValue( "a value" )} ); RoutingProcedureResponse routingResponse = newRoutingResponse( aRecord, aRecord ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); // When ProtocolException error = assertThrows( ProtocolException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( error.getMessage(), containsString( "records received '2' is too few or too many." ) ); } @@ -111,12 +110,12 @@ void shouldProtocolErrorWhenUnparsableRecord() Record aRecord = new InternalRecord( asList( "key1", "key2" ), new Value[]{new StringValue( "a value" )} ); RoutingProcedureResponse routingResponse = newRoutingResponse( aRecord ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); // When ProtocolException error = assertThrows( ProtocolException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( error.getMessage(), containsString( "unparsable record received." ) ); } @@ -136,13 +135,13 @@ void shouldProtocolErrorWhenNoRouters() serverInfo( "WRITE", "one:1337" ) ) ) } ); RoutingProcedureResponse routingResponse = newRoutingResponse( record ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); when( mockedClock.millis() ).thenReturn( 12345L ); // When ProtocolException error = assertThrows( ProtocolException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( error.getMessage(), containsString( "no router or reader found in response." ) ); } @@ -162,13 +161,13 @@ void routeMessageRoutingProcedureShouldProtocolErrorWhenNoRouters() serverInfo( "WRITE", "one:1337" ) ) ) } ); RoutingProcedureResponse routingResponse = newRoutingResponse( record ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); when( mockedClock.millis() ).thenReturn( 12345L ); // When ProtocolException error = assertThrows( ProtocolException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( error.getMessage(), containsString( "no router or reader found in response." ) ); } @@ -188,13 +187,13 @@ void shouldProtocolErrorWhenNoReaders() serverInfo( "ROUTE", "one:1337", "two:1337" ) ) ) } ); RoutingProcedureResponse routingResponse = newRoutingResponse( record ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); when( mockedClock.millis() ).thenReturn( 12345L ); // When ProtocolException error = assertThrows( ProtocolException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( error.getMessage(), containsString( "no router or reader found in response." ) ); } @@ -214,13 +213,13 @@ void routeMessageRoutingProcedureShouldProtocolErrorWhenNoReaders() serverInfo( "ROUTE", "one:1337", "two:1337" ) ) ) } ); RoutingProcedureResponse routingResponse = newRoutingResponse( record ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); when( mockedClock.millis() ).thenReturn( 12345L ); // When ProtocolException error = assertThrows( ProtocolException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( error.getMessage(), containsString( "no router or reader found in response." ) ); } @@ -233,12 +232,13 @@ void shouldPropagateConnectionFailureExceptions() ClusterCompositionProvider provider = newClusterCompositionProvider( mockedRunner, connection ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( failedFuture( new ServiceUnavailableException( "Connection breaks during cypher execution" ) ) ); // When & Then ServiceUnavailableException e = assertThrows( ServiceUnavailableException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( + provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertThat( e.getMessage(), containsString( "Connection breaks during cypher execution" ) ); } @@ -259,12 +259,12 @@ void shouldReturnSuccessResultWhenNoError() serverInfo( "ROUTE", "one:1337", "two:1337" ) ) ) } ); RoutingProcedureResponse routingResponse = newRoutingResponse( record ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); when( mockedClock.millis() ).thenReturn( 12345L ); // When - ClusterComposition cluster = await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ); + ClusterComposition cluster = await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ); // Then assertEquals( 12345 + 100_000, cluster.expirationTimestamp() ); @@ -290,12 +290,12 @@ void routeMessageRoutingProcedureShouldReturnSuccessResultWhenNoError() serverInfo( "ROUTE", "one:1337", "two:1337" ) ) ) } ); RoutingProcedureResponse routingResponse = newRoutingResponse( record ); - when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( mockedRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( routingResponse ) ); when( mockedClock.millis() ).thenReturn( 12345L ); // When - ClusterComposition cluster = await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ); + ClusterComposition cluster = await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ); // Then assertEquals( 12345 + 100_000, cluster.expirationTimestamp() ); @@ -311,14 +311,14 @@ void shouldReturnFailureWhenProcedureRunnerFails() Connection connection = mock( Connection.class ); RuntimeException error = new RuntimeException( "hi" ); - when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ) + when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( newRoutingResponse( error ) ) ); RoutingProcedureClusterCompositionProvider provider = newClusterCompositionProvider( procedureRunner, connection ); RuntimeException e = assertThrows( RuntimeException.class, - () -> await( provider.getClusterComposition( connection, defaultDatabase(), empty(), null ) ) ); + () -> await( provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ) ) ); assertEquals( error, e ); } @@ -331,10 +331,10 @@ void shouldUseMultiDBProcedureRunnerWhenConnectingWith40Server() throws Throwabl RoutingProcedureClusterCompositionProvider provider = newClusterCompositionProvider( procedureRunner, connection ); - when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ).thenReturn( completedWithNull() ); - provider.getClusterComposition( connection, defaultDatabase(), empty(), null ); + when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ).thenReturn( completedWithNull() ); + provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ); - verify( procedureRunner ).run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ); + verify( procedureRunner ).run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ); } @Test @@ -346,10 +346,10 @@ void shouldUseProcedureRunnerWhenConnectingWith35AndPreviousServers() throws Thr RoutingProcedureClusterCompositionProvider provider = newClusterCompositionProvider( procedureRunner, connection ); - when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ).thenReturn( completedWithNull() ); - provider.getClusterComposition( connection, defaultDatabase(), empty(), null ); + when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ).thenReturn( completedWithNull() ); + provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ); - verify( procedureRunner ).run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ); + verify( procedureRunner ).run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ); } @Test @@ -361,10 +361,10 @@ void shouldUseRouteMessageProcedureRunnerWhenConnectingWithProtocol43() throws T RoutingProcedureClusterCompositionProvider provider = newClusterCompositionProvider( procedureRunner, connection ); - when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ) ).thenReturn( completedWithNull() ); - provider.getClusterComposition( connection, defaultDatabase(), empty(), null ); + when( procedureRunner.run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ) ).thenReturn( completedWithNull() ); + provider.getClusterComposition( connection, defaultDatabase(), Collections.emptySet(), null ); - verify( procedureRunner ).run( eq( connection ), any( DatabaseName.class ), any( InternalBookmark.class ), any() ); + verify( procedureRunner ).run( eq( connection ), any( DatabaseName.class ), any( Set.class ), any() ); } private static Map serverInfo( String role, String... addresses ) diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerTest.java index e732068e40..47ebf69eb6 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerTest.java @@ -32,7 +32,6 @@ import org.neo4j.driver.exceptions.ServiceUnavailableException; import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.ConnectionContext; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; @@ -278,7 +277,7 @@ private static Rediscovery newRediscoveryMock() Rediscovery rediscovery = mock( RediscoveryImpl.class ); Set noServers = Collections.emptySet(); ClusterComposition clusterComposition = new ClusterComposition( 1, noServers, noServers, noServers, null ); - when( rediscovery.lookupClusterComposition( any( RoutingTable.class ), any( ConnectionPool.class ), any( InternalBookmark.class ), any() ) ) + when( rediscovery.lookupClusterComposition( any( RoutingTable.class ), any( ConnectionPool.class ), any( Set.class ), any() ) ) .thenReturn( completedFuture( new ClusterCompositionLookupResult( clusterComposition ) ) ); return rediscovery; } diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImplTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImplTest.java index ffd93d309d..458783410e 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImplTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RoutingTableRegistryImplTest.java @@ -24,6 +24,7 @@ import org.junit.jupiter.params.provider.ValueSource; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -32,7 +33,6 @@ import org.neo4j.driver.AccessMode; import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.ImmutableConnectionContext; import org.neo4j.driver.internal.cluster.RoutingTableRegistryImpl.RoutingTableHandlerFactory; import org.neo4j.driver.internal.spi.ConnectionPool; @@ -98,7 +98,7 @@ void shouldCreateRoutingTableHandlerIfAbsentWhenFreshRoutingTable( String databa // When DatabaseName database = database( databaseName ); - routingTables.ensureRoutingTable( new ImmutableConnectionContext( database, InternalBookmark.empty(), AccessMode.READ ) ); + routingTables.ensureRoutingTable( new ImmutableConnectionContext( database, Collections.emptySet(), AccessMode.READ ) ); // Then assertTrue( map.containsKey( database ) ); @@ -117,7 +117,7 @@ void shouldReturnExistingRoutingTableHandlerWhenFreshRoutingTable( String databa RoutingTableHandlerFactory factory = mockedHandlerFactory(); RoutingTableRegistryImpl routingTables = newRoutingTables( map, factory ); - ImmutableConnectionContext context = new ImmutableConnectionContext( database, InternalBookmark.empty(), AccessMode.READ ); + ImmutableConnectionContext context = new ImmutableConnectionContext( database, Collections.emptySet(), AccessMode.READ ); // When RoutingTableHandler actual = await( routingTables.ensureRoutingTable( context ) ); @@ -138,7 +138,7 @@ void shouldReturnFreshRoutingTable( AccessMode mode ) throws Throwable RoutingTableHandlerFactory factory = mockedHandlerFactory( handler ); RoutingTableRegistryImpl routingTables = new RoutingTableRegistryImpl( map, factory, null, null, null, DEV_NULL_LOGGING ); - ImmutableConnectionContext context = new ImmutableConnectionContext( defaultDatabase(), InternalBookmark.empty(), mode ); + ImmutableConnectionContext context = new ImmutableConnectionContext( defaultDatabase(), Collections.emptySet(), mode ); // When routingTables.ensureRoutingTable( context ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunnerTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunnerTest.java index 7bb13949ee..d4d821a531 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunnerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/SingleDatabaseRoutingProcedureRunnerTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.params.provider.MethodSource; import java.net.URI; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.CompletionStage; @@ -33,7 +34,7 @@ import org.neo4j.driver.Record; import org.neo4j.driver.Value; import org.neo4j.driver.exceptions.FatalDiscoveryException; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.spi.Connection; import static java.util.Collections.EMPTY_MAP; @@ -49,7 +50,6 @@ import static org.neo4j.driver.internal.DatabaseNameUtil.SYSTEM_DATABASE_NAME; import static org.neo4j.driver.internal.DatabaseNameUtil.database; import static org.neo4j.driver.internal.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.InternalBookmark.empty; import static org.neo4j.driver.internal.cluster.SingleDatabaseRoutingProcedureRunner.GET_ROUTING_TABLE; import static org.neo4j.driver.internal.cluster.SingleDatabaseRoutingProcedureRunner.ROUTING_CONTEXT; import static org.neo4j.driver.util.TestUtil.await; @@ -60,12 +60,12 @@ class SingleDatabaseRoutingProcedureRunnerTest extends AbstractRoutingProcedureR void shouldCallGetRoutingTableWithEmptyMap() { TestRoutingProcedureRunner runner = new TestRoutingProcedureRunner( RoutingContext.EMPTY ); - RoutingProcedureResponse response = await( runner.run( connection(), defaultDatabase(), empty(), null ) ); + RoutingProcedureResponse response = await( runner.run( connection(), defaultDatabase(), Collections.emptySet(), null ) ); assertTrue( response.isSuccess() ); assertEquals( 1, response.records().size() ); - assertThat( runner.bookmarkHolder, equalTo( BookmarkHolder.NO_OP ) ); + assertThat( runner.bookmarksHolder, equalTo( BookmarksHolder.NO_OP ) ); assertThat( runner.connection.databaseName(), equalTo( defaultDatabase() ) ); assertThat( runner.connection.mode(), equalTo( AccessMode.WRITE ) ); @@ -80,12 +80,12 @@ void shouldCallGetRoutingTableWithParam() RoutingContext context = new RoutingContext( uri ); TestRoutingProcedureRunner runner = new TestRoutingProcedureRunner( context ); - RoutingProcedureResponse response = await( runner.run( connection(), defaultDatabase(), empty(), null ) ); + RoutingProcedureResponse response = await( runner.run( connection(), defaultDatabase(), Collections.emptySet(), null ) ); assertTrue( response.isSuccess() ); assertEquals( 1, response.records().size() ); - assertThat( runner.bookmarkHolder, equalTo( BookmarkHolder.NO_OP ) ); + assertThat( runner.bookmarksHolder, equalTo( BookmarksHolder.NO_OP ) ); assertThat( runner.connection.databaseName(), equalTo( defaultDatabase() ) ); assertThat( runner.connection.mode(), equalTo( AccessMode.WRITE ) ); @@ -99,7 +99,7 @@ void shouldCallGetRoutingTableWithParam() void shouldErrorWhenDatabaseIsNotAbsent( String db ) throws Throwable { TestRoutingProcedureRunner runner = new TestRoutingProcedureRunner( RoutingContext.EMPTY ); - assertThrows( FatalDiscoveryException.class, () -> await( runner.run( connection(), database( db ), empty(), null ) ) ); + assertThrows( FatalDiscoveryException.class, () -> await( runner.run( connection(), database( db ), Collections.emptySet(), null ) ) ); } SingleDatabaseRoutingProcedureRunner singleDatabaseRoutingProcedureRunner( RoutingContext context ) @@ -128,7 +128,7 @@ private static class TestRoutingProcedureRunner extends SingleDatabaseRoutingPro final CompletionStage> runProcedureResult; private Connection connection; private Query procedure; - private BookmarkHolder bookmarkHolder; + private BookmarksHolder bookmarksHolder; TestRoutingProcedureRunner( RoutingContext context ) { @@ -142,11 +142,11 @@ private static class TestRoutingProcedureRunner extends SingleDatabaseRoutingPro } @Override - CompletionStage> runProcedure(Connection connection, Query procedure, BookmarkHolder bookmarkHolder ) + CompletionStage> runProcedure( Connection connection, Query procedure, BookmarksHolder bookmarksHolder ) { this.connection = connection; this.procedure = procedure; - this.bookmarkHolder = bookmarkHolder; + this.bookmarksHolder = bookmarksHolder; return runProcedureResult; } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java index 48356abf69..708a6b07b1 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java @@ -42,7 +42,6 @@ import org.neo4j.driver.Bookmark; import org.neo4j.driver.Logging; -import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.exceptions.FatalDiscoveryException; import org.neo4j.driver.exceptions.ProtocolException; import org.neo4j.driver.internal.BoltServerAddress; @@ -59,6 +58,7 @@ import org.neo4j.driver.internal.cluster.RoutingTableRegistry; import org.neo4j.driver.internal.cluster.RoutingTableRegistryImpl; import org.neo4j.driver.internal.metrics.DevNullMetricsListener; +import org.neo4j.driver.internal.metrics.MetricsListener; import org.neo4j.driver.internal.spi.Connection; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.internal.util.Clock; @@ -365,7 +365,7 @@ private class RandomizedRediscovery implements Rediscovery { @Override public CompletionStage lookupClusterComposition( RoutingTable routingTable, ConnectionPool connectionPool, - Bookmark bookmark, String impersonatedUser ) + Set bookmarks, String impersonatedUser ) { // when looking up a new routing table, we return a valid random routing table back Set servers = new HashSet<>(); diff --git a/driver/src/test/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListenerTest.java b/driver/src/test/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListenerTest.java index daaeb1c26f..717b92008e 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListenerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/handlers/SessionPullResponseCompletionListenerTest.java @@ -26,7 +26,7 @@ import org.neo4j.driver.exceptions.AuthorizationExpiredException; import org.neo4j.driver.exceptions.ConnectionReadTimeoutException; import org.neo4j.driver.internal.BoltServerAddress; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.handlers.pulln.BasicPullResponseHandler; import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3; @@ -48,7 +48,7 @@ class SessionPullResponseCompletionListenerTest void shouldReleaseConnectionOnSuccess() { Connection connection = newConnectionMock(); - PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarkHolder.NO_OP ); + PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarksHolder.NO_OP ); ResponseHandler handler = newHandler( connection, listener ); handler.onSuccess( emptyMap() ); @@ -60,7 +60,7 @@ void shouldReleaseConnectionOnSuccess() void shouldReleaseConnectionOnFailure() { Connection connection = newConnectionMock(); - PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarkHolder.NO_OP ); + PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarksHolder.NO_OP ); ResponseHandler handler = newHandler( connection, listener ); handler.onFailure( new RuntimeException() ); @@ -73,20 +73,20 @@ void shouldUpdateBookmarksOnSuccess() { Connection connection = newConnectionMock(); String bookmarkValue = "neo4j:bookmark:v1:tx42"; - BookmarkHolder bookmarkHolder = mock( BookmarkHolder.class ); - PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, bookmarkHolder ); + BookmarksHolder bookmarksHolder = mock( BookmarksHolder.class ); + PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, bookmarksHolder ); ResponseHandler handler = newHandler( connection, listener ); handler.onSuccess( singletonMap( "bookmark", value( bookmarkValue ) ) ); - verify( bookmarkHolder ).setBookmark( InternalBookmark.parse( bookmarkValue ) ); + verify( bookmarksHolder ).setBookmark( InternalBookmark.parse( bookmarkValue ) ); } @Test void shouldReleaseConnectionImmediatelyOnAuthorizationExpiredExceptionFailure() { Connection connection = newConnectionMock(); - PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarkHolder.NO_OP ); + PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarksHolder.NO_OP ); ResponseHandler handler = newHandler( connection, listener ); AuthorizationExpiredException exception = new AuthorizationExpiredException( "code", "message" ); @@ -100,7 +100,7 @@ void shouldReleaseConnectionImmediatelyOnAuthorizationExpiredExceptionFailure() void shouldReleaseConnectionImmediatelyOnConnectionReadTimeoutExceptionFailure() { Connection connection = newConnectionMock(); - PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarkHolder.NO_OP ); + PullResponseCompletionListener listener = new SessionPullResponseCompletionListener( connection, BookmarksHolder.NO_OP ); ResponseHandler handler = newHandler( connection, listener ); handler.onFailure( ConnectionReadTimeoutException.INSTANCE ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/handlers/pulln/SessionPullResponseCompletionListenerTest.java b/driver/src/test/java/org/neo4j/driver/internal/handlers/pulln/SessionPullResponseCompletionListenerTest.java index 3c9cc0ddb6..df14f5d514 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/handlers/pulln/SessionPullResponseCompletionListenerTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/handlers/pulln/SessionPullResponseCompletionListenerTest.java @@ -21,9 +21,9 @@ import java.util.Collections; import java.util.function.BiConsumer; -import org.neo4j.driver.Record; import org.neo4j.driver.Query; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.Record; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.handlers.RunResponseHandler; import org.neo4j.driver.internal.handlers.SessionPullResponseCompletionListener; import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4; @@ -45,16 +45,15 @@ protected void shouldHandleSuccessWithSummary( BasicPullResponseHandler.State st Connection conn = mockConnection(); BiConsumer recordConsumer = mock( BiConsumer.class ); BiConsumer summaryConsumer = mock( BiConsumer.class ); - BookmarkHolder bookmarkHolder = mock( BookmarkHolder.class ); - PullResponseHandler handler = newSessionResponseHandler( conn, recordConsumer, summaryConsumer, bookmarkHolder, state ); + BookmarksHolder bookmarksHolder = mock( BookmarksHolder.class ); + PullResponseHandler handler = newSessionResponseHandler( conn, recordConsumer, summaryConsumer, bookmarksHolder, state ); // When handler.onSuccess( Collections.emptyMap() ); // Then -// assertThat( handler.status(), equalTo( SUCCEEDED ) ); verify( conn ).release(); - verify( bookmarkHolder ).setBookmark( any() ); + verify( bookmarksHolder ).setBookmark( any() ); verify( recordConsumer ).accept( null, null ); verify( summaryConsumer ).accept( any( ResultSummary.class ), eq( null ) ); } @@ -83,16 +82,16 @@ protected void shouldHandleFailure( BasicPullResponseHandler.State state ) protected BasicPullResponseHandler newResponseHandlerWithStatus( Connection conn, BiConsumer recordConsumer, BiConsumer summaryConsumer, BasicPullResponseHandler.State state ) { - BookmarkHolder bookmarkHolder = BookmarkHolder.NO_OP; - return newSessionResponseHandler( conn, recordConsumer, summaryConsumer, bookmarkHolder, state ); + BookmarksHolder bookmarksHolder = BookmarksHolder.NO_OP; + return newSessionResponseHandler( conn, recordConsumer, summaryConsumer, bookmarksHolder, state ); } private static BasicPullResponseHandler newSessionResponseHandler( Connection conn, BiConsumer recordConsumer, - BiConsumer summaryConsumer, BookmarkHolder bookmarkHolder, + BiConsumer summaryConsumer, BookmarksHolder bookmarksHolder, BasicPullResponseHandler.State state ) { RunResponseHandler runHandler = mock( RunResponseHandler.class ); - SessionPullResponseCompletionListener listener = new SessionPullResponseCompletionListener( conn, bookmarkHolder ); + SessionPullResponseCompletionListener listener = new SessionPullResponseCompletionListener( conn, bookmarksHolder ); BasicPullResponseHandler handler = new BasicPullResponseHandler( mock( Query.class ), runHandler, conn, BoltProtocolV4.METADATA_EXTRACTOR, listener ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/BeginMessageEncoderTest.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/BeginMessageEncoderTest.java index f2c6355412..aaa6e231b5 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/BeginMessageEncoderTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/BeginMessageEncoderTest.java @@ -26,8 +26,11 @@ import java.time.Duration; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.neo4j.driver.AccessMode; @@ -54,7 +57,7 @@ class BeginMessageEncoderTest @MethodSource( "arguments" ) void shouldEncodeBeginMessage( AccessMode mode, String impersonatedUser ) throws Exception { - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx42" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx42" ) ); Map txMetadata = new HashMap<>(); txMetadata.put( "hello", value( "world" ) ); @@ -62,13 +65,13 @@ void shouldEncodeBeginMessage( AccessMode mode, String impersonatedUser ) throws Duration txTimeout = Duration.ofSeconds( 1 ); - encoder.encode( new BeginMessage( bookmark, txTimeout, txMetadata, mode, defaultDatabase(), impersonatedUser ), packer ); + encoder.encode( new BeginMessage( bookmarks, txTimeout, txMetadata, mode, defaultDatabase(), impersonatedUser ), packer ); InOrder order = inOrder( packer ); order.verify( packer ).packStructHeader( 1, BeginMessage.SIGNATURE ); Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( "bookmarks", value( bookmark.values() ) ); + expectedMetadata.put( "bookmarks", value( bookmarks.stream().map( Bookmark::value ).collect( Collectors.toSet() ) ) ); expectedMetadata.put( "tx_timeout", value( 1000 ) ); expectedMetadata.put( "tx_metadata", value( txMetadata ) ); if ( mode == READ ) diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoderTest.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoderTest.java index 76aa007700..383b258694 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoderTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RouteMessageEncoderTest.java @@ -25,6 +25,7 @@ import org.mockito.InOrder; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -54,7 +55,7 @@ void shouldEncodeRouteMessage(String databaseName) throws IOException { Map routingContext = getRoutingContext(); - encoder.encode( new RouteMessage( getRoutingContext(), null, databaseName, null ), packer ); + encoder.encode( new RouteMessage( getRoutingContext(), Collections.emptySet(), databaseName, null ), packer ); InOrder inOrder = inOrder( packer ); @@ -72,13 +73,13 @@ void shouldEncodeRouteMessageWithBookmark(String databaseName) throws IOExceptio Map routingContext = getRoutingContext(); Bookmark bookmark = InternalBookmark.parse( "somebookmark" ); - encoder.encode( new RouteMessage( getRoutingContext(), bookmark, databaseName, null ), packer ); + encoder.encode( new RouteMessage( getRoutingContext(), Collections.singleton( bookmark ), databaseName, null ), packer ); InOrder inOrder = inOrder( packer ); inOrder.verify( packer ).packStructHeader( 3, (byte) 0x66 ); inOrder.verify( packer ).pack( routingContext ); - inOrder.verify( packer ).pack( value( bookmark.values() ) ); + inOrder.verify( packer ).pack( value( Collections.singleton( bookmark.value() ) ) ); inOrder.verify( packer ).pack( databaseName ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RunWithMetadataMessageEncoderTest.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RunWithMetadataMessageEncoderTest.java index f90da33e62..0a0bd80b9d 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RunWithMetadataMessageEncoderTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/encode/RunWithMetadataMessageEncoderTest.java @@ -24,8 +24,11 @@ import org.mockito.InOrder; import java.time.Duration; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; @@ -56,7 +59,7 @@ void shouldEncodeRunWithMetadataMessage( AccessMode mode ) throws Exception { Map params = singletonMap( "answer", value( 42 ) ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx999" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx999" ) ); Map txMetadata = new HashMap<>(); txMetadata.put( "key1", value( "value1" ) ); @@ -66,7 +69,7 @@ void shouldEncodeRunWithMetadataMessage( AccessMode mode ) throws Exception Duration txTimeout = Duration.ofMillis( 42 ); Query query = new Query( "RETURN $answer", value( params ) ); - encoder.encode( autoCommitTxRunMessage( query, txTimeout, txMetadata, defaultDatabase(), mode, bookmark, null ), packer ); + encoder.encode( autoCommitTxRunMessage( query, txTimeout, txMetadata, defaultDatabase(), mode, bookmarks, null ), packer ); InOrder order = inOrder( packer ); order.verify( packer ).packStructHeader( 3, RunWithMetadataMessage.SIGNATURE ); @@ -74,7 +77,7 @@ void shouldEncodeRunWithMetadataMessage( AccessMode mode ) throws Exception order.verify( packer ).pack( params ); Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( "bookmarks", value( bookmark.values() ) ); + expectedMetadata.put( "bookmarks", value( bookmarks.stream().map( Bookmark::value ).collect( Collectors.toSet() ) ) ); expectedMetadata.put( "tx_timeout", value( 42 ) ); expectedMetadata.put( "tx_metadata", value( txMetadata ) ); if ( mode == READ ) diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilderTest.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilderTest.java index e9dae116ca..3d1add50b8 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilderTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/request/TransactionMetadataBuilderTest.java @@ -25,9 +25,12 @@ import java.time.Duration; import java.time.LocalDateTime; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; @@ -50,7 +53,8 @@ public class TransactionMetadataBuilderTest @EnumSource( AccessMode.class ) void shouldHaveCorrectMetadata( AccessMode mode ) { - Bookmark bookmark = InternalBookmark.parse( new HashSet<>( asList( "neo4j:bookmark:v1:tx11", "neo4j:bookmark:v1:tx52" ) ) ); + Set bookmarks = + Collections.singleton( InternalBookmark.parse( new HashSet<>( asList( "neo4j:bookmark:v1:tx11", "neo4j:bookmark:v1:tx52" ) ) ) ); Map txMetadata = new HashMap<>(); txMetadata.put( "foo", value( "bar" ) ); @@ -59,10 +63,10 @@ void shouldHaveCorrectMetadata( AccessMode mode ) Duration txTimeout = Duration.ofSeconds( 7 ); - Map metadata = buildMetadata( txTimeout, txMetadata, defaultDatabase(), mode, bookmark, null ); + Map metadata = buildMetadata( txTimeout, txMetadata, defaultDatabase(), mode, bookmarks, null ); Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( "bookmarks", value( bookmark.values() ) ); + expectedMetadata.put( "bookmarks", value( bookmarks.stream().map( Bookmark::value ).collect( Collectors.toSet() ) ) ); expectedMetadata.put( "tx_timeout", value( 7000 ) ); expectedMetadata.put( "tx_metadata", value( txMetadata ) ); if ( mode == READ ) @@ -77,7 +81,8 @@ void shouldHaveCorrectMetadata( AccessMode mode ) @ValueSource( strings = {"", "foo", "data"} ) void shouldHaveCorrectMetadataForDatabaseName( String databaseName ) { - Bookmark bookmark = InternalBookmark.parse( new HashSet<>( asList( "neo4j:bookmark:v1:tx11", "neo4j:bookmark:v1:tx52" ) ) ); + Set bookmarks = + Collections.singleton( InternalBookmark.parse( new HashSet<>( asList( "neo4j:bookmark:v1:tx11", "neo4j:bookmark:v1:tx52" ) ) ) ); Map txMetadata = new HashMap<>(); txMetadata.put( "foo", value( "bar" ) ); @@ -86,10 +91,10 @@ void shouldHaveCorrectMetadataForDatabaseName( String databaseName ) Duration txTimeout = Duration.ofSeconds( 7 ); - Map metadata = buildMetadata( txTimeout, txMetadata, database( databaseName ), WRITE, bookmark, null ); + Map metadata = buildMetadata( txTimeout, txMetadata, database( databaseName ), WRITE, bookmarks, null ); Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( "bookmarks", value( bookmark.values() ) ); + expectedMetadata.put( "bookmarks", value( bookmarks.stream().map( Bookmark::value ).collect( Collectors.toSet() ) ) ); expectedMetadata.put( "tx_timeout", value( 7000 ) ); expectedMetadata.put( "tx_metadata", value( txMetadata ) ); expectedMetadata.put( "db", value( databaseName ) ); @@ -100,7 +105,7 @@ void shouldHaveCorrectMetadataForDatabaseName( String databaseName ) @Test void shouldNotHaveMetadataForDatabaseNameWhenIsNull() { - Map metadata = buildMetadata( null, null, defaultDatabase(), WRITE, null, null ); + Map metadata = buildMetadata( null, null, defaultDatabase(), WRITE, Collections.emptySet(), null ); assertTrue( metadata.isEmpty() ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/BoltProtocolV3Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/BoltProtocolV3Test.java index 60f34a4f3f..d03f6e9328 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/BoltProtocolV3Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/BoltProtocolV3Test.java @@ -27,8 +27,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -40,8 +42,8 @@ import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.Value; import org.neo4j.driver.exceptions.ClientException; -import org.neo4j.driver.internal.BookmarkHolder; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.async.connection.ChannelAttributes; @@ -191,9 +193,9 @@ void shouldBeginTransactionWithoutBookmark() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); - verify( connection ).writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + verify( connection ).writeAndFlush( eq( new BeginMessage( Collections.emptySet(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -202,12 +204,12 @@ void shouldBeginTransactionWithoutBookmark() void shouldBeginTransactionWithBookmarks() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( bookmark, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( bookmarks, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -217,10 +219,10 @@ void shouldBeginTransactionWithConfig() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), txConfig ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), txConfig, defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -229,11 +231,12 @@ void shouldBeginTransactionWithConfig() void shouldBeginTransactionWithBookmarksAndConfig() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, txConfig ); - verify( connection ).writeAndFlush( eq( new BeginMessage( bookmark, txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); + verify( connection ).writeAndFlush( eq( new BeginMessage( bookmarks, txConfig, defaultDatabase(), WRITE, null ) ), + any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -286,28 +289,28 @@ void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse( AccessMode @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ), txConfig, mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ) ), txConfig, mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ), txConfig, mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ) ), txConfig, mode ); } @ParameterizedTest @@ -346,7 +349,7 @@ void databaseNameForAutoCommitTransactions() @Test void shouldNotSupportDatabaseNameInBeginTransaction() { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); ClientException e = assertThrows( ClientException.class, () -> await( txStage ) ); assertThat( e.getMessage(), startsWith( "Database name parameter for selecting database is not supported" ) ); @@ -357,7 +360,7 @@ void shouldNotSupportDatabaseNameForAutoCommitTransactions() { ClientException e = assertThrows( ClientException.class, () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), - new Query( "RETURN 1" ), BookmarkHolder.NO_OP, TransactionConfig.empty(), + new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); assertThat( e.getMessage(), startsWith( "Database name parameter for selecting database is not supported" ) ); } @@ -368,12 +371,12 @@ protected void testDatabaseNameSupport( boolean autoCommitTx ) if ( autoCommitTx ) { e = assertThrows( ClientException.class, - () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), new Query( "RETURN 1" ), BookmarkHolder.NO_OP, + () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); } else { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); e = assertThrows( ClientException.class, () -> await( txStage ) ); } @@ -389,7 +392,7 @@ protected void testRunInUnmanagedTransactionAndWaitForRunResponse( boolean succe protocol.runInUnmanagedTransaction( connection, QUERY, mock( UnmanagedTransaction.class ), UNLIMITED_FETCH_SIZE ).asyncResult() .toCompletableFuture(); - ResponseHandler runResponseHandler = verifyRunInvoked( connection, false, InternalBookmark.empty(), TransactionConfig.empty(), mode ).runHandler; + ResponseHandler runResponseHandler = verifyRunInvoked( connection, false, Collections.emptySet(), TransactionConfig.empty(), mode ).runHandler; assertFalse( cursorFuture.isDone() ); Throwable error = new RuntimeException(); @@ -419,13 +422,13 @@ protected void testRunInUnmanagedTransactionAndWaitForRunResponse( boolean succe protected void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConfig config, AccessMode mode ) throws Exception { Connection connection = connectionMock( mode, protocol ); - Bookmark initialBookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ); + Set initialBookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ) ); CompletionStage cursorStage; if ( autoCommitTx ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initialBookmark ); - cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ).asyncResult(); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( initialBookmarks ); + cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ).asyncResult(); } else { @@ -435,52 +438,52 @@ protected void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionCo CompletableFuture cursorFuture = cursorStage.toCompletableFuture(); assertFalse( cursorFuture.isDone() ); - Bookmark bookmark = autoCommitTx ? initialBookmark : InternalBookmark.empty(); + Set bookmarks = autoCommitTx ? initialBookmarks : Collections.emptySet(); - ResponseHandler runResponseHandler = verifyRunInvoked( connection, autoCommitTx, bookmark, config, mode ).runHandler; + ResponseHandler runResponseHandler = verifyRunInvoked( connection, autoCommitTx, bookmarks, config, mode ).runHandler; runResponseHandler.onSuccess( emptyMap() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } - protected void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + protected void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); assertFalse( cursorFuture.isDone() ); - ResponseHandlers handlers = verifyRunInvoked( connection, true, bookmark, config, mode ); + ResponseHandlers handlers = verifyRunInvoked( connection, true, bookmarks, config, mode ); String newBookmarkValue = "neo4j:bookmark:v1:tx98765"; handlers.runHandler.onSuccess( emptyMap() ); handlers.pullAllHandler.onSuccess( singletonMap( "bookmark", value( newBookmarkValue ) ) ); - assertEquals( InternalBookmark.parse( newBookmarkValue ), bookmarkHolder.getBookmark() ); + assertEquals( Collections.singleton( InternalBookmark.parse( newBookmarkValue ) ), bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } - protected void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + protected void testFailedRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); assertFalse( cursorFuture.isDone() ); - ResponseHandler runResponseHandler = verifyRunInvoked( connection, true, bookmark, config, mode ).runHandler; + ResponseHandler runResponseHandler = verifyRunInvoked( connection, true, bookmarks, config, mode ).runHandler; Throwable error = new RuntimeException(); runResponseHandler.onFailure( error ); - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); Throwable actual = assertThrows( error.getClass(), () -> await( cursorFuture.get().mapSuccessfulRunCompletionAsync() ) ); @@ -492,7 +495,8 @@ private static InternalAuthToken dummyAuthToken() return (InternalAuthToken) AuthTokens.basic( "hello", "world" ); } - private static ResponseHandlers verifyRunInvoked( Connection connection, boolean session, Bookmark bookmark, TransactionConfig config, AccessMode mode ) + private static ResponseHandlers verifyRunInvoked( Connection connection, boolean session, Set bookmarks, TransactionConfig config, + AccessMode mode ) { ArgumentCaptor runHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); ArgumentCaptor pullAllHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); @@ -500,7 +504,7 @@ private static ResponseHandlers verifyRunInvoked( Connection connection, boolean RunWithMetadataMessage expectedMessage; if ( session ) { - expectedMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, defaultDatabase(), mode, bookmark, null ); + expectedMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, defaultDatabase(), mode, bookmarks, null ); } else { diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/MessageWriterV3Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/MessageWriterV3Test.java index 1b399ba610..b08df410dc 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/MessageWriterV3Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v3/MessageWriterV3Test.java @@ -90,16 +90,18 @@ protected Stream supportedMessages() // Bolt V3 messages new HelloMessage( "MyDriver/1.2.3", ((InternalAuthToken) basic( "neo4j", "neo4j" )).toMap(), Collections.emptyMap() ), GOODBYE, - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), READ, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), READ, defaultDatabase(), null ), - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), WRITE, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), WRITE, defaultDatabase(), null ), COMMIT, ROLLBACK, autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), READ, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), WRITE, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), unmanagedTxRunMessage( new Query( "RETURN 1" ) ), PULL_ALL, DISCARD_ALL, @@ -107,9 +109,9 @@ protected Stream supportedMessages() // Bolt V3 messages with struct values autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), READ, InternalBookmark.empty(), null ), + defaultDatabase(), READ, Collections.emptySet(), null ), autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), WRITE, InternalBookmark.empty(), null ), + defaultDatabase(), WRITE, Collections.emptySet(), null ), unmanagedTxRunMessage( new Query( "RETURN $x", singletonMap( "x", point( 42, 1, 2, 3 ) ) ) ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4Test.java index 4c7eac908b..5c5d6358c3 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/BoltProtocolV4Test.java @@ -27,8 +27,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -39,9 +41,9 @@ import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.async.connection.ChannelAttributes; @@ -184,10 +186,10 @@ void shouldBeginTransactionWithoutBookmark() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -196,12 +198,12 @@ void shouldBeginTransactionWithoutBookmark() void shouldBeginTransactionWithBookmarks() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( bookmark, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( bookmarks, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -211,10 +213,10 @@ void shouldBeginTransactionWithConfig() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), txConfig ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), txConfig, defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -223,11 +225,12 @@ void shouldBeginTransactionWithConfig() void shouldBeginTransactionWithBookmarksAndConfig() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, txConfig ); - verify( connection ).writeAndFlush( eq( new BeginMessage( bookmark, txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); + verify( connection ).writeAndFlush( eq( new BeginMessage( bookmarks, txConfig, defaultDatabase(), WRITE, null ) ), + any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -280,28 +283,28 @@ void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse( AccessMode @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ), txConfig, mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ) ), txConfig, mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ), txConfig, mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ) ), txConfig, mode ); } @ParameterizedTest @@ -340,7 +343,7 @@ void databaseNameForAutoCommitTransactions() @Test void shouldSupportDatabaseNameInBeginTransaction() { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); assertDoesNotThrow( () -> await( txStage ) ); } @@ -350,7 +353,7 @@ void shouldNotSupportDatabaseNameForAutoCommitTransactions() { assertDoesNotThrow( () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), - new Query( "RETURN 1" ), BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); + new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); } private BoltProtocol createProtocol() @@ -368,18 +371,18 @@ private static InternalAuthToken dummyAuthToken() return (InternalAuthToken) AuthTokens.basic( "hello", "world" ); } - protected void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + protected void testFailedRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to Run message with a failure @@ -387,31 +390,31 @@ protected void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookm runHandler.onFailure( error ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); Throwable actual = assertThrows( error.getClass(), () -> await( cursorFuture.get().mapSuccessfulRunCompletionAsync() ) ); assertSame( error, actual ); } - protected void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + protected void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to the run message runHandler.onSuccess( emptyMap() ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } @@ -457,13 +460,13 @@ protected void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionCo { // Given Connection connection = connectionMock( mode, protocol ); - Bookmark initialBookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ); + Set initialBookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ) ); CompletionStage cursorStage; if ( autoCommitTx ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initialBookmark ); - cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( initialBookmarks ); + cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult(); } else @@ -477,7 +480,7 @@ protected void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionCo assertFalse( cursorFuture.isDone() ); ResponseHandler runResponseHandler = - autoCommitTx ? verifySessionRunInvoked( connection, initialBookmark, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); + autoCommitTx ? verifySessionRunInvoked( connection, initialBookmarks, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); runResponseHandler.onSuccess( emptyMap() ); assertTrue( cursorFuture.isDone() ); @@ -490,18 +493,18 @@ protected void testDatabaseNameSupport( boolean autoCommitTx ) if ( autoCommitTx ) { ResultCursorFactory factory = - protocol.runInAutoCommitTransaction( connection, QUERY, BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); + protocol.runInAutoCommitTransaction( connection, QUERY, BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); CompletionStage resultStage = factory.asyncResult(); ResponseHandler runHandler = - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); runHandler.onSuccess( emptyMap() ); await( resultStage ); } else { - CompletionStage txStage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); await( txStage ); - verifyBeginInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifyBeginInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } } @@ -510,10 +513,10 @@ private ResponseHandler verifyTxRunInvoked( Connection connection ) return verifyRunInvoked( connection, RunWithMetadataMessage.unmanagedTxRunMessage( QUERY ) ); } - private ResponseHandler verifySessionRunInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, + private ResponseHandler verifySessionRunInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { - RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmark, null ); + RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmarks, null ); return verifyRunInvoked( connection, runMessage ); } @@ -531,10 +534,10 @@ private ResponseHandler verifyRunInvoked( Connection connection, RunWithMetadata return runHandlerCaptor.getValue(); } - private void verifyBeginInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) + private void verifyBeginInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { ArgumentCaptor beginHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); - BeginMessage beginMessage = new BeginMessage( bookmark, config, databaseName, mode, null ); + BeginMessage beginMessage = new BeginMessage( bookmarks, config, databaseName, mode, null ); verify( connection ).writeAndFlush( eq( beginMessage ), beginHandlerCaptor.capture() ); assertThat( beginHandlerCaptor.getValue(), instanceOf( BeginTxResponseHandler.class ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/MessageWriterV4Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/MessageWriterV4Test.java index fe7decacd5..bbb661df7a 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/MessageWriterV4Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v4/MessageWriterV4Test.java @@ -98,26 +98,28 @@ protected Stream supportedMessages() // Bolt V3 messages new HelloMessage( "MyDriver/1.2.3", ((InternalAuthToken) basic( "neo4j", "neo4j" )).toMap(), Collections.emptyMap() ), GOODBYE, - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), READ, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), READ, defaultDatabase(), null ), - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), WRITE, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), WRITE, database( "foo" ), null ), COMMIT, ROLLBACK, RESET, autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), READ, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), database( "foo" ), WRITE, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), unmanagedTxRunMessage( new Query( "RETURN 1" ) ), // Bolt V3 messages with struct values autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), READ, InternalBookmark.empty(), null ), + defaultDatabase(), READ, Collections.emptySet(), null ), autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), database( "foo" ), - WRITE, InternalBookmark.empty(), null ), + WRITE, Collections.emptySet(), null ), unmanagedTxRunMessage( new Query( "RETURN $x", singletonMap( "x", point( 42, 1, 2, 3 ) ) ) ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41Test.java index 5ec5d4dd34..0801274a06 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/BoltProtocolV41Test.java @@ -27,8 +27,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -39,9 +41,9 @@ import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.async.connection.ChannelAttributes; @@ -189,10 +191,10 @@ void shouldBeginTransactionWithoutBookmark() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -201,12 +203,12 @@ void shouldBeginTransactionWithoutBookmark() void shouldBeginTransactionWithBookmarks() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( bookmark, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( bookmarks, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -216,10 +218,10 @@ void shouldBeginTransactionWithConfig() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), txConfig ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), txConfig, defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -228,11 +230,12 @@ void shouldBeginTransactionWithConfig() void shouldBeginTransactionWithBookmarksAndConfig() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, txConfig ); - verify( connection ).writeAndFlush( eq( new BeginMessage( bookmark, txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); + verify( connection ).writeAndFlush( eq( new BeginMessage( bookmarks, txConfig, defaultDatabase(), WRITE, null ) ), + any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -285,28 +288,28 @@ void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse( AccessMode @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ), txConfig, mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ) ), txConfig, mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ), txConfig, mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ) ), txConfig, mode ); } @ParameterizedTest @@ -345,7 +348,7 @@ void databaseNameForAutoCommitTransactions() @Test void shouldSupportDatabaseNameInBeginTransaction() { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); assertDoesNotThrow( () -> await( txStage ) ); } @@ -355,7 +358,7 @@ void shouldNotSupportDatabaseNameForAutoCommitTransactions() { assertDoesNotThrow( () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), - new Query( "RETURN 1" ), BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); + new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); } private Class expectedMessageFormatType() @@ -363,18 +366,18 @@ private Class expectedMessageFormatType() return MessageFormatV4.class; } - private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testFailedRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to Run message with a failure @@ -382,31 +385,31 @@ private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmar runHandler.onFailure( error ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); Throwable actual = assertThrows( error.getClass(), () -> await( cursorFuture.get().mapSuccessfulRunCompletionAsync() ) ); assertSame( error, actual ); } - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to the run message runHandler.onSuccess( emptyMap() ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } @@ -452,13 +455,13 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf { // Given Connection connection = connectionMock( mode, protocol ); - Bookmark initialBookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ); + Set initialBookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ) ); CompletionStage cursorStage; if ( autoCommitTx ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initialBookmark ); - cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( initialBookmarks ); + cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult(); } else @@ -471,7 +474,7 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf CompletableFuture cursorFuture = cursorStage.toCompletableFuture(); assertFalse( cursorFuture.isDone() ); ResponseHandler runResponseHandler = - autoCommitTx ? verifySessionRunInvoked( connection, initialBookmark, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); + autoCommitTx ? verifySessionRunInvoked( connection, initialBookmarks, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); runResponseHandler.onSuccess( emptyMap() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); @@ -483,19 +486,19 @@ private void testDatabaseNameSupport( boolean autoCommitTx ) if ( autoCommitTx ) { ResultCursorFactory factory = - protocol.runInAutoCommitTransaction( connection, QUERY, BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); + protocol.runInAutoCommitTransaction( connection, QUERY, BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); CompletionStage resultStage = factory.asyncResult(); ResponseHandler runHandler = - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); runHandler.onSuccess( emptyMap() ); await( resultStage ); - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } else { - CompletionStage txStage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); await( txStage ); - verifyBeginInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifyBeginInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } } @@ -504,10 +507,10 @@ private ResponseHandler verifyTxRunInvoked( Connection connection ) return verifyRunInvoked( connection, RunWithMetadataMessage.unmanagedTxRunMessage( QUERY ) ); } - private ResponseHandler verifySessionRunInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, + private ResponseHandler verifySessionRunInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { - RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmark, null ); + RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmarks, null ); return verifyRunInvoked( connection, runMessage ); } @@ -525,10 +528,10 @@ private ResponseHandler verifyRunInvoked( Connection connection, RunWithMetadata return runHandlerCaptor.getValue(); } - private void verifyBeginInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) + private void verifyBeginInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { ArgumentCaptor beginHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); - BeginMessage beginMessage = new BeginMessage( bookmark, config, databaseName, mode, null ); + BeginMessage beginMessage = new BeginMessage( bookmarks, config, databaseName, mode, null ); verify( connection ).writeAndFlush( eq( beginMessage ), beginHandlerCaptor.capture() ); assertThat( beginHandlerCaptor.getValue(), instanceOf( BeginTxResponseHandler.class ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/MessageWriterV41Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/MessageWriterV41Test.java index 86266f9f27..c7b5821b94 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/MessageWriterV41Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v41/MessageWriterV41Test.java @@ -97,26 +97,28 @@ protected Stream supportedMessages() // Bolt V3 messages new HelloMessage( "MyDriver/1.2.3", ((InternalAuthToken) basic( "neo4j", "neo4j" )).toMap(), Collections.emptyMap() ), GOODBYE, - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), READ, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), READ, defaultDatabase(), null ), - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), WRITE, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), WRITE, database( "foo" ), null ), COMMIT, ROLLBACK, RESET, autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), READ, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), database( "foo" ), WRITE, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), unmanagedTxRunMessage( new Query( "RETURN 1" ) ), // Bolt V3 messages with struct values autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), READ, InternalBookmark.empty(), null ), + defaultDatabase(), READ, Collections.emptySet(), null ), autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), database( "foo" ), - WRITE, InternalBookmark.empty(), null ), + WRITE, Collections.emptySet(), null ), unmanagedTxRunMessage( new Query( "RETURN $x", singletonMap( "x", point( 42, 1, 2, 3 ) ) ) ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/BoltProtocolV42Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/BoltProtocolV42Test.java index 7bd3d211ae..bb286cf74d 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/BoltProtocolV42Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/BoltProtocolV42Test.java @@ -27,8 +27,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -39,9 +41,9 @@ import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.async.connection.ChannelAttributes; @@ -189,10 +191,10 @@ void shouldBeginTransactionWithoutBookmark() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -201,12 +203,12 @@ void shouldBeginTransactionWithoutBookmark() void shouldBeginTransactionWithBookmarks() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( bookmark, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( bookmarks, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -216,10 +218,10 @@ void shouldBeginTransactionWithConfig() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), txConfig ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), txConfig, defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -228,11 +230,12 @@ void shouldBeginTransactionWithConfig() void shouldBeginTransactionWithBookmarksAndConfig() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, txConfig ); - verify( connection ).writeAndFlush( eq( new BeginMessage( bookmark, txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); + verify( connection ).writeAndFlush( eq( new BeginMessage( bookmarks, txConfig, defaultDatabase(), WRITE, null ) ), + any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -285,28 +288,28 @@ void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse( AccessMode @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ), txConfig, mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ) ), txConfig, mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ), txConfig, mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ) ), txConfig, mode ); } @ParameterizedTest @@ -345,7 +348,7 @@ void databaseNameForAutoCommitTransactions() @Test void shouldSupportDatabaseNameInBeginTransaction() { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); assertDoesNotThrow( () -> await( txStage ) ); } @@ -355,7 +358,7 @@ void shouldNotSupportDatabaseNameForAutoCommitTransactions() { assertDoesNotThrow( () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), - new Query( "RETURN 1" ), BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); + new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); } private Class expectedMessageFormatType() @@ -363,18 +366,18 @@ private Class expectedMessageFormatType() return MessageFormatV4.class; } - private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testFailedRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to Run message with a failure @@ -382,30 +385,30 @@ private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmar runHandler.onFailure( error ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); Throwable actual = assertThrows( error.getClass(), () -> await( cursorFuture.get().mapSuccessfulRunCompletionAsync() ) ); assertSame( error, actual ); } - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to the run message runHandler.onSuccess( emptyMap() ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } @@ -451,13 +454,13 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf { // Given Connection connection = connectionMock( mode, protocol ); - Bookmark initialBookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ); + Set initialBookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ) ); CompletionStage cursorStage; if ( autoCommitTx ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initialBookmark ); - cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( initialBookmarks ); + cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult(); } else @@ -471,7 +474,7 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf assertFalse( cursorFuture.isDone() ); ResponseHandler runResponseHandler = - autoCommitTx ? verifySessionRunInvoked( connection, initialBookmark, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); + autoCommitTx ? verifySessionRunInvoked( connection, initialBookmarks, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); runResponseHandler.onSuccess( emptyMap() ); assertTrue( cursorFuture.isDone() ); @@ -484,19 +487,19 @@ private void testDatabaseNameSupport( boolean autoCommitTx ) if ( autoCommitTx ) { ResultCursorFactory factory = - protocol.runInAutoCommitTransaction( connection, QUERY, BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); + protocol.runInAutoCommitTransaction( connection, QUERY, BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); CompletionStage resultStage = factory.asyncResult(); ResponseHandler runHandler = - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); runHandler.onSuccess( emptyMap() ); await( resultStage ); - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } else { - CompletionStage txStage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); await( txStage ); - verifyBeginInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifyBeginInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } } @@ -505,10 +508,10 @@ private ResponseHandler verifyTxRunInvoked( Connection connection ) return verifyRunInvoked( connection, RunWithMetadataMessage.unmanagedTxRunMessage( QUERY ) ); } - private ResponseHandler verifySessionRunInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, + private ResponseHandler verifySessionRunInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { - RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmark, null ); + RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmarks, null ); return verifyRunInvoked( connection, runMessage ); } @@ -526,10 +529,10 @@ private ResponseHandler verifyRunInvoked( Connection connection, RunWithMetadata return runHandlerCaptor.getValue(); } - private void verifyBeginInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) + private void verifyBeginInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { ArgumentCaptor beginHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); - BeginMessage beginMessage = new BeginMessage( bookmark, config, databaseName, mode, null ); + BeginMessage beginMessage = new BeginMessage( bookmarks, config, databaseName, mode, null ); verify( connection ).writeAndFlush( eq( beginMessage ), beginHandlerCaptor.capture() ); assertThat( beginHandlerCaptor.getValue(), instanceOf( BeginTxResponseHandler.class ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/MessageWriterV42Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/MessageWriterV42Test.java index 8ebd7217bd..9920aee550 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/MessageWriterV42Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v42/MessageWriterV42Test.java @@ -97,26 +97,28 @@ protected Stream supportedMessages() // Bolt V3 messages new HelloMessage( "MyDriver/1.2.3", ((InternalAuthToken) basic( "neo4j", "neo4j" )).toMap(), Collections.emptyMap() ), GOODBYE, - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), READ, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), READ, defaultDatabase(), null ), - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), WRITE, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), WRITE, database( "foo" ), null ), COMMIT, ROLLBACK, RESET, autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), READ, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), database( "foo" ), WRITE, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), unmanagedTxRunMessage( new Query( "RETURN 1" ) ), // Bolt V3 messages with struct values autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), READ, InternalBookmark.empty(), null ), + defaultDatabase(), READ, Collections.emptySet(), null ), autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), database( "foo" ), - WRITE, InternalBookmark.empty(), null ), + WRITE, Collections.emptySet(), null ), unmanagedTxRunMessage( new Query( "RETURN $x", singletonMap( "x", point( 42, 1, 2, 3 ) ) ) ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/BoltProtocolV43Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/BoltProtocolV43Test.java index f2ab8545cf..855f0f3cef 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/BoltProtocolV43Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/BoltProtocolV43Test.java @@ -27,8 +27,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -39,9 +41,9 @@ import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.async.connection.ChannelAttributes; @@ -188,10 +190,10 @@ void shouldBeginTransactionWithoutBookmark() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -200,12 +202,12 @@ void shouldBeginTransactionWithoutBookmark() void shouldBeginTransactionWithBookmarks() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( bookmark, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( bookmarks, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -215,10 +217,10 @@ void shouldBeginTransactionWithConfig() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), txConfig ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), txConfig, defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -227,11 +229,12 @@ void shouldBeginTransactionWithConfig() void shouldBeginTransactionWithBookmarksAndConfig() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, txConfig ); - verify( connection ).writeAndFlush( eq( new BeginMessage( bookmark, txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); + verify( connection ).writeAndFlush( eq( new BeginMessage( bookmarks, txConfig, defaultDatabase(), WRITE, null ) ), + any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -284,28 +287,28 @@ void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse( AccessMode @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ), txConfig, mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ) ), txConfig, mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ), txConfig, mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ) ), txConfig, mode ); } @ParameterizedTest @@ -344,7 +347,7 @@ void databaseNameForAutoCommitTransactions() @Test void shouldSupportDatabaseNameInBeginTransaction() { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); assertDoesNotThrow( () -> await( txStage ) ); } @@ -354,7 +357,7 @@ void shouldNotSupportDatabaseNameForAutoCommitTransactions() { assertDoesNotThrow( () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), - new Query( "RETURN 1" ), BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); + new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); } private Class expectedMessageFormatType() @@ -362,18 +365,18 @@ private Class expectedMessageFormatType() return MessageFormatV43.class; } - private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testFailedRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to Run message with a failure @@ -381,31 +384,31 @@ private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmar runHandler.onFailure( error ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); Throwable actual = assertThrows( error.getClass(), () -> await( cursorFuture.get().mapSuccessfulRunCompletionAsync() ) ); assertSame( error, actual ); } - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to the run message runHandler.onSuccess( emptyMap() ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } @@ -451,13 +454,13 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf { // Given Connection connection = connectionMock( mode, protocol ); - Bookmark initialBookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ); + Set initialBookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ) ); CompletionStage cursorStage; if ( autoCommitTx ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initialBookmark ); - cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( initialBookmarks ); + cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult(); } else @@ -471,7 +474,7 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf assertFalse( cursorFuture.isDone() ); ResponseHandler runResponseHandler = - autoCommitTx ? verifySessionRunInvoked( connection, initialBookmark, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); + autoCommitTx ? verifySessionRunInvoked( connection, initialBookmarks, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); runResponseHandler.onSuccess( emptyMap() ); assertTrue( cursorFuture.isDone() ); @@ -484,19 +487,19 @@ private void testDatabaseNameSupport( boolean autoCommitTx ) if ( autoCommitTx ) { ResultCursorFactory factory = - protocol.runInAutoCommitTransaction( connection, QUERY, BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); + protocol.runInAutoCommitTransaction( connection, QUERY, BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); CompletionStage resultStage = factory.asyncResult(); ResponseHandler runHandler = - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); runHandler.onSuccess( emptyMap() ); await( resultStage ); - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } else { - CompletionStage txStage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); await( txStage ); - verifyBeginInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifyBeginInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } } @@ -505,10 +508,10 @@ private ResponseHandler verifyTxRunInvoked( Connection connection ) return verifyRunInvoked( connection, RunWithMetadataMessage.unmanagedTxRunMessage( QUERY ) ); } - private ResponseHandler verifySessionRunInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, + private ResponseHandler verifySessionRunInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { - RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmark, null ); + RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmarks, null ); return verifyRunInvoked( connection, runMessage ); } @@ -526,10 +529,10 @@ private ResponseHandler verifyRunInvoked( Connection connection, RunWithMetadata return runHandlerCaptor.getValue(); } - private void verifyBeginInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) + private void verifyBeginInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { ArgumentCaptor beginHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); - BeginMessage beginMessage = new BeginMessage( bookmark, config, databaseName, mode, null ); + BeginMessage beginMessage = new BeginMessage( bookmarks, config, databaseName, mode, null ); verify( connection ).writeAndFlush( eq( beginMessage ), beginHandlerCaptor.capture() ); assertThat( beginHandlerCaptor.getValue(), instanceOf( BeginTxResponseHandler.class ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/MessageWriterV43Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/MessageWriterV43Test.java index 2f45f29f63..3fb849d16a 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/MessageWriterV43Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v43/MessageWriterV43Test.java @@ -102,26 +102,28 @@ protected Stream supportedMessages() // Bolt V3 messages new HelloMessage( "MyDriver/1.2.3", ((InternalAuthToken) basic( "neo4j", "neo4j" )).toMap(), Collections.emptyMap() ), GOODBYE, - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), READ, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), READ, defaultDatabase(), null ), - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), WRITE, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), WRITE, database( "foo" ), null ), COMMIT, ROLLBACK, RESET, autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), READ, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), database( "foo" ), WRITE, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), unmanagedTxRunMessage( new Query( "RETURN 1" ) ), // Bolt V3 messages with struct values autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), READ, InternalBookmark.empty(), null ), + defaultDatabase(), READ, Collections.emptySet(), null ), autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), database( "foo" ), - WRITE, InternalBookmark.empty(), null ), + WRITE, Collections.emptySet(), null ), unmanagedTxRunMessage( new Query( "RETURN $x", singletonMap( "x", point( 42, 1, 2, 3 ) ) ) ), // New 4.3 Messages @@ -143,6 +145,6 @@ private RouteMessage routeMessage() { Map routeContext = new HashMap<>(); routeContext.put( "someContext", Values.value( 124 ) ); - return new RouteMessage( routeContext, InternalBookmark.empty(), "dbName", null ); + return new RouteMessage( routeContext, Collections.emptySet(), "dbName", null ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/BoltProtocolV44Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/BoltProtocolV44Test.java index adffe6d22a..fce553a385 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/BoltProtocolV44Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/BoltProtocolV44Test.java @@ -27,8 +27,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -39,9 +41,9 @@ import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.async.connection.ChannelAttributes; @@ -188,10 +190,10 @@ void shouldBeginTransactionWithoutBookmark() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -200,12 +202,12 @@ void shouldBeginTransactionWithoutBookmark() void shouldBeginTransactionWithBookmarks() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( bookmark, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( bookmarks, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -215,10 +217,10 @@ void shouldBeginTransactionWithConfig() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), txConfig ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), txConfig, defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -227,11 +229,12 @@ void shouldBeginTransactionWithConfig() void shouldBeginTransactionWithBookmarksAndConfig() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, txConfig ); - verify( connection ).writeAndFlush( eq( new BeginMessage( bookmark, txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); + verify( connection ).writeAndFlush( eq( new BeginMessage( bookmarks, txConfig, defaultDatabase(), WRITE, null ) ), + any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -284,28 +287,28 @@ void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse( AccessMode @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ), txConfig, mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ) ), txConfig, mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ), txConfig, mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ) ), txConfig, mode ); } @ParameterizedTest @@ -344,7 +347,7 @@ void databaseNameForAutoCommitTransactions() @Test void shouldSupportDatabaseNameInBeginTransaction() { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); assertDoesNotThrow( () -> await( txStage ) ); } @@ -354,7 +357,7 @@ void shouldNotSupportDatabaseNameForAutoCommitTransactions() { assertDoesNotThrow( () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), - new Query( "RETURN 1" ), BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); + new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); } private Class expectedMessageFormatType() @@ -362,18 +365,18 @@ private Class expectedMessageFormatType() return MessageFormatV44.class; } - private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testFailedRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to Run message with a failure @@ -381,31 +384,31 @@ private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmar runHandler.onFailure( error ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); Throwable actual = assertThrows( error.getClass(), () -> await( cursorFuture.get().mapSuccessfulRunCompletionAsync() ) ); assertSame( error, actual ); } - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to the run message runHandler.onSuccess( emptyMap() ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } @@ -451,13 +454,13 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf { // Given Connection connection = connectionMock( mode, protocol ); - Bookmark initialBookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ); + Set initialBookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ) ); CompletionStage cursorStage; if ( autoCommitTx ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initialBookmark ); - cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( initialBookmarks ); + cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult(); } else @@ -471,7 +474,7 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf assertFalse( cursorFuture.isDone() ); ResponseHandler runResponseHandler = - autoCommitTx ? verifySessionRunInvoked( connection, initialBookmark, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); + autoCommitTx ? verifySessionRunInvoked( connection, initialBookmarks, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); runResponseHandler.onSuccess( emptyMap() ); assertTrue( cursorFuture.isDone() ); @@ -484,19 +487,19 @@ private void testDatabaseNameSupport( boolean autoCommitTx ) if ( autoCommitTx ) { ResultCursorFactory factory = - protocol.runInAutoCommitTransaction( connection, QUERY, BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); + protocol.runInAutoCommitTransaction( connection, QUERY, BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); CompletionStage resultStage = factory.asyncResult(); ResponseHandler runHandler = - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); runHandler.onSuccess( emptyMap() ); await( resultStage ); - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } else { - CompletionStage txStage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); await( txStage ); - verifyBeginInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifyBeginInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } } @@ -505,10 +508,10 @@ private ResponseHandler verifyTxRunInvoked( Connection connection ) return verifyRunInvoked( connection, RunWithMetadataMessage.unmanagedTxRunMessage( QUERY ) ); } - private ResponseHandler verifySessionRunInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, + private ResponseHandler verifySessionRunInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { - RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmark, null ); + RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmarks, null ); return verifyRunInvoked( connection, runMessage ); } @@ -526,10 +529,10 @@ private ResponseHandler verifyRunInvoked( Connection connection, RunWithMetadata return runHandlerCaptor.getValue(); } - private void verifyBeginInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) + private void verifyBeginInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { ArgumentCaptor beginHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); - BeginMessage beginMessage = new BeginMessage( bookmark, config, databaseName, mode, null ); + BeginMessage beginMessage = new BeginMessage( bookmarks, config, databaseName, mode, null ); verify( connection ).writeAndFlush( eq( beginMessage ), beginHandlerCaptor.capture() ); assertThat( beginHandlerCaptor.getValue(), instanceOf( BeginTxResponseHandler.class ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/MessageWriterV44Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/MessageWriterV44Test.java index 5214bf083f..24533b7c49 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/MessageWriterV44Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v44/MessageWriterV44Test.java @@ -102,26 +102,28 @@ protected Stream supportedMessages() // Bolt V3 messages new HelloMessage( "MyDriver/1.2.3", ((InternalAuthToken) basic( "neo4j", "neo4j" )).toMap(), Collections.emptyMap() ), GOODBYE, - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), READ, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), READ, defaultDatabase(), null ), - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), WRITE, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), WRITE, database( "foo" ), null ), COMMIT, ROLLBACK, RESET, autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), READ, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), database( "foo" ), WRITE, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), unmanagedTxRunMessage( new Query( "RETURN 1" ) ), // Bolt V3 messages with struct values autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), READ, InternalBookmark.empty(), null ), + defaultDatabase(), READ, Collections.emptySet(), null ), autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), database( "foo" ), - WRITE, InternalBookmark.empty(), null ), + WRITE, Collections.emptySet(), null ), unmanagedTxRunMessage( new Query( "RETURN $x", singletonMap( "x", point( 42, 1, 2, 3 ) ) ) ), // New 4.3 Messages @@ -143,6 +145,6 @@ private RouteMessage routeMessage() { Map routeContext = new HashMap<>(); routeContext.put( "someContext", Values.value( 124 ) ); - return new RouteMessage( routeContext, InternalBookmark.empty(), "dbName", null ); + return new RouteMessage( routeContext, Collections.emptySet(), "dbName", null ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/BoltProtocolV5Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/BoltProtocolV5Test.java index eac7d06528..96e879961f 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/BoltProtocolV5Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/BoltProtocolV5Test.java @@ -27,8 +27,10 @@ import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -39,9 +41,9 @@ import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.BookmarkHolder; +import org.neo4j.driver.internal.BookmarksHolder; import org.neo4j.driver.internal.DatabaseName; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.UnmanagedTransaction; import org.neo4j.driver.internal.async.connection.ChannelAttributes; @@ -188,10 +190,10 @@ void shouldBeginTransactionWithoutBookmark() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -200,12 +202,12 @@ void shouldBeginTransactionWithoutBookmark() void shouldBeginTransactionWithBookmarks() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx100" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, TransactionConfig.empty() ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, TransactionConfig.empty() ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( bookmark, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( bookmarks, TransactionConfig.empty(), defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -215,10 +217,10 @@ void shouldBeginTransactionWithConfig() { Connection connection = connectionMock( protocol ); - CompletionStage stage = protocol.beginTransaction( connection, InternalBookmark.empty(), txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, Collections.emptySet(), txConfig ); verify( connection ) - .writeAndFlush( eq( new BeginMessage( InternalBookmark.empty(), txConfig, defaultDatabase(), WRITE, null ) ), + .writeAndFlush( eq( new BeginMessage( Collections.emptySet(), txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -227,11 +229,12 @@ void shouldBeginTransactionWithConfig() void shouldBeginTransactionWithBookmarksAndConfig() { Connection connection = connectionMock( protocol ); - Bookmark bookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ); + Set bookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx4242" ) ); - CompletionStage stage = protocol.beginTransaction( connection, bookmark, txConfig ); + CompletionStage stage = protocol.beginTransaction( connection, bookmarks, txConfig ); - verify( connection ).writeAndFlush( eq( new BeginMessage( bookmark, txConfig, defaultDatabase(), WRITE, null ) ), any( BeginTxResponseHandler.class ) ); + verify( connection ).writeAndFlush( eq( new BeginMessage( bookmarks, txConfig, defaultDatabase(), WRITE, null ) ), + any( BeginTxResponseHandler.class ) ); assertNull( await( stage ) ); } @@ -284,28 +287,28 @@ void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse( AccessMode @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse( AccessMode mode ) throws Exception { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ), txConfig, mode ); + testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx65" ) ), txConfig, mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.empty(), TransactionConfig.empty(), mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.emptySet(), TransactionConfig.empty(), mode ); } @ParameterizedTest @EnumSource( AccessMode.class ) void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse( AccessMode mode ) throws Exception { - testFailedRunInAutoCommitTxWithWaitingForResponse( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ), txConfig, mode ); + testFailedRunInAutoCommitTxWithWaitingForResponse( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx163" ) ), txConfig, mode ); } @ParameterizedTest @@ -344,7 +347,7 @@ void databaseNameForAutoCommitTransactions() @Test void shouldSupportDatabaseNameInBeginTransaction() { - CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connectionMock( "foo", protocol ), Collections.emptySet(), TransactionConfig.empty() ); assertDoesNotThrow( () -> await( txStage ) ); } @@ -354,7 +357,7 @@ void shouldNotSupportDatabaseNameForAutoCommitTransactions() { assertDoesNotThrow( () -> protocol.runInAutoCommitTransaction( connectionMock( "foo", protocol ), - new Query( "RETURN 1" ), BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); + new Query( "RETURN 1" ), BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ) ); } private Class expectedMessageFormatType() @@ -362,18 +365,18 @@ private Class expectedMessageFormatType() return MessageFormatV5.class; } - private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testFailedRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to Run message with a failure @@ -381,31 +384,31 @@ private void testFailedRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmar runHandler.onFailure( error ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); Throwable actual = assertThrows( error.getClass(), () -> await( cursorFuture.get().mapSuccessfulRunCompletionAsync() ) ); assertSame( error, actual ); } - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Bookmark bookmark, TransactionConfig config, AccessMode mode ) throws Exception + private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( Set bookmarks, TransactionConfig config, AccessMode mode ) throws Exception { // Given Connection connection = connectionMock( mode, protocol ); - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( bookmark ); + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( bookmarks ); CompletableFuture cursorFuture = - protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult() .toCompletableFuture(); - ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmark, config, mode, defaultDatabase() ); + ResponseHandler runHandler = verifySessionRunInvoked( connection, bookmarks, config, mode, defaultDatabase() ); assertFalse( cursorFuture.isDone() ); // When I response to the run message runHandler.onSuccess( emptyMap() ); // Then - assertEquals( bookmark, bookmarkHolder.getBookmark() ); + assertEquals( bookmarks, bookmarksHolder.getBookmarks() ); assertTrue( cursorFuture.isDone() ); assertNotNull( cursorFuture.get() ); } @@ -451,13 +454,13 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf { // Given Connection connection = connectionMock( mode, protocol ); - Bookmark initialBookmark = InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ); + Set initialBookmarks = Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx987" ) ); CompletionStage cursorStage; if ( autoCommitTx ) { - BookmarkHolder bookmarkHolder = new DefaultBookmarkHolder( initialBookmark ); - cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarkHolder, config, UNLIMITED_FETCH_SIZE ) + BookmarksHolder bookmarksHolder = new DefaultBookmarksHolder( initialBookmarks ); + cursorStage = protocol.runInAutoCommitTransaction( connection, QUERY, bookmarksHolder, config, UNLIMITED_FETCH_SIZE ) .asyncResult(); } else @@ -471,7 +474,7 @@ private void testRunAndWaitForRunResponse( boolean autoCommitTx, TransactionConf assertFalse( cursorFuture.isDone() ); ResponseHandler runResponseHandler = - autoCommitTx ? verifySessionRunInvoked( connection, initialBookmark, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); + autoCommitTx ? verifySessionRunInvoked( connection, initialBookmarks, config, mode, defaultDatabase() ) : verifyTxRunInvoked( connection ); runResponseHandler.onSuccess( emptyMap() ); assertTrue( cursorFuture.isDone() ); @@ -484,19 +487,19 @@ private void testDatabaseNameSupport( boolean autoCommitTx ) if ( autoCommitTx ) { ResultCursorFactory factory = - protocol.runInAutoCommitTransaction( connection, QUERY, BookmarkHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); + protocol.runInAutoCommitTransaction( connection, QUERY, BookmarksHolder.NO_OP, TransactionConfig.empty(), UNLIMITED_FETCH_SIZE ); CompletionStage resultStage = factory.asyncResult(); ResponseHandler runHandler = - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); runHandler.onSuccess( emptyMap() ); await( resultStage ); - verifySessionRunInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifySessionRunInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } else { - CompletionStage txStage = protocol.beginTransaction( connection, InternalBookmark.empty(), TransactionConfig.empty() ); + CompletionStage txStage = protocol.beginTransaction( connection, Collections.emptySet(), TransactionConfig.empty() ); await( txStage ); - verifyBeginInvoked( connection, InternalBookmark.empty(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); + verifyBeginInvoked( connection, Collections.emptySet(), TransactionConfig.empty(), AccessMode.WRITE, database( "foo" ) ); } } @@ -505,7 +508,7 @@ private ResponseHandler verifyTxRunInvoked( Connection connection ) return verifyRunInvoked( connection, RunWithMetadataMessage.unmanagedTxRunMessage( QUERY ) ); } - private ResponseHandler verifySessionRunInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, + private ResponseHandler verifySessionRunInvoked( Connection connection, Set bookmark, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { RunWithMetadataMessage runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( QUERY, config, databaseName, mode, bookmark, null ); @@ -526,10 +529,10 @@ private ResponseHandler verifyRunInvoked( Connection connection, RunWithMetadata return runHandlerCaptor.getValue(); } - private void verifyBeginInvoked( Connection connection, Bookmark bookmark, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) + private void verifyBeginInvoked( Connection connection, Set bookmarks, TransactionConfig config, AccessMode mode, DatabaseName databaseName ) { ArgumentCaptor beginHandlerCaptor = ArgumentCaptor.forClass( ResponseHandler.class ); - BeginMessage beginMessage = new BeginMessage( bookmark, config, databaseName, mode, null ); + BeginMessage beginMessage = new BeginMessage( bookmarks, config, databaseName, mode, null ); verify( connection ).writeAndFlush( eq( beginMessage ), beginHandlerCaptor.capture() ); assertThat( beginHandlerCaptor.getValue(), instanceOf( BeginTxResponseHandler.class ) ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/MessageWriterV5Test.java b/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/MessageWriterV5Test.java index ea233fee4c..7fd96d1e6a 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/MessageWriterV5Test.java +++ b/driver/src/test/java/org/neo4j/driver/internal/messaging/v5/MessageWriterV5Test.java @@ -102,26 +102,28 @@ protected Stream supportedMessages() // Bolt V3 messages new HelloMessage( "MyDriver/1.2.3", ((InternalAuthToken) basic( "neo4j", "neo4j" )).toMap(), Collections.emptyMap() ), GOODBYE, - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), READ, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), READ, defaultDatabase(), null ), - new BeginMessage( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), WRITE, + new BeginMessage( Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx123" ) ), ofSeconds( 5 ), + singletonMap( "key", value( 42 ) ), WRITE, database( "foo" ), null ), COMMIT, ROLLBACK, RESET, autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), defaultDatabase(), READ, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), autoCommitTxRunMessage( new Query( "RETURN 1" ), ofSeconds( 5 ), singletonMap( "key", value( 42 ) ), database( "foo" ), WRITE, - InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ), null ), + Collections.singleton( InternalBookmark.parse( "neo4j:bookmark:v1:tx1" ) ), null ), unmanagedTxRunMessage( new Query( "RETURN 1" ) ), // Bolt V3 messages with struct values autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), - defaultDatabase(), READ, InternalBookmark.empty(), null ), + defaultDatabase(), READ, Collections.emptySet(), null ), autoCommitTxRunMessage( new Query( "RETURN $x", singletonMap( "x", value( ZonedDateTime.now() ) ) ), ofSeconds( 1 ), emptyMap(), database( "foo" ), - WRITE, InternalBookmark.empty(), null ), + WRITE, Collections.emptySet(), null ), unmanagedTxRunMessage( new Query( "RETURN $x", singletonMap( "x", point( 42, 1, 2, 3 ) ) ) ), // New 4.3 Messages @@ -143,6 +145,6 @@ private RouteMessage routeMessage() { Map routeContext = new HashMap<>(); routeContext.put( "someContext", Values.value( 124 ) ); - return new RouteMessage( routeContext, InternalBookmark.empty(), "dbName", null ); + return new RouteMessage( routeContext, Collections.emptySet(), "dbName", null ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java index 27fa738335..2f1acf9a4e 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java @@ -258,7 +258,22 @@ void shouldDelegateBookmark() rxSession.lastBookmark(); // Then - verify( session ).lastBookmark(); + verify( session ).lastBookmarks(); + verifyNoMoreInteractions( session ); + } + + @Test + void shouldDelegateBookmarks() + { + // Given + NetworkSession session = mock( NetworkSession.class ); + InternalRxSession rxSession = new InternalRxSession( session ); + + // When + rxSession.lastBookmarks(); + + // Then + verify( session ).lastBookmarks(); verifyNoMoreInteractions( session ); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java index c0ef7e7483..8af94aaec0 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java @@ -289,7 +289,22 @@ void shouldDelegateBookmark() rxSession.lastBookmark(); // Then - verify( session ).lastBookmark(); + verify( session ).lastBookmarks(); + verifyNoMoreInteractions( session ); + } + + @Test + void shouldDelegateBookmarks() + { + // Given + NetworkSession session = mock( NetworkSession.class ); + InternalRxSession rxSession = new InternalRxSession( session ); + + // When + rxSession.lastBookmarks(); + + // Then + verify( session ).lastBookmarks(); verifyNoMoreInteractions( session ); } diff --git a/driver/src/test/java/org/neo4j/driver/util/SessionExtension.java b/driver/src/test/java/org/neo4j/driver/util/SessionExtension.java index f0d94b968d..bedb79b84e 100644 --- a/driver/src/test/java/org/neo4j/driver/util/SessionExtension.java +++ b/driver/src/test/java/org/neo4j/driver/util/SessionExtension.java @@ -22,7 +22,11 @@ import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; +import java.util.Collections; +import java.util.HashSet; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; @@ -125,6 +129,26 @@ public Bookmark lastBookmark() return realSession.lastBookmark(); } + @Override + public Set lastBookmarks() + { + Bookmark bookmark = lastBookmark(); + if ( bookmark == null || bookmark.isEmpty() ) + { + return Collections.emptySet(); + } + else if ( bookmark.values().size() == 1 ) + { + return Collections.singleton( bookmark ); + } + else + { + return bookmark.values().stream() + .map( Bookmark::from ) + .collect( Collectors.toCollection( HashSet::new ) ); + } + } + @Override public Result run( String query, Map parameters ) { @@ -132,9 +156,9 @@ public Result run( String query, Map parameters ) } @Override - public Result run(String query, Value parameters ) + public Result run( String query, Value parameters ) { - return realSession.run(query, parameters ); + return realSession.run( query, parameters ); } @Override diff --git a/driver/src/test/java/org/neo4j/driver/util/TestUtil.java b/driver/src/test/java/org/neo4j/driver/util/TestUtil.java index 00390b3a50..021bd6561f 100644 --- a/driver/src/test/java/org/neo4j/driver/util/TestUtil.java +++ b/driver/src/test/java/org/neo4j/driver/util/TestUtil.java @@ -37,6 +37,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; @@ -58,7 +59,7 @@ import org.neo4j.driver.SessionConfig; import org.neo4j.driver.exceptions.ServiceUnavailableException; import org.neo4j.driver.internal.BoltServerAddress; -import org.neo4j.driver.internal.DefaultBookmarkHolder; +import org.neo4j.driver.internal.DefaultBookmarksHolder; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.connection.EventLoopGroupFactory; import org.neo4j.driver.internal.handlers.BeginTxResponseHandler; @@ -101,7 +102,6 @@ import static org.neo4j.driver.SessionConfig.forDatabase; import static org.neo4j.driver.internal.DatabaseNameUtil.database; import static org.neo4j.driver.internal.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.InternalBookmark.empty; import static org.neo4j.driver.internal.handlers.pulln.FetchSizeUtil.UNLIMITED_FETCH_SIZE; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; import static org.neo4j.driver.internal.util.Futures.completedWithNull; @@ -282,35 +282,35 @@ public static boolean databaseExists( Driver driver, String database ) } } - public static NetworkSession newSession( ConnectionProvider connectionProvider, Bookmark x ) + public static NetworkSession newSession( ConnectionProvider connectionProvider, Set bookmarks ) { - return newSession( connectionProvider, WRITE, x ); + return newSession( connectionProvider, WRITE, bookmarks ); } - private static NetworkSession newSession( ConnectionProvider connectionProvider, AccessMode mode, Bookmark x ) + private static NetworkSession newSession( ConnectionProvider connectionProvider, AccessMode mode, Set bookmarks ) { - return newSession( connectionProvider, mode, new FixedRetryLogic( 0 ), x ); + return newSession( connectionProvider, mode, new FixedRetryLogic( 0 ), bookmarks ); } public static NetworkSession newSession( ConnectionProvider connectionProvider, AccessMode mode ) { - return newSession( connectionProvider, mode, empty() ); + return newSession( connectionProvider, mode, Collections.emptySet() ); } public static NetworkSession newSession( ConnectionProvider connectionProvider, RetryLogic logic ) { - return newSession( connectionProvider, WRITE, logic, empty() ); + return newSession( connectionProvider, WRITE, logic, Collections.emptySet() ); } public static NetworkSession newSession( ConnectionProvider connectionProvider ) { - return newSession( connectionProvider, WRITE, empty() ); + return newSession( connectionProvider, WRITE, Collections.emptySet() ); } public static NetworkSession newSession( ConnectionProvider connectionProvider, AccessMode mode, - RetryLogic retryLogic, Bookmark bookmark ) + RetryLogic retryLogic, Set bookmarks ) { - return new NetworkSession( connectionProvider, retryLogic, defaultDatabase(), mode, new DefaultBookmarkHolder( bookmark ), null, UNLIMITED_FETCH_SIZE, + return new NetworkSession( connectionProvider, retryLogic, defaultDatabase(), mode, new DefaultBookmarksHolder( bookmarks ), null, UNLIMITED_FETCH_SIZE, DEV_NULL_LOGGING ); } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/channel/handler/TestkitRequestResponseMapperHandler.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/channel/handler/TestkitRequestResponseMapperHandler.java index d599257a76..28814d4f87 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/channel/handler/TestkitRequestResponseMapperHandler.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/channel/handler/TestkitRequestResponseMapperHandler.java @@ -36,6 +36,7 @@ public class TestkitRequestResponseMapperHandler extends ChannelDuplexHandler public void channelRead( ChannelHandlerContext ctx, Object msg ) { String testkitMessage = (String) msg; + System.out.println( testkitMessage ); TestkitRequest testkitRequest; try { @@ -53,6 +54,7 @@ public void write( ChannelHandlerContext ctx, Object msg, ChannelPromise promise { TestkitResponse testkitResponse = (TestkitResponse) msg; String responseStr = objectMapper.writeValueAsString( testkitResponse ); + System.out.println( responseStr ); ctx.writeAndFlush( responseStr, promise ); } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/TestkitModule.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/TestkitModule.java index 47f9a7fb44..200dee049b 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/TestkitModule.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/TestkitModule.java @@ -20,7 +20,6 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import neo4j.org.testkit.backend.messages.requests.deserializer.TestkitListDeserializer; -import neo4j.org.testkit.backend.messages.responses.serializer.TestkitBookmarkSerializer; import neo4j.org.testkit.backend.messages.responses.serializer.TestkitListValueSerializer; import neo4j.org.testkit.backend.messages.responses.serializer.TestkitMapValueSerializer; import neo4j.org.testkit.backend.messages.responses.serializer.TestkitNodeValueSerializer; @@ -31,7 +30,6 @@ import java.util.List; -import org.neo4j.driver.Bookmark; import org.neo4j.driver.Record; import org.neo4j.driver.Value; import org.neo4j.driver.internal.value.ListValue; @@ -51,7 +49,6 @@ public TestkitModule() this.addSerializer( ListValue.class, new TestkitListValueSerializer() ); this.addSerializer( Record.class, new TestkitRecordSerializer() ); this.addSerializer( MapValue.class, new TestkitMapValueSerializer() ); - this.addSerializer( Bookmark.class, new TestkitBookmarkSerializer() ); this.addSerializer( PathValue.class, new TestkitPathValueSerializer() ); this.addSerializer( RelationshipValue.class, new TestkitRelationshipValueSerializer() ); } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/SessionLastBookmarks.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/SessionLastBookmarks.java index b3709e5e8f..6f9824836c 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/SessionLastBookmarks.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/SessionLastBookmarks.java @@ -26,7 +26,9 @@ import neo4j.org.testkit.backend.messages.responses.TestkitResponse; import reactor.core.publisher.Mono; +import java.util.Set; import java.util.concurrent.CompletionStage; +import java.util.stream.Collectors; import org.neo4j.driver.Bookmark; @@ -40,15 +42,14 @@ public class SessionLastBookmarks implements TestkitRequest public TestkitResponse process( TestkitState testkitState ) { SessionHolder sessionHolder = testkitState.getSessionHolder( data.getSessionId() ); - Bookmark bookmark = sessionHolder.getSession().lastBookmark(); - return createResponse( bookmark ); + return createResponse( sessionHolder.getSession().lastBookmarks() ); } @Override public CompletionStage processAsync( TestkitState testkitState ) { return testkitState.getAsyncSessionHolder( data.getSessionId() ) - .thenApply( sessionHolder -> sessionHolder.getSession().lastBookmark() ) + .thenApply( sessionHolder -> sessionHolder.getSession().lastBookmarks() ) .thenApply( this::createResponse ); } @@ -57,6 +58,7 @@ public Mono processRx( TestkitState testkitState ) { return testkitState.getRxSessionHolder( data.getSessionId() ) .map( sessionHolder -> sessionHolder.getSession().lastBookmark() ) + .map( bookmark -> bookmark.values().stream().map( Bookmark::from ).collect( Collectors.toSet() ) ) .map( this::createResponse ); } @@ -64,13 +66,17 @@ public Mono processRx( TestkitState testkitState ) public Mono processReactive( TestkitState testkitState ) { return testkitState.getReactiveSessionHolder( data.getSessionId() ) - .map( sessionHolder -> sessionHolder.getSession().lastBookmark() ) + .map( sessionHolder -> sessionHolder.getSession().lastBookmarks() ) .map( this::createResponse ); } - private Bookmarks createResponse( Bookmark bookmark ) + private Bookmarks createResponse( Set bookmarks ) { - return Bookmarks.builder().data( Bookmarks.BookmarksBody.builder().bookmarks( bookmark ).build() ).build(); + return Bookmarks.builder() + .data( Bookmarks.BookmarksBody.builder() + .bookmarks( bookmarks.stream().map( Bookmark::value ).collect( Collectors.toSet() ) ) + .build() ) + .build(); } @Setter diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/Bookmarks.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/Bookmarks.java index 2492aa25a7..7e4adc86f6 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/Bookmarks.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/Bookmarks.java @@ -21,7 +21,7 @@ import lombok.Builder; import lombok.Getter; -import org.neo4j.driver.Bookmark; +import java.util.Set; @Getter @Builder @@ -39,6 +39,6 @@ public String testkitName() @Builder public static class BookmarksBody { - private Bookmark bookmarks; + private Set bookmarks; } } diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/serializer/TestkitBookmarkSerializer.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/serializer/TestkitBookmarkSerializer.java deleted file mode 100644 index a786a22462..0000000000 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/serializer/TestkitBookmarkSerializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.serializer; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; - -import java.io.IOException; -import java.util.Set; - -import org.neo4j.driver.Bookmark; - -public class TestkitBookmarkSerializer extends StdSerializer -{ - public TestkitBookmarkSerializer() - { - super( Bookmark.class ); - } - - @Override - public void serialize( Bookmark value, JsonGenerator gen, SerializerProvider provider ) throws IOException - { - gen.writeStartArray(); - - Set bookmarks = value.values(); - - for ( String bm : bookmarks ) - { - gen.writeString( bm ); - } - - gen.writeEndArray(); - } -}