Skip to content

Add an async enabled transaction synchronization #1864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions src/NHibernate.Test/Async/NHSpecificTest/NH1082/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@


using System;
using NHibernate.Cfg;
using NUnit.Framework;
using Environment = NHibernate.Cfg.Environment;

namespace NHibernate.Test.NHSpecificTest.NH1082
{
Expand Down Expand Up @@ -40,8 +38,31 @@ public async Task ExceptionsInBeforeTransactionCompletionAbortTransactionAsync()
}
}


[Test]
public async Task ExceptionsInTransactionSynchronizationBeforeTransactionCompletionAbortTransactionAsync()
{
var c = new C { ID = 1, Value = "value" };

var synchronization = new TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion();
using (ISession s = Sfi.OpenSession())
using (ITransaction t = s.BeginTransaction())
{
t.RegisterSynchronization(synchronization);

await (s.SaveAsync(c));

Assert.ThrowsAsync<BadException>(() => t.CommitAsync());
}

using (ISession s = Sfi.OpenSession())
{
var objectInDb = await (s.GetAsync<C>(1));
Assert.IsNull(objectInDb);
}
}

// Since v5.2
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not written 5.3 but 5.2, in case we merge this in it.

[Test, Obsolete]
public async Task ExceptionsInSynchronizationBeforeTransactionCompletionAbortTransactionAsync()
{
var c = new C { ID = 1, Value = "value" };
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using NHibernate.Transaction;

namespace NHibernate.Test.NHSpecificTest.NH1082
{
using System.Threading.Tasks;
using System.Threading;
public partial class TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion : ITransactionCompletionSynchronization
{
public Task ExecuteBeforeTransactionCompletionAsync(CancellationToken cancellationToken)
{
throw new BadException();
}

public Task ExecuteAfterTransactionCompletionAsync(bool success, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@


using System;
using System.Collections;
using System.Data;
using System.Data.Common;
using NHibernate.Transaction;
using NUnit.Framework;

namespace NHibernate.Test.TransactionTest
Expand All @@ -20,22 +21,23 @@ namespace NHibernate.Test.TransactionTest
[TestFixture]
public class TransactionNotificationFixtureAsync : TestCase
{
protected override string[] Mappings
{
get { return Array.Empty<string>(); }
}
protected override string[] Mappings => Array.Empty<string>();

[Test]
public async Task CommitAsync()
{
var interceptor = new RecordingInterceptor();
using (var session = Sfi.WithOptions().Interceptor(interceptor).OpenSession())
using (var tx = session.BeginTransaction())
{
ITransaction tx = session.BeginTransaction();
var synchronisation = new Synchronization();
tx.RegisterSynchronization(synchronisation);
await (tx.CommitAsync());
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1));
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(1));
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1), "interceptor begin");
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(1), "interceptor before");
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor after");
Assert.That(synchronisation.BeforeExecutions, Is.EqualTo(1), "sync before");
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync after");
}
}

Expand All @@ -44,26 +46,31 @@ public async Task RollbackAsync()
{
var interceptor = new RecordingInterceptor();
using (var session = Sfi.WithOptions().Interceptor(interceptor).OpenSession())
using (var tx = session.BeginTransaction())
{
ITransaction tx = session.BeginTransaction();
var synchronisation = new Synchronization();
tx.RegisterSynchronization(synchronisation);
await (tx.RollbackAsync());
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1));
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(0));
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1), "interceptor begin");
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(0), "interceptor before");
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor after");
Assert.That(synchronisation.BeforeExecutions, Is.EqualTo(0), "sync before");
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync after");
}
}


[Theory]
[Description("NH2128")]
public async Task ShouldNotifyAfterTransactionAsync(bool usePrematureClose)
{
var interceptor = new RecordingInterceptor();
var synchronisation = new Synchronization();
ISession s;

using (s = OpenSession(interceptor))
using (s.BeginTransaction())
using (var t = s.BeginTransaction())
{
t.RegisterSynchronization(synchronisation);
await (s.CreateCriteria<object>().ListAsync());

// Call session close while still inside transaction?
Expand All @@ -72,22 +79,24 @@ public async Task ShouldNotifyAfterTransactionAsync(bool usePrematureClose)
}

Assert.That(s.IsOpen, Is.False);
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor");
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync");
}


[Description("NH2128")]
[Theory]
public async Task ShouldNotifyAfterTransactionWithOwnConnectionAsync(bool usePrematureClose)
{
var interceptor = new RecordingInterceptor();
var synchronisation = new Synchronization();
ISession s;

using (var ownConnection = await (Sfi.ConnectionProvider.GetConnectionAsync(CancellationToken.None)))
{
using (s = Sfi.WithOptions().Connection(ownConnection).Interceptor(interceptor).OpenSession())
using (s.BeginTransaction())
using (var t = s.BeginTransaction())
{
t.RegisterSynchronization(synchronisation);
await (s.CreateCriteria<object>().ListAsync());

// Call session close while still inside transaction?
Expand All @@ -97,7 +106,56 @@ public async Task ShouldNotifyAfterTransactionWithOwnConnectionAsync(bool usePre
}

Assert.That(s.IsOpen, Is.False);
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor");
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync");
}
}

#region Synchronization classes

public partial class CustomTransaction : ITransaction
{

public Task CommitAsync(CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
}

public Task RollbackAsync(CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotImplementedException();
}
}

public partial class Synchronization : ITransactionCompletionSynchronization
{

public Task ExecuteBeforeTransactionCompletionAsync(CancellationToken cancellationToken)
{
try
{
BeforeExecutions += 1;
return Task.CompletedTask;
}
catch (Exception ex)
{
return Task.FromException<object>(ex);
}
}

public Task ExecuteAfterTransactionCompletionAsync(bool success, CancellationToken cancellationToken)
{
try
{
AfterExecutions += 1;
return Task.CompletedTask;
}
catch (Exception ex)
{
return Task.FromException<object>(ex);
}
}
}

#endregion
}
27 changes: 24 additions & 3 deletions src/NHibernate.Test/NHSpecificTest/NH1082/Fixture.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using NHibernate.Cfg;
using NUnit.Framework;
using Environment = NHibernate.Cfg.Environment;

namespace NHibernate.Test.NHSpecificTest.NH1082
{
Expand Down Expand Up @@ -29,8 +27,31 @@ public void ExceptionsInBeforeTransactionCompletionAbortTransaction()
}
}


[Test]
public void ExceptionsInTransactionSynchronizationBeforeTransactionCompletionAbortTransaction()
{
var c = new C { ID = 1, Value = "value" };

var synchronization = new TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion();
using (ISession s = Sfi.OpenSession())
using (ITransaction t = s.BeginTransaction())
{
t.RegisterSynchronization(synchronization);

s.Save(c);

Assert.Throws<BadException>(t.Commit);
}

using (ISession s = Sfi.OpenSession())
{
var objectInDb = s.Get<C>(1);
Assert.IsNull(objectInDb);
}
}

// Since v5.2
[Test, Obsolete]
public void ExceptionsInSynchronizationBeforeTransactionCompletionAbortTransaction()
{
var c = new C { ID = 1, Value = "value" };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using NHibernate.Transaction;

namespace NHibernate.Test.NHSpecificTest.NH1082
{
// Since v5.2
[Obsolete]
public class SynchronizationThatThrowsExceptionAtBeforeTransactionCompletion : ISynchronization
{
public void BeforeCompletion()
Expand All @@ -13,4 +16,4 @@ public void AfterCompletion(bool success)
{
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using NHibernate.Transaction;

namespace NHibernate.Test.NHSpecificTest.NH1082
{
public partial class TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion : ITransactionCompletionSynchronization
{
public void ExecuteBeforeTransactionCompletion()
{
throw new BadException();
}

public void ExecuteAfterTransactionCompletion(bool success)
{
}
}
}
Loading