From 52740027391b973c4400898603855ea76d24d2b6 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 1 Feb 2021 12:41:18 +0100 Subject: [PATCH 1/2] Add the ability to change the SQL Write Lock TimeOut --- .../Configuration/GlobalSettings.cs | 23 +++++++++++++++++++ .../Configuration/IGlobalSettings.cs | 5 ++++ src/Umbraco.Core/Constants-AppSettings.cs | 8 +++++++ .../SqlSyntax/SqlCeSyntaxProvider.cs | 5 +++- .../SqlSyntax/SqlServerSyntaxProvider.cs | 5 +++- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 2c79c0008655..1d1ccaf7b4ad 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -391,5 +391,28 @@ public bool UseHttps } } } + + + /// + /// An int value representing the time in milliseconds to lock the database for a write operation + /// + /// + /// The default value is 1800 milliseconds + /// + /// The timeout in milliseconds. + public int SqlWriteLockTimeOut + { + get + { + try + { + return int.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.SqlWriteLockTimeOut]); + } + catch + { + return 1800; + } + } + } } } diff --git a/src/Umbraco.Core/Configuration/IGlobalSettings.cs b/src/Umbraco.Core/Configuration/IGlobalSettings.cs index fd5140042c72..483829f85ff3 100644 --- a/src/Umbraco.Core/Configuration/IGlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/IGlobalSettings.cs @@ -72,5 +72,10 @@ public interface IGlobalSettings /// Gets the location of temporary files. /// string LocalTempPath { get; } + + /// + /// Gets the write lock timeout. + /// + int SqlWriteLockTimeOut { get; } } } diff --git a/src/Umbraco.Core/Constants-AppSettings.cs b/src/Umbraco.Core/Constants-AppSettings.cs index cb3b0d48d085..0182034011bb 100644 --- a/src/Umbraco.Core/Constants-AppSettings.cs +++ b/src/Umbraco.Core/Constants-AppSettings.cs @@ -140,6 +140,14 @@ public static class Debug /// public const string DatabaseFactoryServerVersion = "Umbraco.Core.Debug.DatabaseFactoryServerVersion"; } + + /// + /// An int value representing the time in milliseconds to lock the database for a write operation + /// + /// + /// The default value is 1800 milliseconds + /// + public const string SqlWriteLockTimeOut = "Umbraco.Core.SqlWriteLockTimeOut"; } } } diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs index d37905f221bd..046f54405a57 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Configuration; using System.Data; using System.Data.SqlServerCe; using System.Linq; using NPoco; +using Umbraco.Core.Composing; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -163,7 +165,8 @@ public override void WriteLock(IDatabase db, params int[] lockIds) if (db.Transaction.IsolationLevel < IsolationLevel.RepeatableRead) throw new InvalidOperationException("A transaction with minimum RepeatableRead isolation level is required."); - db.Execute(@"SET LOCK_TIMEOUT 1800;"); + var timeOut = Current.Configs.Global().SqlWriteLockTimeOut; + db.Execute(@"SET LOCK_TIMEOUT " + timeOut + ";"); // *not* using a unique 'WHERE IN' query here because the *order* of lockIds is important to avoid deadlocks foreach (var lockId in lockIds) { diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index 9d33a2169ca1..3fc5e36f6e0b 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.Configuration; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; using NPoco; +using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Scoping; @@ -254,7 +256,8 @@ public override bool DoesTableExist(IDatabase db, string tableName) public override void WriteLock(IDatabase db, params int[] lockIds) { - WriteLock(db, TimeSpan.FromMilliseconds(1800), lockIds); + var timeOut = Current.Configs.Global().SqlWriteLockTimeOut; + WriteLock(db, TimeSpan.FromMilliseconds(timeOut), lockIds); } public void WriteLock(IDatabase db, TimeSpan timeout, params int[] lockIds) From 7e213f96d406a64dbde7266343ddaf4d6cf09159 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 2 Feb 2021 10:20:26 +0100 Subject: [PATCH 2/2] Needed to add a default setting to to the settings for tests --- src/Umbraco.Tests/TestHelpers/SettingsForTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs index 572d572ab774..1121a4882328 100644 --- a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs +++ b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs @@ -23,7 +23,8 @@ public static IGlobalSettings GenerateMockGlobalSettings() settings.LocalTempStorageLocation == LocalTempStorage.Default && settings.LocalTempPath == IOHelper.MapPath("~/App_Data/TEMP") && settings.ReservedPaths == (GlobalSettings.StaticReservedPaths + "~/umbraco") && - settings.ReservedUrls == GlobalSettings.StaticReservedUrls); + settings.ReservedUrls == GlobalSettings.StaticReservedUrls && + settings.SqlWriteLockTimeOut == 1800); return config; }