Merge remote-tracking branch 'origin/v8/dev' into netcore/netcore

# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Runtime/MainDom.cs
#	src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs
#	src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml
#	src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml
#	src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml
This commit is contained in:
Bjarke Berg
2020-12-14 22:15:06 +01:00
7 changed files with 108 additions and 49 deletions

View File

@@ -157,7 +157,15 @@ namespace Umbraco.Core.Runtime
_logger.LogInformation("Acquiring.");
// Get the lock
var acquired = _mainDomLock.AcquireLockAsync(LockTimeoutMilliseconds).GetAwaiter().GetResult();
var acquired = false;
try
{
acquired = _mainDomLock.AcquireLockAsync(LockTimeoutMilliseconds).GetAwaiter().GetResult();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while acquiring");
}
if (!acquired)
{

View File

@@ -7,7 +7,7 @@ using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Umbraco.Core.Configuration;
using NPoco;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Hosting;
using Umbraco.Core.Persistence;
@@ -42,7 +42,7 @@ namespace Umbraco.Core.Runtime
loggerFactory,
globalSettings,
connectionStrings,
new Lazy<IMapperCollection>(() => new MapperCollection(Enumerable.Empty<BaseMapper>())),
new Lazy<IMapperCollection>(() => new Persistence.Mappers.MapperCollection(Enumerable.Empty<BaseMapper>())),
dbProviderFactoryCreator);
MainDomKey = MainDomKeyPrefix + "-" + (NetworkHelper.MachineName + MainDom.GetMainDomId(_hostingEnvironment)).GenerateHash<SHA1>();
@@ -57,7 +57,9 @@ namespace Umbraco.Core.Runtime
}
if (!(_dbFactory.SqlContext.SqlSyntax is SqlServerSyntaxProvider sqlServerSyntaxProvider))
{
throw new NotSupportedException("SqlMainDomLock is only supported for Sql Server");
}
_sqlServerSyntax = sqlServerSyntaxProvider;
@@ -65,11 +67,13 @@ namespace Umbraco.Core.Runtime
var tempId = Guid.NewGuid().ToString();
using var db = _dbFactory.CreateDatabase();
using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
IUmbracoDatabase db = null;
try
{
db = _dbFactory.CreateDatabase();
db.BeginTransaction(IsolationLevel.ReadCommitted);
try
{
// wait to get a write lock
@@ -110,7 +114,8 @@ namespace Umbraco.Core.Runtime
}
finally
{
transaction.Complete();
db?.CompleteTransaction();
db?.Dispose();
}
@@ -172,11 +177,11 @@ namespace Umbraco.Core.Runtime
return;
}
using var db = _dbFactory.CreateDatabase();
using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
IUmbracoDatabase db = null;
try
{
db = _dbFactory.CreateDatabase();
db.BeginTransaction(IsolationLevel.ReadCommitted);
// get a read lock
_sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom);
@@ -202,7 +207,8 @@ namespace Umbraco.Core.Runtime
}
finally
{
transaction.Complete();
db?.CompleteTransaction();
db?.Dispose();
}
}
@@ -221,34 +227,47 @@ namespace Umbraco.Core.Runtime
return Task.Run(() =>
{
using var db = _dbFactory.CreateDatabase();
var watch = new Stopwatch();
watch.Start();
while (true)
try
{
// poll very often, we need to take over as fast as we can
// local testing shows the actual query to be executed from client/server is approx 300ms but would change depending on environment/IO
Thread.Sleep(1000);
using var db = _dbFactory.CreateDatabase();
var acquired = TryAcquire(db, tempId, updatedTempId);
if (acquired.HasValue)
return acquired.Value;
if (watch.ElapsedMilliseconds >= millisecondsTimeout)
var watch = new Stopwatch();
watch.Start();
while (true)
{
return AcquireWhenMaxWaitTimeElapsed(db);
// poll very often, we need to take over as fast as we can
// local testing shows the actual query to be executed from client/server is approx 300ms but would change depending on environment/IO
Thread.Sleep(1000);
var acquired = TryAcquire(db, tempId, updatedTempId);
if (acquired.HasValue)
return acquired.Value;
if (watch.ElapsedMilliseconds >= millisecondsTimeout)
{
return AcquireWhenMaxWaitTimeElapsed(db);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred trying to acquire and waiting for existing SqlMainDomLock to shutdown");
return false;
}
}, _cancellationTokenSource.Token);
}
private bool? TryAcquire(IUmbracoDatabase db, string tempId, string updatedTempId)
{
using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
// Creates a separate transaction to the DB instance so we aren't allocating tons of new DB instances for each transaction
// since this is executed in a tight loop
ITransaction transaction = null;
try
{
transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
// get a read lock
_sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom);
@@ -294,7 +313,8 @@ namespace Umbraco.Core.Runtime
}
finally
{
transaction.Complete();
transaction?.Complete();
transaction?.Dispose();
}
return null; // continue
@@ -302,6 +322,9 @@ namespace Umbraco.Core.Runtime
private bool AcquireWhenMaxWaitTimeElapsed(IUmbracoDatabase db)
{
// Creates a separate transaction to the DB instance so we aren't allocating tons of new DB instances for each transaction
// since this is executed in a tight loop
// if the timeout has elapsed, it either means that the other main dom is taking too long to shutdown,
// or it could mean that the previous appdomain was terminated and didn't clear out the main dom SQL row
// and it's just been left as an orphan row.
@@ -311,10 +334,12 @@ namespace Umbraco.Core.Runtime
_logger.LogDebug("Timeout elapsed, assuming orphan row, acquiring MainDom.");
using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
ITransaction transaction = null;
try
{
transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
_sqlServerSyntax.WriteLock(db, Constants.Locks.MainDom);
// so now we update the row with our appdomain id
@@ -337,7 +362,8 @@ namespace Umbraco.Core.Runtime
}
finally
{
transaction.Complete();
transaction?.Complete();
transaction?.Dispose();
}
}
@@ -390,11 +416,12 @@ namespace Umbraco.Core.Runtime
if (_dbFactory.Configured)
{
using var db = _dbFactory.CreateDatabase();
using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
IUmbracoDatabase db = null;
try
{
db = _dbFactory.CreateDatabase();
db.BeginTransaction(IsolationLevel.ReadCommitted);
// get a write lock
_sqlServerSyntax.WriteLock(db, Constants.Locks.MainDom);
@@ -421,7 +448,15 @@ namespace Umbraco.Core.Runtime
}
finally
{
transaction.Complete();
try
{
db?.CompleteTransaction();
db?.Dispose();
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error during dispose when completing transaction.");
}
}
}
}

View File

@@ -239,9 +239,10 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
// Ask to re-enter preview mode?
const localizeVarsFallback = {
"returnToPreviewHeadline": "Preview content?",
"returnToPreviewDescription":"You have ended preview mode, do you want to continue previewing this content?",
"returnToPreviewButton":"Preview"
"returnToPreviewHeadline": "Preview website?",
"returnToPreviewDescription":"You have ended preview mode, do you want to enable it again to view the latest saved version of your website?",
"returnToPreviewAcceptButton":"Preview latest version",
"returnToPreviewDeclineButton":"View published version"
};
const umbLocalizedVars = Object.assign(localizeVarsFallback, $window.umbLocalizedVars);
@@ -344,10 +345,20 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
<div class="umbraco-preview-dialog__question">${umbLocalizedVars.returnToPreviewDescription}</div>`;
con.appendChild(modal);
var declineButton = document.createElement("button");
declineButton.type = "button";
declineButton.innerHTML = umbLocalizedVars.returnToPreviewDeclineButton;
declineButton.addEventListener("click", () => {
bodyEl.removeChild(fragment);
$scope.exitPreview();
hasPreviewDialog = false;
});
modal.appendChild(declineButton);
var continueButton = document.createElement("button");
continueButton.type = "button";
continueButton.className = "umbraco-preview-dialog__continue";
continueButton.innerHTML = umbLocalizedVars.returnToPreviewButton;
continueButton.innerHTML = umbLocalizedVars.returnToPreviewAcceptButton;
continueButton.addEventListener("click", () => {
bodyEl.removeChild(fragment);
reenterPreviewMode();

View File

@@ -28,7 +28,8 @@
var OpenWebsiteTitle = LocalizedTextService.Localize("preview", "openWebsiteTitle");
var returnToPreviewHeadline = LocalizedTextService.Localize("preview", "returnToPreviewHeadline");
var returnToPreviewDescription = LocalizedTextService.Localize("preview", "returnToPreviewDescription");
var returnToPreviewButton = LocalizedTextService.Localize("preview", "returnToPreviewButton");
var returnToPreviewAcceptButton = LocalizedTextService.Localize("preview", "returnToPreviewAcceptButton");
var returnToPreviewDeclineButton = LocalizedTextService.Localize("preview", "returnToPreviewDeclineButton");
}
<!DOCTYPE html>
<html lang="en">
@@ -44,7 +45,8 @@
window.umbLocalizedVars = {
'returnToPreviewHeadline': '@returnToPreviewHeadline',
'returnToPreviewDescription':'@returnToPreviewDescription',
'returnToPreviewButton':'@returnToPreviewButton'
'returnToPreviewAcceptButton':'@returnToPreviewAcceptButton',
'returnToPreviewDeclineButton':'@returnToPreviewDeclineButton'
};
</script>
</head>

View File

@@ -1439,7 +1439,7 @@ Mange hilsner fra Umbraco robotten
<key alias="elementDoesNotSupport">Dette benyttes ikke for en Element-type</key>
<key alias="propertyHasChanges">Du har lavet ændringer til denne egenskab. Er du sikker på at du vil kassere dem?</key>
<key alias="displaySettingsHeadline">Visning</key>
<key alias="displaySettingsLabelOnTop">Flyt label over editoren</key>
<key alias="displaySettingsLabelOnTop">Label hen over (fuld brede)</key>
</area>
<area alias="languages">
<key alias="addLanguage">Tilføj sprog</key>
@@ -1873,8 +1873,9 @@ Mange hilsner fra Umbraco robotten
<key alias="openWebsiteLabel">Vis i nyt vindue</key>
<key alias="openWebsiteTitle">Åben forhåndsvisning i nyt vindue</key>
<key alias="returnToPreviewHeadline">Forhåndsvisning af indholdet?</key>
<key alias="returnToPreviewDescription">Du har afslutet forhåndsvisning, vil du se dette indhold i forhåndsvisning?</key>
<key alias="returnToPreviewButton">Fortsæt</key>
<key alias="returnToPreviewDescription">Du har afslutet forhåndsvisning, vil du starte forhåndsvisning igen for at se seneste gemte version af indholdet?</key>
<key alias="returnToPreviewButton">Start forhåndsvisning</key>
<key alias="returnToPreviewDeclineButton">Se udgivet indhold</key>
<key alias="viewPublishedContentHeadline">Se udgivet indhold?</key>
<key alias="viewPublishedContentDescription">Du er i forhåndsvisning, vil du afslutte for at se den udgivet version?</key>
<key alias="viewPublishedContentAcceptButton">Se udgivet version</key>

View File

@@ -1699,7 +1699,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="elementDoesNotSupport">This is not applicable for an Element type</key>
<key alias="propertyHasChanges">You have made changes to this property. Are you sure you want to discard them?</key>
<key alias="displaySettingsHeadline">Appearance</key>
<key alias="displaySettingsLabelOnTop">Display label on top of editor.</key>
<key alias="displaySettingsLabelOnTop">Label above (full-width)</key>
</area>
<area alias="languages">
<key alias="addLanguage">Add language</key>
@@ -2536,9 +2536,10 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="endTitle">End preview mode</key>
<key alias="openWebsiteLabel">Preview website</key>
<key alias="openWebsiteTitle">Open website in preview mode</key>
<key alias="returnToPreviewHeadline">Preview content?</key>
<key alias="returnToPreviewDescription">You have ended preview mode, do you want to continue previewing this content?</key>
<key alias="returnToPreviewButton">Preview</key>
<key alias="returnToPreviewHeadline">Preview website?</key>
<key alias="returnToPreviewDescription">ou have ended preview mode, do you want to enable it again to view the latest saved version of your website?</key>
<key alias="returnToPreviewAcceptButton">Preview latest version</key>
<key alias="returnToPreviewDeclineButton">View published version</key>
<key alias="viewPublishedContentHeadline">View published version?</key>
<key alias="viewPublishedContentDescription">You are in Preview Mode, do you want exit in order to view the published version of your website?</key>
<key alias="viewPublishedContentAcceptButton">View published version</key>

View File

@@ -1717,7 +1717,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="elementDoesNotSupport">This is not applicable for an element type</key>
<key alias="propertyHasChanges">You have made changes to this property. Are you sure you want to discard them?</key>
<key alias="displaySettingsHeadline">Appearance</key>
<key alias="displaySettingsLabelOnTop">Display label on top of editor.</key>
<key alias="displaySettingsLabelOnTop">Label above (full-width)</key>
</area>
<area alias="languages">
<key alias="addLanguage">Add language</key>
@@ -2556,9 +2556,10 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="endTitle">End preview mode</key>
<key alias="openWebsiteLabel">Preview website</key>
<key alias="openWebsiteTitle">Open website in preview mode</key>
<key alias="returnToPreviewHeadline">Preview content?</key>
<key alias="returnToPreviewDescription">You have ended preview mode, do you want to continue previewing this content?</key>
<key alias="returnToPreviewButton">Preview</key>
<key alias="returnToPreviewHeadline">Preview website?</key>
<key alias="returnToPreviewDescription">ou have ended preview mode, do you want to enable it again to view the latest saved version of your website?</key>
<key alias="returnToPreviewAcceptButton">Preview latest version</key>
<key alias="returnToPreviewDeclineButton">View published version</key>
<key alias="viewPublishedContentHeadline">View published version?</key>
<key alias="viewPublishedContentDescription">You are in Preview Mode, do you want exit in order to view the published version of your website?</key>
<key alias="viewPublishedContentAcceptButton">View published version</key>