Skip to content

WIP - Do not try to invalidate query spaces for non cached persisters #2130

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
97 changes: 60 additions & 37 deletions src/NHibernate/Action/BulkOperationCleanupAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,49 @@ namespace NHibernate.Action
/// Implementation of BulkOperationCleanupAction.
/// </summary>
[Serializable]
public partial class BulkOperationCleanupAction : IAsyncExecutable, IAfterTransactionCompletionProcess
public partial class BulkOperationCleanupAction :
IAsyncExecutable,
IAfterTransactionCompletionProcess,
ICacheableExecutable
{
private readonly ISessionImplementor session;
private readonly HashSet<string> affectedEntityNames = new HashSet<string>();
private readonly HashSet<string> affectedCollectionRoles = new HashSet<string>();
private readonly List<string> spaces;
private readonly ISessionFactoryImplementor _factory;
private readonly HashSet<string> affectedEntityNames;
private readonly HashSet<string> affectedCollectionRoles;
private readonly string[] spaces;
private readonly bool _hasCache;

public BulkOperationCleanupAction(ISessionImplementor session, IQueryable[] affectedQueryables)
{
this.session = session;
List<string> tmpSpaces = new List<string>();
for (int i = 0; i < affectedQueryables.Length; i++)
_factory = session.Factory;
var tmpSpaces = new HashSet<string>();
foreach (var queryables in affectedQueryables)
{
if (affectedQueryables[i].HasCache)
if (queryables.HasCache)
{
affectedEntityNames.Add(affectedQueryables[i].EntityName);
_hasCache = true;
if (affectedEntityNames == null)
{
affectedEntityNames = new HashSet<string>();
}

affectedEntityNames.Add(queryables.EntityName);
}
ISet<string> roles = session.Factory.GetCollectionRolesByEntityParticipant(affectedQueryables[i].EntityName);

var roles = _factory.GetCollectionRolesByEntityParticipant(queryables.EntityName);
Copy link
Member

Choose a reason for hiding this comment

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

Collection persister can also have cache. But currently _hasCache is only calculated for entity persister. And shouldn't we retrieve here list for only cached collection roles?

if (roles != null)
{
if (affectedCollectionRoles == null)
{
affectedCollectionRoles = new HashSet<string>();
}

affectedCollectionRoles.UnionWith(roles);
}
for (int y = 0; y < affectedQueryables[i].QuerySpaces.Length; y++)
{
tmpSpaces.Add(affectedQueryables[i].QuerySpaces[y]);
}

tmpSpaces.UnionWith(queryables.QuerySpaces);
}
spaces = new List<string>(tmpSpaces);

spaces = tmpSpaces.ToArray();
}

/// <summary>
Expand All @@ -50,35 +65,44 @@ public BulkOperationCleanupAction(ISessionImplementor session, IQueryable[] affe
public BulkOperationCleanupAction(ISessionImplementor session, ISet<string> querySpaces)
{
//from H3.2 TODO: cache the autodetected information and pass it in instead.
this.session = session;
_factory = session.Factory;

ISet<string> tmpSpaces = new HashSet<string>(querySpaces);
ISessionFactoryImplementor factory = session.Factory;
IDictionary<string, IClassMetadata> acmd = factory.GetAllClassMetadata();
var tmpSpaces = new HashSet<string>(querySpaces);
var acmd = _factory.GetAllClassMetadata();
foreach (KeyValuePair<string, IClassMetadata> entry in acmd)
{
string entityName = entry.Key;
IEntityPersister persister = factory.GetEntityPersister(entityName);
string[] entitySpaces = persister.QuerySpaces;
var entityName = entry.Key;
var persister = _factory.GetEntityPersister(entityName);
var entitySpaces = persister.QuerySpaces;

if (AffectedEntity(querySpaces, entitySpaces))
{
if (persister.HasCache)
{
_hasCache = true;
if (affectedEntityNames == null)
{
affectedEntityNames = new HashSet<string>();
}

affectedEntityNames.Add(persister.EntityName);
}
ISet<string> roles = session.Factory.GetCollectionRolesByEntityParticipant(persister.EntityName);

var roles = session.Factory.GetCollectionRolesByEntityParticipant(persister.EntityName);
if (roles != null)
{
if (affectedCollectionRoles == null)
{
affectedCollectionRoles = new HashSet<string>();
}

affectedCollectionRoles.UnionWith(roles);
}
for (int y = 0; y < entitySpaces.Length; y++)
{
tmpSpaces.Add(entitySpaces[y]);
}

tmpSpaces.UnionWith(entitySpaces);
}
}
spaces = new List<string>(tmpSpaces);
spaces = tmpSpaces.ToArray();
}

private bool AffectedEntity(ISet<string> querySpaces, string[] entitySpaces)
Expand All @@ -91,12 +115,11 @@ private bool AffectedEntity(ISet<string> querySpaces, string[] entitySpaces)
return entitySpaces.Any(querySpaces.Contains);
}

public bool HasCache => _hasCache;

#region IExecutable Members

public string[] PropertySpaces
{
get { return spaces.ToArray(); }
}
public string[] PropertySpaces => spaces;

public void BeforeExecutions()
{
Expand Down Expand Up @@ -132,17 +155,17 @@ public void ExecuteAfterTransactionCompletion(bool success)

private void EvictCollectionRegions()
{
if (affectedCollectionRoles != null && affectedCollectionRoles.Any())
if (affectedCollectionRoles != null)
{
session.Factory.EvictCollection(affectedCollectionRoles);
_factory.EvictCollection(affectedCollectionRoles);
}
}

private void EvictEntityRegions()
{
if (affectedEntityNames != null && affectedEntityNames.Any())
if (affectedEntityNames != null)
{
session.Factory.EvictEntity(affectedEntityNames);
_factory.EvictEntity(affectedEntityNames);
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/NHibernate/Action/CollectionAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ namespace NHibernate.Action
/// Any action relating to insert/update/delete of a collection
/// </summary>
[Serializable]
public abstract partial class CollectionAction : IAsyncExecutable, IComparable<CollectionAction>, IDeserializationCallback, IAfterTransactionCompletionProcess
public abstract partial class CollectionAction:
IAsyncExecutable,
IComparable<CollectionAction>,
IDeserializationCallback,
IAfterTransactionCompletionProcess,
ICacheableExecutable
{
private readonly object key;
[NonSerialized] private ICollectionPersister persister;
Expand Down Expand Up @@ -77,6 +82,8 @@ protected internal ISessionImplementor Session
get { return session; }
}

public bool HasCache => persister.HasCache;

#region IExecutable Members

/// <summary>
Expand Down
5 changes: 4 additions & 1 deletion src/NHibernate/Action/EntityAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public abstract partial class EntityAction :
IBeforeTransactionCompletionProcess,
IAfterTransactionCompletionProcess,
IComparable<EntityAction>,
IDeserializationCallback
IDeserializationCallback,
ICacheableExecutable
{
private readonly string entityName;
private readonly object id;
Expand Down Expand Up @@ -195,5 +196,7 @@ public void ExecuteAfterTransactionCompletion(bool success)
{
AfterTransactionCompletionProcessImpl(success);
}

public bool HasCache => persister.HasCache;
}
}
8 changes: 8 additions & 0 deletions src/NHibernate/Action/ICacheableExecutable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace NHibernate.Action
{
//6.0 TODO: Merge to IExecutable
public interface ICacheableExecutable : IExecutable
{
bool HasCache { get; }
}
}
31 changes: 10 additions & 21 deletions src/NHibernate/Async/Action/BulkOperationCleanupAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@

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

#region IExecutable Members
Expand Down Expand Up @@ -72,18 +75,11 @@ private Task EvictCollectionRegionsAsync(CancellationToken cancellationToken)
{
return Task.FromCanceled<object>(cancellationToken);
}
try
{
if (affectedCollectionRoles != null && affectedCollectionRoles.Any())
{
return session.Factory.EvictCollectionAsync(affectedCollectionRoles, cancellationToken);
}
return Task.CompletedTask;
}
catch (Exception ex)
if (affectedCollectionRoles != null)
{
return Task.FromException<object>(ex);
return _factory.EvictCollectionAsync(affectedCollectionRoles, cancellationToken);
}
return Task.CompletedTask;
}

private Task EvictEntityRegionsAsync(CancellationToken cancellationToken)
Expand All @@ -92,18 +88,11 @@ private Task EvictEntityRegionsAsync(CancellationToken cancellationToken)
{
return Task.FromCanceled<object>(cancellationToken);
}
try
{
if (affectedEntityNames != null && affectedEntityNames.Any())
{
return session.Factory.EvictEntityAsync(affectedEntityNames, cancellationToken);
}
return Task.CompletedTask;
}
catch (Exception ex)
if (affectedEntityNames != null)
{
return Task.FromException<object>(ex);
return _factory.EvictEntityAsync(affectedEntityNames, cancellationToken);
}
return Task.CompletedTask;
}

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

protected async Task<object> GetKeyAsync(CancellationToken cancellationToken)
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate/Async/Action/EntityAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public abstract partial class EntityAction :
IBeforeTransactionCompletionProcess,
IAfterTransactionCompletionProcess,
IComparable<EntityAction>,
IDeserializationCallback
IDeserializationCallback,
ICacheableExecutable
{

#region IExecutable Members
Expand Down
7 changes: 3 additions & 4 deletions src/NHibernate/Async/Engine/ActionQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private Task PreInvalidateCachesAsync(CancellationToken cancellationToken)
{
return Task.FromCanceled<object>(cancellationToken);
}
if (session.Factory.Settings.IsQueryCacheEnabled && executedSpaces.Count > 0)
if (executedSpaces?.Count > 0)
{
return session.Factory.UpdateTimestampsCache.PreInvalidateAsync(executedSpaces, cancellationToken);
}
Expand Down Expand Up @@ -165,12 +165,11 @@ public async Task AfterTransactionCompletionAsync(bool success, CancellationToke
private async Task InvalidateCachesAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (session.Factory.Settings.IsQueryCacheEnabled && executedSpaces.Count > 0)
if (executedSpaces?.Count > 0)
{
await (session.Factory.UpdateTimestampsCache.InvalidateAsync(executedSpaces, cancellationToken)).ConfigureAwait(false);
executedSpaces.Clear();
}

executedSpaces.Clear();
}
private partial class BeforeTransactionCompletionProcessQueue
{
Expand Down
14 changes: 8 additions & 6 deletions src/NHibernate/Engine/ActionQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public ActionQueue(ISessionImplementor session)
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue();
beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue();

executedSpaces = new HashSet<string>();
executedSpaces = session.Factory.Settings.IsQueryCacheEnabled ? new HashSet<string>() : null;
}

public virtual void Clear()
Expand Down Expand Up @@ -172,7 +172,7 @@ private void ExecuteActions<T>(List<T> list) where T: IExecutable

private void PreInvalidateCaches()
{
if (session.Factory.Settings.IsQueryCacheEnabled && executedSpaces.Count > 0)
if (executedSpaces?.Count > 0)
{
session.Factory.UpdateTimestampsCache.PreInvalidate(executedSpaces);
}
Expand Down Expand Up @@ -216,7 +216,10 @@ private void RegisterCleanupActions(IExecutable executable)
RegisterProcess(executable.AfterTransactionCompletionProcess);
#pragma warning restore 618,619
}
if (executable.PropertySpaces != null)

if (executedSpaces != null &&
executable.PropertySpaces != null &&
(!(executable is ICacheableExecutable ce) || ce.HasCache))
{
executedSpaces.UnionWith(executable.PropertySpaces);
}
Expand Down Expand Up @@ -294,12 +297,11 @@ public void AfterTransactionCompletion(bool success)

private void InvalidateCaches()
{
if (session.Factory.Settings.IsQueryCacheEnabled && executedSpaces.Count > 0)
if (executedSpaces?.Count > 0)
{
session.Factory.UpdateTimestampsCache.Invalidate(executedSpaces);
executedSpaces.Clear();
}

executedSpaces.Clear();
}

/// <summary>
Expand Down