Create scoped notification publishing - particularly for "ed" notifications that must run after the current scope has completed

This commit is contained in:
Kenn Jacobsen
2021-03-03 17:08:21 +01:00
parent 134a92e4d9
commit 8e745eb13c
10 changed files with 232 additions and 190 deletions

View File

@@ -1,4 +1,4 @@
using System;
using System;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Infrastructure.Persistence;
@@ -30,6 +30,11 @@ namespace Umbraco.Cms.Core.Scoping
/// </summary>
IEventDispatcher Events { get; }
/// <summary>
/// Gets the scope notification publisher
/// </summary>
IScopedNotificationPublisher Notifications { get; }
/// <summary>
/// Gets the repositories cache mode.
/// </summary>

View File

@@ -19,6 +19,7 @@ namespace Umbraco.Cms.Core.Scoping
private readonly ScopeProvider _scopeProvider;
private readonly CoreDebugSettings _coreDebugSettings;
private readonly IMediaFileSystem _mediaFileSystem;
private readonly IEventAggregator _eventAggregator;
private readonly ILogger<Scope> _logger;
private readonly IsolationLevel _isolationLevel;
@@ -35,12 +36,15 @@ namespace Umbraco.Cms.Core.Scoping
private EventMessages _messages;
private ICompletable _fscope;
private IEventDispatcher _eventDispatcher;
// eventually this may need to be injectable - for now we'll create it explicitly and let future needs determine if it should be injectable
private IScopedNotificationPublisher _notificationPublisher;
// initializes a new scope
private Scope(
ScopeProvider scopeProvider,
CoreDebugSettings coreDebugSettings,
IMediaFileSystem mediaFileSystem,
IEventAggregator eventAggregator,
ILogger<Scope> logger,
FileSystems fileSystems,
Scope parent,
@@ -56,6 +60,7 @@ namespace Umbraco.Cms.Core.Scoping
_scopeProvider = scopeProvider;
_coreDebugSettings = coreDebugSettings;
_mediaFileSystem = mediaFileSystem;
_eventAggregator = eventAggregator;
_logger = logger;
Context = scopeContext;
@@ -69,6 +74,7 @@ namespace Umbraco.Cms.Core.Scoping
Detachable = detachable;
#if DEBUG_SCOPES
_scopeProvider.RegisterScope(this);
Console.WriteLine("create " + InstanceId.ToString("N").Substring(0, 8));
@@ -124,6 +130,7 @@ namespace Umbraco.Cms.Core.Scoping
ScopeProvider scopeProvider,
CoreDebugSettings coreDebugSettings,
IMediaFileSystem mediaFileSystem,
IEventAggregator eventAggregator,
ILogger<Scope> logger,
FileSystems fileSystems,
bool detachable,
@@ -134,7 +141,7 @@ namespace Umbraco.Cms.Core.Scoping
bool? scopeFileSystems = null,
bool callContext = false,
bool autoComplete = false)
: this(scopeProvider, coreDebugSettings, mediaFileSystem, logger, fileSystems, null, scopeContext, detachable, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
: this(scopeProvider, coreDebugSettings, mediaFileSystem, eventAggregator, logger, fileSystems, null, scopeContext, detachable, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
{ }
// initializes a new scope in a nested scopes chain, with its parent
@@ -142,6 +149,7 @@ namespace Umbraco.Cms.Core.Scoping
ScopeProvider scopeProvider,
CoreDebugSettings coreDebugSettings,
IMediaFileSystem mediaFileSystem,
IEventAggregator eventAggregator,
ILogger<Scope> logger,
FileSystems fileSystems,
Scope parent,
@@ -151,7 +159,7 @@ namespace Umbraco.Cms.Core.Scoping
bool? scopeFileSystems = null,
bool callContext = false,
bool autoComplete = false)
: this(scopeProvider, coreDebugSettings, mediaFileSystem, logger, fileSystems, parent, null, false, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
: this(scopeProvider, coreDebugSettings, mediaFileSystem, eventAggregator, logger, fileSystems, parent, null, false, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
{ }
public Guid InstanceId { get; } = Guid.NewGuid();
@@ -314,6 +322,16 @@ namespace Umbraco.Cms.Core.Scoping
}
}
public IScopedNotificationPublisher Notifications
{
get
{
EnsureNotDisposed();
if (ParentScope != null) return ParentScope.Notifications;
return _notificationPublisher ?? (_notificationPublisher = new ScopedNotificationPublisher(_eventAggregator));
}
}
/// <inheritdoc />
public bool Complete()
{
@@ -453,7 +471,10 @@ namespace Umbraco.Cms.Core.Scoping
{
// deal with events
if (onException == false)
{
_eventDispatcher?.ScopeExit(completed);
_notificationPublisher?.ScopeExit(completed);
}
}, () =>
{
// if *we* created it, then get rid of it

View File

@@ -26,8 +26,9 @@ namespace Umbraco.Cms.Core.Scoping
private readonly FileSystems _fileSystems;
private readonly CoreDebugSettings _coreDebugSettings;
private readonly IMediaFileSystem _mediaFileSystem;
private readonly IEventAggregator _eventAggregator;
public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, IOptions<CoreDebugSettings> coreDebugSettings, IMediaFileSystem mediaFileSystem, ILogger<ScopeProvider> logger, ILoggerFactory loggerFactory, IRequestCache requestCache)
public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, IOptions<CoreDebugSettings> coreDebugSettings, IMediaFileSystem mediaFileSystem, ILogger<ScopeProvider> logger, ILoggerFactory loggerFactory, IRequestCache requestCache, IEventAggregator eventAggregator)
{
DatabaseFactory = databaseFactory;
_fileSystems = fileSystems;
@@ -36,6 +37,7 @@ namespace Umbraco.Cms.Core.Scoping
_logger = logger;
_loggerFactory = loggerFactory;
_requestCache = requestCache;
_eventAggregator = eventAggregator;
// take control of the FileSystems
_fileSystems.IsScoped = () => AmbientScope != null && AmbientScope.ScopedFileSystems;
@@ -253,7 +255,7 @@ namespace Umbraco.Cms.Core.Scoping
IEventDispatcher eventDispatcher = null,
bool? scopeFileSystems = null)
{
return new Scope(this, _coreDebugSettings, _mediaFileSystem, _loggerFactory.CreateLogger<Scope>(), _fileSystems, true, null, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems);
return new Scope(this, _coreDebugSettings, _mediaFileSystem, _eventAggregator, _loggerFactory.CreateLogger<Scope>(), _fileSystems, true, null, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems);
}
/// <inheritdoc />
@@ -309,13 +311,13 @@ namespace Umbraco.Cms.Core.Scoping
{
var ambientContext = AmbientContext;
var newContext = ambientContext == null ? new ScopeContext() : null;
var scope = new Scope(this, _coreDebugSettings, _mediaFileSystem, _loggerFactory.CreateLogger<Scope>(), _fileSystems, false, newContext, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
var scope = new Scope(this, _coreDebugSettings, _mediaFileSystem, _eventAggregator, _loggerFactory.CreateLogger<Scope>(), _fileSystems, false, newContext, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
// assign only if scope creation did not throw!
SetAmbient(scope, newContext ?? ambientContext);
return scope;
}
var nested = new Scope(this, _coreDebugSettings, _mediaFileSystem, _loggerFactory.CreateLogger<Scope>(), _fileSystems, ambientScope, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
var nested = new Scope(this, _coreDebugSettings, _mediaFileSystem, _eventAggregator, _loggerFactory.CreateLogger<Scope>(), _fileSystems, ambientScope, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
SetAmbient(nested, AmbientContext);
return nested;
}