Skip to content

Commit 3abf925

Browse files
committed
Bookmark in BEGIN
1 parent eb4087e commit 3abf925

File tree

5 files changed

+92
-42
lines changed

5 files changed

+92
-42
lines changed

driver/src/main/java/org/neo4j/driver/internal/InternalTransaction.java renamed to driver/src/main/java/org/neo4j/driver/internal/ExplicitTransaction.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@
3434
import org.neo4j.driver.v1.exceptions.Neo4jException;
3535
import org.neo4j.driver.v1.types.TypeSystem;
3636

37+
import static java.util.Collections.emptyMap;
38+
import static java.util.Collections.singletonMap;
39+
3740
import static org.neo4j.driver.v1.Values.ofValue;
3841
import static org.neo4j.driver.v1.Values.value;
3942

40-
public class InternalTransaction implements Transaction
43+
class ExplicitTransaction implements Transaction
4144
{
4245
private enum State
4346
{
@@ -68,13 +71,26 @@ private enum State
6871

6972
private State state = State.ACTIVE;
7073

71-
public InternalTransaction( Connection conn, Runnable cleanup )
74+
ExplicitTransaction( Connection conn, Runnable cleanup )
75+
{
76+
this( conn, cleanup, null );
77+
}
78+
79+
ExplicitTransaction( Connection conn, Runnable cleanup, String bookmark )
7280
{
7381
this.conn = conn;
7482
this.cleanup = cleanup;
7583

76-
// Note there is no sync here, so this will just value queued locally
77-
conn.run( "BEGIN", Collections.<String, Value>emptyMap(), StreamCollector.NO_OP );
84+
final Map<String, Value> parameters;
85+
if ( bookmark == null )
86+
{
87+
parameters = emptyMap();
88+
}
89+
else
90+
{
91+
parameters = singletonMap( "bookmark", value( bookmark ) );
92+
}
93+
conn.run( "BEGIN", parameters, StreamCollector.NO_OP );
7894
conn.discardAll();
7995
}
8096

driver/src/main/java/org/neo4j/driver/internal/InternalSession.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void run()
5252
}
5353
};
5454

55-
private InternalTransaction currentTransaction;
55+
private ExplicitTransaction currentTransaction;
5656
private AtomicBoolean isOpen = new AtomicBoolean( true );
5757

5858
public InternalSession( Connection connection, Logger logger )
@@ -152,17 +152,24 @@ public String server()
152152

153153
@Override
154154
public Transaction beginTransaction()
155+
{
156+
return beginTransaction( null );
157+
}
158+
159+
@Override
160+
public Transaction beginTransaction( String bookmark )
155161
{
156162
ensureConnectionIsValidBeforeOpeningTransaction();
157-
currentTransaction = new InternalTransaction( connection, txCleanup );
158-
connection.onError( new Runnable() {
163+
currentTransaction = new ExplicitTransaction( connection, txCleanup, bookmark );
164+
connection.onError( new Runnable()
165+
{
159166
@Override
160167
public void run()
161168
{
162-
//must check if transaction has been closed
163-
if (currentTransaction != null)
169+
// must check if transaction has been closed
170+
if ( currentTransaction != null )
164171
{
165-
if( connection.hasUnrecoverableErrors() )
172+
if ( connection.hasUnrecoverableErrors() )
166173
{
167174
currentTransaction.markToClose();
168175
}
@@ -172,7 +179,7 @@ public void run()
172179
}
173180
}
174181
}
175-
});
182+
} );
176183
return currentTransaction;
177184
}
178185

driver/src/main/java/org/neo4j/driver/v1/Session.java

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,57 @@
11
/**
22
* Copyright (c) 2002-2016 "Neo Technology,"
33
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4-
*
4+
* <p>
55
* This file is part of Neo4j.
6-
*
6+
* <p>
77
* Licensed under the Apache License, Version 2.0 (the "License");
88
* you may not use this file except in compliance with the License.
99
* You may obtain a copy of the License at
10-
*
11-
* http://www.apache.org/licenses/LICENSE-2.0
12-
*
10+
* <p>
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
* <p>
1313
* Unless required by applicable law or agreed to in writing, software
1414
* distributed under the License is distributed on an "AS IS" BASIS,
1515
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1616
* See the License for the specific language governing permissions and
1717
* limitations under the License.
1818
*/
19+
1920
package org.neo4j.driver.v1;
2021

2122
import org.neo4j.driver.v1.util.Resource;
2223

2324
/**
24-
* A live session with a Neo4j instance.
25+
* A <em>Session</em> hosts a series of {@linkplain Transaction transactions}
26+
* carried out against a database. Within the database, all statements are
27+
* carried out within a transaction. Within application code, however, it is
28+
* not always necessary to explicitly {@link #beginTransaction() begin a
29+
* transaction}. If a statement is {@link #run} directly against a {@link
30+
* Session}, the server will automatically <code>BEGIN</code> and
31+
* <code>COMMIT</code> that statement within its own transaction. This type
32+
* of transaction is known as an <em>autocommit transaction</em>.
2533
* <p>
26-
* Sessions serve two purposes. For one, they are an optimization. By keeping state on the database side, we can
27-
* avoid re-transmitting certain metadata over and over.
34+
* Explicit transactions allow multiple statements to be committed as part of
35+
* a single atomic operation and can be rolled back if necessary. They can also
36+
* be used to ensure <em>causal consistency</em>, meaning that an application
37+
* can run a series of queries on different members of a cluster, while
38+
* ensuring that each query sees the state of graph at least as up-to-date as
39+
* the graph seen by the previous query. For more on causal consistency, see
40+
* the Neo4j clustering manual.
2841
* <p>
29-
* Sessions also serve a role in transaction isolation and ordering semantics. Neo4j requires
30-
* "sticky sessions", meaning all requests within one session must always go to the same Neo4j instance.
42+
* Typically, a session will wrap a TCP connection. Such a connection will be
43+
* acquired from a connection pool and released back there when the session is
44+
* destroyed. One connection can therefore be adopted by many sessions,
45+
* although by only one at a time. Application code should never need to deal
46+
* directly with connection management.
3147
* <p>
32-
* Session objects are not thread safe, if you want to run concurrent operations against the database,
33-
* simply create multiple sessions objects.
34-
*
35-
* <h2>Important note on semantics</h2>
36-
*
37-
* Please see the section under {@link StatementRunner} for an important overview of the guarantees
38-
* the session gives you around when statements are executed.
48+
* A session inherits its destination address and permissions from its
49+
* underlying connection. This means that one session may only ever target one
50+
* machine within a cluster and does not support re-authentication. To achieve
51+
* otherwise requires creation of a separate session.
52+
* <p>
53+
* Similarly, multiple sessions should be used when working with concurrency;
54+
* session implementations are generally not thread safe.
3955
*
4056
* @since 1.0
4157
*/
@@ -44,20 +60,25 @@ public interface Session extends Resource, StatementRunner
4460
String LOG_NAME = "session";
4561

4662
/**
47-
* Begin a new transaction in this session. A session can have at most one transaction running at a time, if you
48-
* want to run multiple concurrent transactions, you should use multiple concurrent sessions.
49-
* <p>
50-
* All data operations in Neo4j are transactional. However, for convenience we provide a {@link #run(String)}
51-
* method directly on this session interface as well. When you use that method, your statement automatically gets
52-
* wrapped in a transaction.
53-
* <p>
54-
* If you want to run multiple statements in the same transaction, you should wrap them in a transaction using this
55-
* method.
63+
* Begin a new <em>explicit {@linkplain Transaction transaction}</em>. At
64+
* most one transaction may exist in a session at any point in time. To
65+
* maintain multiple concurrent transactions, use multiple concurrent
66+
* sessions.
5667
*
57-
* @return a new transaction
68+
* @return a new {@link Transaction}
5869
*/
5970
Transaction beginTransaction();
6071

72+
/**
73+
* Begin a new <em>explicit {@linkplain Transaction transaction}</em>,
74+
* requiring that the server hosting is at least as up-to-date as the
75+
* transaction referenced by the supplied <em>bookmark</em>.
76+
*
77+
* @param bookmark a reference to a previous transaction
78+
* @return a new {@link Transaction}
79+
*/
80+
Transaction beginTransaction( String bookmark );
81+
6182
/**
6283
* Reset the current session. This sends an immediate RESET signal to the server which both interrupts
6384
* any statement that is currently executing and ignores any subsequently queued statements. Following

driver/src/test/java/org/neo4j/driver/internal/InternalTransactionTest.java renamed to driver/src/test/java/org/neo4j/driver/internal/ExplicitTransactionTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import static org.mockito.Mockito.verifyNoMoreInteractions;
3434
import static org.mockito.Mockito.when;
3535

36-
public class InternalTransactionTest
36+
public class ExplicitTransactionTest
3737
{
3838
@Test
3939
public void shouldRollbackOnImplicitFailure() throws Throwable
@@ -42,7 +42,7 @@ public void shouldRollbackOnImplicitFailure() throws Throwable
4242
Connection conn = mock( Connection.class );
4343
when( conn.isOpen() ).thenReturn( true );
4444
Runnable cleanup = mock( Runnable.class );
45-
InternalTransaction tx = new InternalTransaction( conn, cleanup );
45+
ExplicitTransaction tx = new ExplicitTransaction( conn, cleanup );
4646

4747
// When
4848
tx.close();
@@ -66,7 +66,7 @@ public void shouldRollbackOnExplicitFailure() throws Throwable
6666
Connection conn = mock( Connection.class );
6767
when( conn.isOpen() ).thenReturn( true );
6868
Runnable cleanup = mock( Runnable.class );
69-
InternalTransaction tx = new InternalTransaction( conn, cleanup );
69+
ExplicitTransaction tx = new ExplicitTransaction( conn, cleanup );
7070

7171
// When
7272
tx.failure();
@@ -92,7 +92,7 @@ public void shouldCommitOnSuccess() throws Throwable
9292
Connection conn = mock( Connection.class );
9393
when( conn.isOpen() ).thenReturn( true );
9494
Runnable cleanup = mock( Runnable.class );
95-
InternalTransaction tx = new InternalTransaction( conn, cleanup );
95+
ExplicitTransaction tx = new ExplicitTransaction( conn, cleanup );
9696

9797
// When
9898
tx.success();

driver/src/test/java/org/neo4j/driver/v1/util/TestNeo4jSession.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ public Transaction beginTransaction()
106106
return realSession.beginTransaction();
107107
}
108108

109+
@Override
110+
public Transaction beginTransaction( String bookmark )
111+
{
112+
return realSession.beginTransaction( bookmark );
113+
}
114+
109115
@Override
110116
public void reset()
111117
{

0 commit comments

Comments
 (0)