From 00c720413a7ac08b9707326845f0078a9ae5c06c Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 16 Sep 2019 17:23:00 +1000 Subject: [PATCH] Uses reflection to call ResetModels to flag MB to recompile. --- .../PublishedContentExtensionsForModels.cs | 10 +++- .../PublishedModelFactoryExtensions.cs | 52 +++++-------------- .../Cache/ContentTypeCacheRefresher.cs | 2 +- .../Cache/DataTypeCacheRefresher.cs | 2 +- 4 files changed, 25 insertions(+), 41 deletions(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs index 8e68bdae52..bfc65b70d6 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs @@ -25,7 +25,15 @@ namespace Umbraco.Core.Models.PublishedContent // get model // if factory returns nothing, throw - return Current.PublishedModelFactory.CreateModelWithSafeLiveFactoryRefreshCheck(content); + var model = Current.PublishedModelFactory.CreateModel(content); + if (model == null) + throw new Exception("Factory returned null."); + + // if factory returns a different type, throw + if (!(model is IPublishedContent publishedContent)) + throw new Exception($"Factory returned model of type {model.GetType().FullName} which does not implement IPublishedContent."); + + return publishedContent; } } } diff --git a/src/Umbraco.Core/PublishedModelFactoryExtensions.cs b/src/Umbraco.Core/PublishedModelFactoryExtensions.cs index 0e3aa48c53..e30b87d15e 100644 --- a/src/Umbraco.Core/PublishedModelFactoryExtensions.cs +++ b/src/Umbraco.Core/PublishedModelFactoryExtensions.cs @@ -40,50 +40,28 @@ namespace Umbraco.Core } /// - /// Creates a strongly typed model while checking if the factory is and if a refresh flag has been set, in which - /// case the models will be recompiled before model creation - /// - /// - /// - /// - internal static IPublishedContent CreateModelWithSafeLiveFactoryRefreshCheck(this IPublishedModelFactory factory, IPublishedContent content) - { - if (factory is ILivePublishedModelFactory liveFactory && _refresh) - { - lock (liveFactory.SyncRoot) - { - if (_refresh) - { - _refresh = false; - //Call refresh on the live factory to re-compile the models - liveFactory.Refresh(); - } - } - } - - var model = factory.CreateModel(content); - if (model == null) - throw new Exception("Factory returned null."); - - // if factory returns a different type, throw - if (!(model is IPublishedContent publishedContent)) - throw new Exception($"Factory returned model of type {model.GetType().FullName} which does not implement IPublishedContent."); - - return publishedContent; - } - - /// - /// Sets a flag to re-compile the models if the is + /// Sets a flag to reset the ModelsBuilder models if the is /// /// /// - internal static void WithSafeLiveFactoryRefreshSet(this IPublishedModelFactory factory, Action action) + /// + /// This does not recompile the pure live models, only sets a flag to tell models builder to recompile when they are requested. + /// + internal static void WithSafeLiveFactoryReset(this IPublishedModelFactory factory, Action action) { if (factory is ILivePublishedModelFactory liveFactory) { lock (liveFactory.SyncRoot) { - _refresh = true; + // TODO: Fix this in 8.3! - We need to change the ILivePublishedModelFactory interface to have a Reset method and then when we have an embedded MB + // version we will publicize the ResetModels (and change the name to Reset). + // For now, this will suffice and we'll use reflection, there should be no other implementation of ILivePublishedModelFactory. + // Calling ResetModels resets the MB flag so that the next time EnsureModels is called (which is called when nucache lazily calls CreateModel) it will + // trigger the recompiling of pure live models. + var resetMethod = liveFactory.GetType().GetMethod("ResetModels", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); + if (resetMethod != null) + resetMethod.Invoke(liveFactory, null); + action(); } } @@ -93,7 +71,5 @@ namespace Umbraco.Core } } - private static volatile bool _refresh = false; - } } diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs index df81dd85e8..dc1a4701d4 100644 --- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs @@ -90,7 +90,7 @@ namespace Umbraco.Web.Cache // service of changes, else factories may try to rebuild models while // we are using the database to load content into caches - _publishedModelFactory.WithSafeLiveFactoryRefreshSet(() => + _publishedModelFactory.WithSafeLiveFactoryReset(() => _publishedSnapshotService.Notify(payloads)); // now we can trigger the event diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index f86073abdd..0ddb8c4bf6 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -66,7 +66,7 @@ namespace Umbraco.Web.Cache // service of changes, else factories may try to rebuild models while // we are using the database to load content into caches - _publishedModelFactory.WithSafeLiveFactoryRefreshSet(() => + _publishedModelFactory.WithSafeLiveFactoryReset(() => _publishedSnapshotService.Notify(payloads)); base.Refresh(payloads);