From d16bcdc8417249faaa879be22be8ab19e4d1fb7e Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 13 Feb 2019 13:28:11 +0100 Subject: [PATCH] Bugfix NuCache reload during upgrades --- .../InstallSteps/SetUmbracoVersionStep.cs | 5 - .../PublishedSnapshotRebuilder.cs | 1 - .../IPublishedSnapshotService.cs | 2 +- .../NuCache/PublishedSnapshotService.cs | 98 +++++++++++++------ 4 files changed, 68 insertions(+), 38 deletions(-) diff --git a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs index 55d7d49ba9..c1268ca675 100644 --- a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs @@ -46,11 +46,6 @@ namespace Umbraco.Web.Install.InstallSteps security.PerformLogin(-1); } - // Some upgrade scripts "may modify the database (cmsContentXml...) tables directly" - not sure - // that is still true but the idea is that after an upgrade we want to reset the local published snapshot, on - // all LB nodes of course, so we need to use the distributed cache, and refresh everything. - _distributedCache.RefreshAllPublishedSnapshot(); - // Update configurationStatus _globalSettings.ConfigurationStatus = UmbracoVersion.SemanticVersion.ToSemanticString(); diff --git a/src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs b/src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs index 11491a964a..764e46af5d 100644 --- a/src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs +++ b/src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs @@ -15,7 +15,6 @@ namespace Umbraco.Web.Migrations.PostMigrations /// /// Initializes a new instance of the class. /// - /// public PublishedSnapshotRebuilder(IPublishedSnapshotService publishedSnapshotService, DistributedCache distributedCache) { _publishedSnapshotService = publishedSnapshotService; diff --git a/src/Umbraco.Web/PublishedCache/IPublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/IPublishedSnapshotService.cs index 6d73be59e3..9949b4b3f8 100644 --- a/src/Umbraco.Web/PublishedCache/IPublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/IPublishedSnapshotService.cs @@ -51,7 +51,7 @@ namespace Umbraco.Web.PublishedCache #region Rebuild /// - /// Rebuilds caches. + /// Rebuilds internal caches (but does not reload). /// /// /// Forces the snapshot service to rebuild its internal caches. For instance, some caches diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index aebb58fa8d..023b8c999a 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -27,6 +27,7 @@ using Umbraco.Web.Cache; using Umbraco.Web.Install; using Umbraco.Web.PublishedCache.NuCache.DataSource; using Umbraco.Web.Routing; +using File = System.IO.File; namespace Umbraco.Web.PublishedCache.NuCache { @@ -142,31 +143,7 @@ namespace Umbraco.Web.PublishedCache.NuCache if (registered) { - string path; - var tempLocation = globalSettings.LocalTempStorageLocation; - switch (tempLocation) - { - case LocalTempStorage.AspNetTemp: - path = Path.Combine(HttpRuntime.CodegenDir, "UmbracoData", "NuCache"); - break; - case LocalTempStorage.EnvironmentTemp: - // TODO: why has this to be repeated everywhere?! - // include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back - // to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not - // utilizing an old path - assuming we cannot have SHA1 collisions on AppDomainAppId - var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash(); - path = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", appDomainHash, "NuCache"); - break; - //case LocalTempStorage.Default: - //case LocalTempStorage.Unknown: - default: - path = IOHelper.MapPath("~/App_Data/TEMP/NuCache"); - break; - } - - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - + var path = GetLocalFilesPath(); var localContentDbPath = Path.Combine(path, "NuCache.Content.db"); var localMediaDbPath = Path.Combine(path, "NuCache.Media.db"); _localDbExists = System.IO.File.Exists(localContentDbPath) && System.IO.File.Exists(localMediaDbPath); @@ -295,13 +272,69 @@ namespace Umbraco.Web.PublishedCache.NuCache #endregion + #region Local files + + private string GetLocalFilesPath() + { + string path; + var tempLocation = _globalSettings.LocalTempStorageLocation; + switch (tempLocation) + { + case LocalTempStorage.AspNetTemp: + path = Path.Combine(HttpRuntime.CodegenDir, "UmbracoData", "NuCache"); + break; + case LocalTempStorage.EnvironmentTemp: + // TODO: why has this to be repeated everywhere?! + // include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back + // to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not + // utilizing an old path - assuming we cannot have SHA1 collisions on AppDomainAppId + var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash(); + path = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", appDomainHash, "NuCache"); + break; + //case LocalTempStorage.Default: + //case LocalTempStorage.Unknown: + default: + path = IOHelper.MapPath("~/App_Data/TEMP/NuCache"); + break; + } + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + return path; + } + + private void DeleteLocalFilesForContent() + { + if (_isReady && _localContentDb != null) + throw new InvalidOperationException("Cannot delete local files while the cache uses them."); + + var path = GetLocalFilesPath(); + var localContentDbPath = Path.Combine(path, "NuCache.Content.db"); + if (File.Exists(localContentDbPath)) + File.Delete(localContentDbPath); + } + + private void DeleteLocalFilesForMedia() + { + if (_isReady && _localMediaDb != null) + throw new InvalidOperationException("Cannot delete local files while the cache uses them."); + + var path = GetLocalFilesPath(); + var localMediaDbPath = Path.Combine(path, "NuCache.Media.db"); + if (File.Exists(localMediaDbPath)) + File.Delete(localMediaDbPath); + } + + #endregion + #region Environment public override bool EnsureEnvironment(out IEnumerable errors) { // must have app_data and be able to write files into it - var ok = FilePermissionHelper.TryCreateDirectory(SystemDirectories.Data); - errors = ok ? Enumerable.Empty() : new[] { "NuCache local DB files." }; + var ok = FilePermissionHelper.TryCreateDirectory(GetLocalFilesPath()); + errors = ok ? Enumerable.Empty() : new[] { "NuCache local files." }; return ok; } @@ -560,10 +593,11 @@ namespace Umbraco.Web.PublishedCache.NuCache public override void Notify(ContentCacheRefresher.JsonPayload[] payloads, out bool draftChanged, out bool publishedChanged) { - // no cache, nothing we can do + // no cache, trash everything if (_isReady == false) { - draftChanged = publishedChanged = false; + DeleteLocalFilesForContent(); + draftChanged = publishedChanged = true; return; } @@ -655,10 +689,11 @@ namespace Umbraco.Web.PublishedCache.NuCache public override void Notify(MediaCacheRefresher.JsonPayload[] payloads, out bool anythingChanged) { - // no cache, nothing we can do + // no cache, trash everything if (_isReady == false) { - anythingChanged = false; + DeleteLocalFilesForMedia(); + anythingChanged = true; return; } @@ -1279,6 +1314,7 @@ namespace Umbraco.Web.PublishedCache.NuCache public override void Rebuild() { + _logger.Debug("Rebuilding..."); using (var scope = _scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped)) { scope.ReadLock(Constants.Locks.ContentTree);