Skip to content

Commit aa2ea68

Browse files
author
Zhen
committed
Fix the bug where the tx is not rolled back if the result is not consumed
1 parent 13294cd commit aa2ea68

File tree

3 files changed

+102
-8
lines changed

3 files changed

+102
-8
lines changed

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,23 @@ public void close()
122122
{
123123
if ( state == State.MARKED_SUCCESS )
124124
{
125-
conn.run( "COMMIT", Collections.<String, Value>emptyMap(), Collector.NO_OP );
126-
conn.pullAll( new BookmarkCollector( this ) );
127-
conn.sync();
128-
state = State.SUCCEEDED;
125+
try
126+
{
127+
conn.run( "COMMIT", Collections.<String,Value>emptyMap(), Collector.NO_OP );
128+
conn.pullAll( new BookmarkCollector( this ) );
129+
conn.sync();
130+
state = State.SUCCEEDED;
131+
}
132+
catch( Throwable e )
133+
{
134+
// failed to commit
135+
rollbackTx();
136+
throw e;
137+
}
129138
}
130139
else if ( state == State.MARKED_FAILED || state == State.ACTIVE )
131140
{
132-
conn.run( "ROLLBACK", Collections.<String, Value>emptyMap(), Collector.NO_OP );
133-
conn.pullAll( new BookmarkCollector( this ) );
134-
conn.sync();
135-
state = State.ROLLED_BACK;
141+
rollbackTx();
136142
}
137143
}
138144
}
@@ -142,6 +148,14 @@ else if ( state == State.MARKED_FAILED || state == State.ACTIVE )
142148
}
143149
}
144150

151+
private void rollbackTx()
152+
{
153+
conn.run( "ROLLBACK", Collections.<String, Value>emptyMap(), Collector.NO_OP );
154+
conn.pullAll( new BookmarkCollector( this ) );
155+
conn.sync();
156+
state = State.ROLLED_BACK;
157+
}
158+
145159
@Override
146160
@SuppressWarnings( "unchecked" )
147161
public StatementResult run( String statementText, Value statementParameters )

driver/src/test/java/org/neo4j/driver/v1/integration/SessionIT.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,28 @@ public void shouldMarkTxAsFailedAndDisallowRunAfterSessionReset()
360360
}
361361
}
362362

363+
@Test
364+
public void shouldAllowMoreTxAfterSessionResetInTx()
365+
{
366+
// Given
367+
try( Driver driver = GraphDatabase.driver( neo4j.uri() );
368+
Session session = driver.session() )
369+
{
370+
try( Transaction tx = session.beginTransaction() )
371+
{
372+
// When reset the state of this session
373+
session.reset();
374+
}
375+
376+
// Then can run more Tx
377+
try( Transaction tx = session.beginTransaction() )
378+
{
379+
tx.run("Return 2");
380+
tx.success();
381+
}
382+
}
383+
}
384+
363385
@Test
364386
public void shouldCloseSessionWhenDriverIsClosed() throws Throwable
365387
{

driver/src/test/java/org/neo4j/driver/v1/integration/TransactionIT.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.neo4j.driver.v1.integration;
2020

21+
import org.junit.Assert;
2122
import org.junit.Rule;
2223
import org.junit.Test;
2324
import org.junit.rules.ExpectedException;
@@ -38,6 +39,7 @@
3839
import static org.hamcrest.MatcherAssert.assertThat;
3940
import static org.junit.Assert.assertFalse;
4041
import static org.junit.Assert.assertTrue;
42+
import static org.junit.Assert.fail;
4143

4244
public class TransactionIT
4345
{
@@ -303,4 +305,60 @@ public void run()
303305
long nodes = result.single().get( "count(n)" ).asLong();
304306
assertThat( nodes, equalTo( 1L ) );
305307
}
308+
309+
@Test
310+
public void shouldRollBackTxIfErrorWithoutConsume() throws Throwable
311+
{
312+
// Given
313+
int failingPos = 0;
314+
try ( Transaction tx = session.beginTransaction() )
315+
{
316+
StatementResult result = tx.run( "invalid" ); // send run, pull_all
317+
tx.success();
318+
failingPos = 1; // fail to send?
319+
} // When send run_commit, and pull_all
320+
321+
// Then error and should also send ack_fail, roll_back and pull_all
322+
catch ( ClientException e )
323+
{
324+
failingPos = 2; // fail in tx.close in sync?
325+
try ( Transaction tx = session.beginTransaction() )
326+
{
327+
StatementResult cursor = tx.run( "RETURN 1" );
328+
int val = cursor.single().get( "1" ).asInt();
329+
330+
331+
assertThat( val, equalTo( 1 ) );
332+
}
333+
}
334+
assertThat( failingPos, equalTo( 2 ) );
335+
}
336+
337+
@Test
338+
public void shouldRollBackTxIfErrorWithConsume() throws Throwable
339+
{
340+
341+
// Given
342+
try ( Transaction tx = session.beginTransaction() )
343+
{
344+
StatementResult result = tx.run( "invalid" );
345+
tx.success();
346+
347+
// When
348+
result.consume(); // run, pull_all
349+
fail( "Should fail tx due to syntax error" );
350+
} // ack_fail, roll_back, pull_all
351+
// Then
352+
catch ( ClientException e )
353+
{
354+
try ( Transaction tx = session.beginTransaction() )
355+
{
356+
StatementResult cursor = tx.run( "RETURN 1" );
357+
int val = cursor.single().get( "1" ).asInt();
358+
359+
Assert.assertThat( val, equalTo( 1 ) );
360+
}
361+
}
362+
363+
}
306364
}

0 commit comments

Comments
 (0)