Skip to content

Async After-/BeforeTransactionCompletion #1452

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 5 commits into from
Sep 16, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected override void Configure(Configuration configuration)
public async Task SimpleNativeSQLInsert_DoesNotEvictEntireCacheWhenQuerySpacesAreAddedAsync()
{
List<string> clearCalls = new List<string>();
(Sfi.Settings.CacheProvider as SubstituteCacheProvider).OnClear(x =>
((SubstituteCacheProvider) Sfi.Settings.CacheProvider).OnClear(x =>
{
clearCalls.Add(x);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected override void Configure(Configuration configuration)
public void SimpleNativeSQLInsert_DoesNotEvictEntireCacheWhenQuerySpacesAreAdded()
{
List<string> clearCalls = new List<string>();
(Sfi.Settings.CacheProvider as SubstituteCacheProvider).OnClear(x =>
((SubstituteCacheProvider) Sfi.Settings.CacheProvider).OnClear(x =>
{
clearCalls.Add(x);
});
Expand Down
14 changes: 11 additions & 3 deletions src/NHibernate/Action/BulkOperationCleanupAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace NHibernate.Action
/// Implementation of BulkOperationCleanupAction.
/// </summary>
[Serializable]
public partial class BulkOperationCleanupAction : IExecutable, IAfterTransactionCompletionProcess
public partial class BulkOperationCleanupAction : IAsyncExecutable, IAfterTransactionCompletionProcess
{
private readonly ISessionImplementor session;
private readonly HashSet<string> affectedEntityNames = new HashSet<string>();
Expand Down Expand Up @@ -109,9 +109,17 @@ public void Execute()
// nothing to do
}

public IBeforeTransactionCompletionProcess BeforeTransactionCompletionProcess => null;
public BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess =>
null;

public IAfterTransactionCompletionProcess AfterTransactionCompletionProcess => this;
public AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess =>
ExecuteAfterTransactionCompletion;

IBeforeTransactionCompletionProcess IAsyncExecutable.BeforeTransactionCompletionProcess =>
null;

IAfterTransactionCompletionProcess IAsyncExecutable.AfterTransactionCompletionProcess =>
this;

public void ExecuteAfterTransactionCompletion(bool success)
{
Expand Down
15 changes: 11 additions & 4 deletions src/NHibernate/Action/CollectionAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace NHibernate.Action
/// Any action relating to insert/update/delete of a collection
/// </summary>
[Serializable]
public abstract partial class CollectionAction : IExecutable, IComparable<CollectionAction>, IDeserializationCallback, IAfterTransactionCompletionProcess
public abstract partial class CollectionAction : IAsyncExecutable, IComparable<CollectionAction>, IDeserializationCallback, IAfterTransactionCompletionProcess
{
private readonly object key;
private object finalKey;
Expand Down Expand Up @@ -104,10 +104,17 @@ public virtual void BeforeExecutions()
/// <summary>Execute this action</summary>
public abstract void Execute();

public virtual IBeforeTransactionCompletionProcess BeforeTransactionCompletionProcess => null;
IBeforeTransactionCompletionProcess IAsyncExecutable.BeforeTransactionCompletionProcess =>
null;

// Only make sense to add the delegate if there is a cache.
public virtual IAfterTransactionCompletionProcess AfterTransactionCompletionProcess => persister.HasCache ? this : null;
IAfterTransactionCompletionProcess IAsyncExecutable.AfterTransactionCompletionProcess =>
persister.HasCache ? this : null;

public virtual BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess =>
null;

public virtual AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess =>
persister.HasCache ? ExecuteAfterTransactionCompletion : default(AfterTransactionCompletionProcessDelegate);

public virtual void ExecuteAfterTransactionCompletion(bool success)
{
Expand Down
5 changes: 3 additions & 2 deletions src/NHibernate/Action/CollectionUpdateAction.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using NHibernate.Cache;
using NHibernate.Cache.Access;
using NHibernate.Cache.Entry;
using NHibernate.Collection;
using NHibernate.Engine;
Expand All @@ -12,7 +11,7 @@
namespace NHibernate.Action
{
[Serializable]
public sealed partial class CollectionUpdateAction : CollectionAction, IAfterTransactionCompletionProcess
public sealed partial class CollectionUpdateAction : CollectionAction
{
private readonly bool emptySnapshot;

Expand Down Expand Up @@ -116,6 +115,8 @@ private void PostUpdate()

public override void ExecuteAfterTransactionCompletion(bool success)
{
// NH Different behavior: to support unlocking collections from the cache.(r3260)

CacheKey ck = Session.GenerateCacheKey(Key, Persister.KeyType, Persister.Role);

if (success)
Expand Down
41 changes: 27 additions & 14 deletions src/NHibernate/Action/EntityAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ namespace NHibernate.Action
/// instance.
/// </summary>
[Serializable]
public abstract partial class EntityAction : IExecutable, IComparable<EntityAction>, IDeserializationCallback,
public abstract partial class EntityAction :
IAsyncExecutable,
IBeforeTransactionCompletionProcess,
IAfterTransactionCompletionProcess
IAfterTransactionCompletionProcess,
IComparable<EntityAction>,
IDeserializationCallback
{
private readonly string entityName;
private readonly object id;
Expand Down Expand Up @@ -104,12 +107,22 @@ public void BeforeExecutions()

public abstract void Execute();

public virtual IBeforeTransactionCompletionProcess BeforeTransactionCompletionProcess =>
IBeforeTransactionCompletionProcess IAsyncExecutable.BeforeTransactionCompletionProcess =>
NeedsBeforeTransactionCompletion() ? this : null;

public virtual IAfterTransactionCompletionProcess AfterTransactionCompletionProcess =>
IAfterTransactionCompletionProcess IAsyncExecutable.AfterTransactionCompletionProcess =>
NeedsAfterTransactionCompletion() ? this : null;

public virtual BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess =>
NeedsBeforeTransactionCompletion()
? BeforeTransactionCompletionProcessImpl
: default(BeforeTransactionCompletionProcessDelegate);

public virtual AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess =>
NeedsAfterTransactionCompletion()
? AfterTransactionCompletionProcessImpl
: default(AfterTransactionCompletionProcessDelegate);

protected virtual bool NeedsAfterTransactionCompletion()
{
return persister.HasCache || HasPostCommitEventListeners;
Expand All @@ -130,16 +143,6 @@ protected virtual void AfterTransactionCompletionProcessImpl(bool success)
{
}

public void ExecuteBeforeTransactionCompletion()
{
BeforeTransactionCompletionProcessImpl();
}

public void ExecuteAfterTransactionCompletion(bool success)
{
AfterTransactionCompletionProcessImpl(success);
}

#endregion

#region IComparable<EntityAction> Members
Expand Down Expand Up @@ -178,5 +181,15 @@ public override string ToString()
{
return StringHelper.Unqualify(GetType().FullName) + MessageHelper.InfoString(entityName, id);
}

public void ExecuteBeforeTransactionCompletion()
{
BeforeTransactionCompletionProcessImpl();
}

public void ExecuteAfterTransactionCompletion(bool success)
{
AfterTransactionCompletionProcessImpl(success);
}
}
}
3 changes: 3 additions & 0 deletions src/NHibernate/Action/IAfterTransactionCompletionProcess.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace NHibernate.Action
{
/// <summary>
/// Contract representing some process that needs to occur during after transaction completion.
/// </summary>
public partial interface IAfterTransactionCompletionProcess
{
/// <summary>
Expand Down
15 changes: 15 additions & 0 deletions src/NHibernate/Action/IAsyncExecutable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace NHibernate.Action
{
public interface IAsyncExecutable : IExecutable
Copy link
Member

Choose a reason for hiding this comment

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

I would add a // 6.0 TODO: merge into IExecutable. Or is there any value in keeping a separated interface for async methods?

{
/// <summary>
/// Get the before-transaction-completion process, if any, for this action.
/// </summary>
new IBeforeTransactionCompletionProcess BeforeTransactionCompletionProcess { get; }

/// <summary>
/// Get the after-transaction-completion process, if any, for this action.
/// </summary>
new IAfterTransactionCompletionProcess AfterTransactionCompletionProcess { get; }
}
}
3 changes: 3 additions & 0 deletions src/NHibernate/Action/IBeforeTransactionCompletionProcess.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace NHibernate.Action
{
/// <summary>
/// Contract representing some process that needs to occur during before transaction completion.
/// </summary>
public partial interface IBeforeTransactionCompletionProcess
{
/// <summary>
Expand Down
27 changes: 25 additions & 2 deletions src/NHibernate/Action/IExecutable.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
using NHibernate.Engine;

namespace NHibernate.Action
{
/// <summary>
/// Delegate representing some process that needs to occur before transaction completion.
/// </summary>
/// <remarks>
/// NH specific: C# does not support dynamic interface proxies so a delegate is used in
/// place of the Hibernate interface (see Action/BeforeTransactionCompletionProcess). The
/// delegate omits the <see cref="ISessionImplementor" /> parameter as it is not used.
/// </remarks>
public delegate void BeforeTransactionCompletionProcessDelegate();

/// <summary>
/// Delegate representing some process that needs to occur after transaction completion.
/// </summary>
/// <param name="success"> Did the transaction complete successfully? True means it did.</param>
/// <remarks>
/// NH specific: C# does not support dynamic interface proxies so a delegate is used in
/// place of the Hibernate interface (see Action/AfterTransactionCompletionProcess). The
/// delegate omits the <see cref="ISessionImplementor" /> parameter as it is not used.
/// </remarks>
public delegate void AfterTransactionCompletionProcessDelegate(bool success);
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't these delegates be obsoleted?


/// <summary>
/// An operation which may be scheduled for later execution.
/// Usually, the operation is a database insert/update/delete,
Expand All @@ -21,11 +44,11 @@ public partial interface IExecutable
/// <summary>
/// Get the before-transaction-completion process, if any, for this action.
/// </summary>
IBeforeTransactionCompletionProcess BeforeTransactionCompletionProcess { get; }
BeforeTransactionCompletionProcessDelegate BeforeTransactionCompletionProcess { get; }

/// <summary>
/// Get the after-transaction-completion process, if any, for this action.
/// </summary>
IAfterTransactionCompletionProcess AfterTransactionCompletionProcess { get; }
AfterTransactionCompletionProcessDelegate AfterTransactionCompletionProcess { get; }
Copy link
Member

Choose a reason for hiding this comment

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

I would obsolete these properties.

}
}
2 changes: 1 addition & 1 deletion src/NHibernate/Async/Action/BulkOperationCleanupAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

namespace NHibernate.Action
{
public partial class BulkOperationCleanupAction : IExecutable, IAfterTransactionCompletionProcess
public partial class BulkOperationCleanupAction : IAsyncExecutable, IAfterTransactionCompletionProcess
{

#region IExecutable Members
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Async/Action/CollectionAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace NHibernate.Action
{
using System.Threading.Tasks;
using System.Threading;
public abstract partial class CollectionAction : IExecutable, IComparable<CollectionAction>, IDeserializationCallback, IAfterTransactionCompletionProcess
public abstract partial class CollectionAction : IAsyncExecutable, IComparable<CollectionAction>, IDeserializationCallback, IAfterTransactionCompletionProcess
{

#region IExecutable Members
Expand Down
5 changes: 3 additions & 2 deletions src/NHibernate/Async/Action/CollectionUpdateAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using System;
using System.Diagnostics;
using NHibernate.Cache;
using NHibernate.Cache.Access;
using NHibernate.Cache.Entry;
using NHibernate.Collection;
using NHibernate.Engine;
Expand All @@ -23,7 +22,7 @@ namespace NHibernate.Action
{
using System.Threading.Tasks;
using System.Threading;
public sealed partial class CollectionUpdateAction : CollectionAction, IAfterTransactionCompletionProcess
public sealed partial class CollectionUpdateAction : CollectionAction
{

public override async Task ExecuteAsync(CancellationToken cancellationToken)
Expand Down Expand Up @@ -123,6 +122,8 @@ private async Task PostUpdateAsync(CancellationToken cancellationToken)
public override async Task ExecuteAfterTransactionCompletionAsync(bool success, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
// NH Different behavior: to support unlocking collections from the cache.(r3260)

CacheKey ck = Session.GenerateCacheKey(Key, Persister.KeyType, Persister.Role);

if (success)
Expand Down
11 changes: 7 additions & 4 deletions src/NHibernate/Async/Action/EntityAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ namespace NHibernate.Action
{
using System.Threading.Tasks;
using System.Threading;
public abstract partial class EntityAction : IExecutable, IComparable<EntityAction>, IDeserializationCallback,
public abstract partial class EntityAction :
IAsyncExecutable,
IBeforeTransactionCompletionProcess,
IAfterTransactionCompletionProcess
IAfterTransactionCompletionProcess,
IComparable<EntityAction>,
IDeserializationCallback
{

#region IExecutable Members
Expand Down Expand Up @@ -68,6 +71,8 @@ protected virtual Task AfterTransactionCompletionProcessImplAsync(bool success,
}
}

#endregion

public Task ExecuteBeforeTransactionCompletionAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
Expand All @@ -85,7 +90,5 @@ public Task ExecuteAfterTransactionCompletionAsync(bool success, CancellationTok
}
return AfterTransactionCompletionProcessImplAsync(success, cancellationToken);
}

#endregion
}
}
3 changes: 3 additions & 0 deletions src/NHibernate/Async/Action/IExecutable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
//------------------------------------------------------------------------------


using NHibernate.Engine;

namespace NHibernate.Action
{
using System.Threading.Tasks;
using System.Threading;

public partial interface IExecutable
{

Expand Down
44 changes: 43 additions & 1 deletion src/NHibernate/Async/Engine/ActionQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace NHibernate.Engine
{
public partial class ActionQueue
{

private async Task ExecuteActionsAsync(IList list, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand Down Expand Up @@ -240,5 +240,47 @@ public async Task AfterTransactionCompletionAsync(bool success, CancellationToke
processes.Clear();
}
}

private partial class BeforeTransactionCompletionDelegatedProcess : IBeforeTransactionCompletionProcess
{

public Task ExecuteBeforeTransactionCompletionAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<object>(cancellationToken);
}
try
{
ExecuteBeforeTransactionCompletion();
return Task.CompletedTask;
}
catch (Exception ex)
{
return Task.FromException<object>(ex);
}
}
}

private partial class AfterTransactionCompletionDelegatedProcess : IAfterTransactionCompletionProcess
{

public Task ExecuteAfterTransactionCompletionAsync(bool success, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<object>(cancellationToken);
}
try
{
ExecuteAfterTransactionCompletion(success);
return Task.CompletedTask;
}
catch (Exception ex)
{
return Task.FromException<object>(ex);
}
}
}
}
}
Loading