Merge remote-tracking branch 'origin/v9/dev' into netcore/feature/get_rid_of_ICoreComposer

# Conflicts:
#	src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs
#	src/Umbraco.Examine.Lucene/ExamineLuceneConfigureIndexes.cs
#	src/Umbraco.Examine.Lucene/ExamineLuceneFinalComposer.cs
#	src/Umbraco.Examine.Lucene/ExamineLuceneStarting.cs
#	src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs
#	src/Umbraco.PublishedCache.NuCache/Compose/NotificationsComposer.cs
#	src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs
#	src/Umbraco.Web.UI.Client/package-lock.json
This commit is contained in:
Bjarke Berg
2021-06-15 19:10:30 +02:00
969 changed files with 28924 additions and 24595 deletions

View File

@@ -1,12 +1,11 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Notifications;
using Umbraco.Cms.Infrastructure.PublishedCache;
using Umbraco.Cms.Infrastructure.PublishedCache.Persistence;
@@ -31,9 +30,6 @@ namespace Umbraco.Extensions
// must register default options, required in the service ctor
builder.Services.TryAddTransient(factory => new PublishedSnapshotServiceOptions());
builder.SetPublishedSnapshotService<PublishedSnapshotService>();
// Add as itself
builder.Services.TryAddSingleton<PublishedSnapshotService>();
builder.Services.TryAddSingleton<IPublishedSnapshotStatus, PublishedSnapshotStatus>();
// replace this service since we want to improve the content/media
@@ -71,7 +67,8 @@ namespace Umbraco.Extensions
.AddNotificationHandler<ContentTypeRefreshedNotification, PublishedSnapshotServiceEventHandler>()
.AddNotificationHandler<MediaTypeRefreshedNotification, PublishedSnapshotServiceEventHandler>()
.AddNotificationHandler<MemberTypeRefreshedNotification, PublishedSnapshotServiceEventHandler>()
.AddNotificationHandler<ScopedEntityRemoveNotification, PublishedSnapshotServiceEventHandler>();
.AddNotificationHandler<ScopedEntityRemoveNotification, PublishedSnapshotServiceEventHandler>()
;
return builder;
}

View File

@@ -14,9 +14,9 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
#region Constructors
public PublishedSnapshot(PublishedSnapshotService service, bool defaultPreview)
public PublishedSnapshot(IPublishedSnapshotService service, bool defaultPreview)
{
_service = service;
_service = service as PublishedSnapshotService;
_defaultPreview = defaultPreview;
}
@@ -38,7 +38,17 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
}
}
private PublishedSnapshotElements Elements => _elements ?? (_elements = _service.GetElements(_defaultPreview));
private PublishedSnapshotElements Elements
{
get
{
if (_service == null)
{
throw new InvalidOperationException($"The {typeof(PublishedSnapshot)} cannot be used when the {typeof(IPublishedSnapshotService)} is not the default type {typeof(PublishedSnapshotService)}");
}
return _elements ??= _service.GetElements(_defaultPreview);
}
}
public void Resync()
{

View File

@@ -19,6 +19,7 @@ using Umbraco.Cms.Core.Runtime;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Changes;
using Umbraco.Cms.Core.Sync;
using Umbraco.Cms.Infrastructure.PublishedCache.DataSource;
using Umbraco.Cms.Infrastructure.PublishedCache.Persistence;
using Umbraco.Extensions;
@@ -29,6 +30,9 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
{
internal class PublishedSnapshotService : IPublishedSnapshotService
{
private readonly PublishedSnapshotServiceOptions _options;
private readonly ISyncBootStateAccessor _syncBootStateAccessor;
private readonly IMainDom _mainDom;
private readonly ServiceContext _serviceContext;
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
@@ -39,7 +43,6 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
private readonly ILogger<PublishedSnapshotService> _logger;
private readonly ILoggerFactory _loggerFactory;
private readonly GlobalSettings _globalSettings;
private readonly IEntityXmlSerializer _entitySerializer;
private readonly IPublishedModelFactory _publishedModelFactory;
private readonly IDefaultCultureAccessor _defaultCultureAccessor;
private readonly IHostingEnvironment _hostingEnvironment;
@@ -49,9 +52,9 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
private bool _isReadSet;
private object _isReadyLock;
private readonly ContentStore _contentStore;
private readonly ContentStore _mediaStore;
private readonly SnapDictionary<int, Domain> _domainStore;
private ContentStore _contentStore;
private ContentStore _mediaStore;
private SnapDictionary<int, Domain> _domainStore;
private readonly object _storesLock = new object();
private readonly object _elementsLock = new object();
@@ -73,6 +76,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
public PublishedSnapshotService(
PublishedSnapshotServiceOptions options,
ISyncBootStateAccessor syncBootStateAccessor,
IMainDom mainDom,
ServiceContext serviceContext,
IPublishedContentTypeFactory publishedContentTypeFactory,
@@ -84,11 +88,13 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
INuCacheContentService publishedContentService,
IDefaultCultureAccessor defaultCultureAccessor,
IOptions<GlobalSettings> globalSettings,
IEntityXmlSerializer entitySerializer,
IPublishedModelFactory publishedModelFactory,
IHostingEnvironment hostingEnvironment,
IOptions<NuCacheSettings> config)
{
_options = options;
_syncBootStateAccessor = syncBootStateAccessor;
_mainDom = mainDom;
_serviceContext = serviceContext;
_publishedContentTypeFactory = publishedContentTypeFactory;
_publishedSnapshotAccessor = publishedSnapshotAccessor;
@@ -102,41 +108,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
_globalSettings = globalSettings.Value;
_hostingEnvironment = hostingEnvironment;
_config = config.Value;
// we need an Xml serializer here so that the member cache can support XPath,
// for members this is done by navigating the serialized-to-xml member
_entitySerializer = entitySerializer;
_publishedModelFactory = publishedModelFactory;
// lock this entire call, we only want a single thread to be accessing the stores at once and within
// the call below to mainDom.Register, a callback may occur on a threadpool thread to MainDomRelease
// at the same time as we are trying to write to the stores. MainDomRelease also locks on _storesLock so
// it will not be able to close the stores until we are done populating (if the store is empty)
lock (_storesLock)
{
if (!options.IgnoreLocalDb)
{
mainDom.Register(MainDomRegister, MainDomRelease);
// stores are created with a db so they can write to it, but they do not read from it,
// stores need to be populated, happens in OnResolutionFrozen which uses _localDbExists to
// figure out whether it can read the databases or it should populate them from sql
_logger.LogInformation("Creating the content store, localContentDbExists? {LocalContentDbExists}", _localContentDbExists);
_contentStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory, _localContentDb);
_logger.LogInformation("Creating the media store, localMediaDbExists? {LocalMediaDbExists}", _localMediaDbExists);
_mediaStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory, _localMediaDb);
}
else
{
_logger.LogInformation("Creating the content store (local db ignored)");
_contentStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory);
_logger.LogInformation("Creating the media store (local db ignored)");
_mediaStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory);
}
_domainStore = new SnapDictionary<int, Domain>();
}
}
protected PublishedSnapshot CurrentPublishedSnapshot => (PublishedSnapshot)_publishedSnapshotAccessor.PublishedSnapshot;
@@ -144,13 +116,29 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
// NOTE: These aren't used within this object but are made available internally to improve the IdKey lookup performance
// when nucache is enabled.
// TODO: Does this need to be here?
internal int GetDocumentId(Guid udi) => GetId(_contentStore, udi);
internal int GetDocumentId(Guid udi)
{
EnsureCaches();
return GetId(_contentStore, udi);
}
internal int GetMediaId(Guid udi) => GetId(_mediaStore, udi);
internal int GetMediaId(Guid udi)
{
EnsureCaches();
return GetId(_mediaStore, udi);
}
internal Guid GetDocumentUid(int id) => GetUid(_contentStore, id);
internal Guid GetDocumentUid(int id)
{
EnsureCaches();
return GetUid(_contentStore, id);
}
internal Guid GetMediaUid(int id) => GetUid(_mediaStore, id);
internal Guid GetMediaUid(int id)
{
EnsureCaches();
return GetUid(_mediaStore, id);
}
private int GetId(ContentStore store, Guid uid) => store.LiveSnapshot.Get(uid)?.Id ?? 0;
@@ -249,7 +237,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
}
/// <summary>
/// Populates the stores
/// Lazily populates the stores only when they are first requested
/// </summary>
internal void EnsureCaches() => LazyInitializer.EnsureInitialized(
ref _isReady,
@@ -257,15 +245,43 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
ref _isReadyLock,
() =>
{
// even though we are ready locked here we want to ensure that the stores lock is also locked
// lock this entire call, we only want a single thread to be accessing the stores at once and within
// the call below to mainDom.Register, a callback may occur on a threadpool thread to MainDomRelease
// at the same time as we are trying to write to the stores. MainDomRelease also locks on _storesLock so
// it will not be able to close the stores until we are done populating (if the store is empty)
lock (_storesLock)
{
if (!_options.IgnoreLocalDb)
{
_mainDom.Register(MainDomRegister, MainDomRelease);
// stores are created with a db so they can write to it, but they do not read from it,
// stores need to be populated, happens in OnResolutionFrozen which uses _localDbExists to
// figure out whether it can read the databases or it should populate them from sql
_logger.LogInformation("Creating the content store, localContentDbExists? {LocalContentDbExists}", _localContentDbExists);
_contentStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory, _localContentDb);
_logger.LogInformation("Creating the media store, localMediaDbExists? {LocalMediaDbExists}", _localMediaDbExists);
_mediaStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory, _localMediaDb);
}
else
{
_logger.LogInformation("Creating the content store (local db ignored)");
_contentStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory);
_logger.LogInformation("Creating the media store (local db ignored)");
_mediaStore = new ContentStore(_publishedSnapshotAccessor, _variationContextAccessor, _loggerFactory.CreateLogger("ContentStore"), _loggerFactory, _publishedModelFactory);
}
_domainStore = new SnapDictionary<int, Domain>();
var okContent = false;
var okMedia = false;
SyncBootState bootState = _syncBootStateAccessor.GetSyncBootState();
try
{
if (_localContentDbExists)
if (bootState != SyncBootState.ColdBoot && _localContentDbExists)
{
okContent = LockAndLoadContent(() => LoadContentFromLocalDbLocked(true));
if (!okContent)
@@ -274,7 +290,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
}
}
if (_localMediaDbExists)
if (bootState != SyncBootState.ColdBoot && _localMediaDbExists)
{
okMedia = LockAndLoadMedia(() => LoadMediaFromLocalDbLocked(true));
if (!okMedia)
@@ -485,7 +501,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
// be processed as soon as we are configured and the messenger processes instructions.
// note: notifications for content type and data type changes should be invoked with the
// pure live model factory, if any, locked and refreshed - see ContentTypeCacheRefresher and
// InMemoryModelFactory, if any, locked and refreshed - see ContentTypeCacheRefresher and
// DataTypeCacheRefresher
public void Notify(ContentCacheRefresher.JsonPayload[] payloads, out bool draftChanged, out bool publishedChanged)
@@ -705,17 +721,17 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
if (_publishedModelFactory.IsLiveFactoryEnabled())
{
// In the case of Pure Live - we actually need to refresh all of the content and the media
// In the case of ModelsMode.InMemoryAuto generated models - we actually need to refresh all of the content and the media
// see https://github.com/umbraco/Umbraco-CMS/issues/5671
// The underlying issue is that in Pure Live the ILivePublishedModelFactory will re-compile all of the classes/models
// The underlying issue is that in ModelsMode.InMemoryAuto mode the IAutoPublishedModelFactory will re-compile all of the classes/models
// into a new DLL for the application which includes both content types and media types.
// Since the models in the cache are based on these actual classes, all of the objects in the cache need to be updated
// to use the newest version of the class.
// NOTE: Ideally this can be run on background threads here which would prevent blocking the UI
// as is the case when saving a content type. Intially one would think that it won't be any different
// as is the case when saving a content type. Initially one would think that it won't be any different
// between running this here or in another background thread immediately after with regards to how the
// UI will respond because we already know between calling `WithSafeLiveFactoryReset` to reset the PureLive models
// UI will respond because we already know between calling `WithSafeLiveFactoryReset` to reset the generated models
// and this code here, that many front-end requests could be attempted to be processed. If that is the case, those pages are going to get a
// model binding error and our ModelBindingExceptionFilter is going to to its magic to reload those pages so the end user is none the wiser.
// So whether or not this executes 'here' or on a background thread immediately wouldn't seem to make any difference except that we can return

View File

@@ -4,10 +4,10 @@ using System.Linq;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Changes;
using Umbraco.Cms.Core.Services.Notifications;
using Umbraco.Cms.Infrastructure.PublishedCache.Persistence;
using Umbraco.Extensions;

View File

@@ -11,9 +11,9 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
private readonly PublishedSnapshotService _service;
private readonly INuCacheContentService _publishedContentService;
public PublishedSnapshotStatus(PublishedSnapshotService service, INuCacheContentService publishedContentService)
public PublishedSnapshotStatus(IPublishedSnapshotService service, INuCacheContentService publishedContentService)
{
_service = service;
_service = service as PublishedSnapshotService;
_publishedContentService = publishedContentService;
}
@@ -23,6 +23,12 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
/// <inheritdoc/>
public string GetStatus()
{
if (_service == null)
{
return $"The current {typeof(IPublishedSnapshotService)} is not the default type. A status cannot be determined.";
}
// TODO: This should be private
_service.EnsureCaches();
var dbCacheIsOk = _publishedContentService.VerifyContentDbCache()

View File

@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Infrastructure.PublishedCache</RootNamespace>
<LangVersion>8</LangVersion>
<PackageId>Umbraco.Cms.PublishedCache.NuCache</PackageId>
<Title>Umbraco CMS Published Cache</Title>
<Description>Contains the Published Cache assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco</Description>
<Title>Umbraco CMS Published Cache</Title>
<Description>Contains the Published Cache assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco</Description>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
@@ -15,7 +15,14 @@
<ItemGroup>
<PackageReference Include="CSharpTest.Net.Collections-NetStd2" Version="14.906.1403.1084" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Umbraco.Code" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>